table_units.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2018, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 #ifndef O2SCL_TABLE_UNITS_H
24 #define O2SCL_TABLE_UNITS_H
25 
26 /** \file table_units.h
27  \brief File defining \ref o2scl::table_units
28 */
29 
30 #include <o2scl/table.h>
31 #include <o2scl/lib_settings.h>
32 
33 // For the MPI table send and receive functions below
34 #ifdef O2SCL_MPI
35 #include <mpi.h>
36 #endif
37 
38 #ifndef DOXYGEN_NO_O2NS
39 
40 // Forward definition of the table_units class for HDF I/O
41 namespace o2scl {
42  template<class vec_t> class table_units;
43 }
44 
45 // Forward definition of HDF I/O to extend friendship in table_units
46 namespace o2scl_hdf {
47 
48  class hdf_file;
49 
50  template<class vec_t>
51  void hdf_input(hdf_file &hf, o2scl::table_units<vec_t> &t,
52  std::string name);
53 
54  void hdf_output
55  (hdf_file &hf,
56  o2scl::table_units<std::vector<double> > &t,
57  std::string name);
58 
59  template<class vec_t>
60  void hdf_input_data(hdf_file &hf, o2scl::table_units<vec_t> &t);
61 
62  void hdf_output_data
63  (hdf_file &hf,
64  o2scl::table_units<std::vector<double> > &t);
65 
66 }
67 
68 #endif
69 
70 #ifndef DOXYGEN_NO_O2NS
71 namespace o2scl {
72 #endif
73 
74  /** \brief Data \table class with units
75 
76  \future The unit conversion object is now always a pointer to
77  the global conversion object. This could be modified, so that
78  each table can have it's own, but this might require HDF output
79  of unit conversion objects.
80 
81  \future Make table methods virtual? (not necessary yet since
82  delete_column() isn't referred to internally)
83  */
84  template<class vec_t=std::vector<double> >
85  class table_units : public table<vec_t> {
86 
87  public:
88 
89 #ifdef O2SCL_NEVER_DEFINED
90  }{
91 #endif
92 
93  /** \brief Create a new table_units with space for nlines<=cmaxlines.
94  */
95  table_units(int cmaxlines=0) : table<vec_t>(cmaxlines) {
97  }
98 
99  virtual ~table_units() {
100  utree.clear();
101  }
102 
103  /// \name Copy constructors
104  //@{
105  /// Copy with constructor from \ref table_units
106  table_units(const table_units &t) : table<vec_t>(t.get_nlines()) {
107 
108  // Copy constants
109  this->constants=t.constants;
110 
111  // Copy interpolation type
112  this->itype=t.get_interp_type();
113 
114  // Copy the columns and data
115  this->nlines=t.get_nlines();
116  this->maxlines=this->nlines;
117  for(size_t i=0;i<t.get_ncolumns();i++) {
118 
119  // Column name
120  std::string cname=t.get_column_name(i);
121 
122  // Insert column into tree
123  typename table<vec_t>::col s;
124  s.dat.resize(this->nlines);
125  s.index=this->atree.size();
126  this->atree.insert(make_pair(cname,s));
127 
128  // Insert in iterator index
129  typename table<vec_t>::aiter it=this->atree.find(cname);
130  this->alist.push_back(it);
131 
132  // Insert in unit list
133  utree.insert(make_pair(cname,t.get_unit(cname)));
134 
135  // Fill the data
136  for(size_t j=0;j<t.get_nlines();j++) {
137  it->second.dat[j]=t.get(cname,j);
138  }
139 
140  }
141 
142  this->intp_set=false;
144 
145  return;
146  }
147 
148  /// Copy with constructor from \ref table
149  table_units(const table<vec_t> &t) : table<vec_t>(t.get_nlines()) {
150 
151  // Copy constants
152  size_t nc=t.get_nconsts();
153  for(size_t i=0;i<nc;i++) {
154  std::string name;
155  double val;
156  t.get_constant(i,name,val);
157  this->constants.insert(make_pair(name,val));
158  }
159 
160  // Copy interpolation type
161  this->itype=t.get_interp_type();
162 
163  // Copy the columns and data
164  this->nlines=t.get_nlines();
165  this->maxlines=this->nlines;
166  for(size_t i=0;i<t.get_ncolumns();i++) {
167 
168  // Column name
169  std::string cname=t.get_column_name(i);
170 
171  // Insert column into tree
172  typename table<vec_t>::col s;
173  s.dat.resize(this->nlines);
174  s.index=this->atree.size();
175  this->atree.insert(make_pair(cname,s));
176 
177  // Insert in iterator index
178  typename table<vec_t>::aiter it=this->atree.find(cname);
179  this->alist.push_back(it);
180 
181  // Fill the data
182  for(size_t j=0;j<t.get_nlines();j++) {
183  it->second.dat[j]=t.get(cname,j);
184  }
185 
186  }
187 
188  this->intp_set=false;
190 
191  return;
192 
193  }
194 
195  /// Copy with <tt>operator=</tt> from \ref table_units
197 
198  if (this!=&t) {
199 
200  this->clear_table();
201  this->constants.clear();
202  utree.clear();
203 
204  // Copy constants
205  this->constants=t.constants;
206 
207  // Copy interpolation type
208  this->itype=t.get_interp_type();
209 
210  // Copy the columns and data
211  this->nlines=t.get_nlines();
212  this->maxlines=this->nlines;
213  for(size_t i=0;i<t.get_ncolumns();i++) {
214 
215  // Column name
216  std::string cname=t.get_column_name(i);
217 
218  // Insert column into tree
219  typename table<vec_t>::col s;
220  s.dat.resize(this->nlines);
221  s.index=this->atree.size();
222  this->atree.insert(make_pair(cname,s));
223 
224  // Insert in iterator index
225  typename table<vec_t>::aiter it=this->atree.find(cname);
226  this->alist.push_back(it);
227 
228  // Insert in unit list
229  utree.insert(make_pair(cname,t.get_unit(cname)));
230 
231  // Fill the data
232  for(size_t j=0;j<t.get_nlines();j++) {
233  it->second.dat[j]=t.get(cname,j);
234  }
235 
236  }
237 
238  if (this->intp_set) {
239  this->intp_set=false;
240  delete this->si;
241  }
242 
244 
245  }
246 
247  return *this;
248  }
249 
250  /// Copy with <tt>operator=</tt> from \ref table
252 
253  if (this!=&t) {
254 
255  this->clear_table();
256  this->constants.clear();
257  utree.clear();
258 
259  // Copy constants
260  size_t nc=t.get_nconsts();
261  for(size_t i=0;i<nc;i++) {
262  std::string name;
263  double val;
264  t.get_constant(i,name,val);
265  this->constants.insert(make_pair(name,val));
266  }
267 
268  // Copy interpolation type
269  this->itype=t.get_interp_type();
270 
271  // Copy the columns and data
272  this->nlines=t.get_nlines();
273  this->maxlines=this->nlines;
274  for(size_t i=0;i<t.get_ncolumns();i++) {
275 
276  // Column name
277  std::string cname=t.get_column_name(i);
278 
279  // Insert column into tree
280  typename table<vec_t>::col s;
281  s.dat=new vec_t(this->nlines);
282  s.index=this->atree.size();
283  this->atree.insert(make_pair(cname,s));
284 
285  // Insert in iterator index
286  typename table<vec_t>::aiter it=this->atree.find(cname);
287  this->alist.push_back(it);
288 
289  // Fill the data
290  for(size_t j=0;j<t.get_nlines();j++) {
291  (*it->second.dat)[j]=t.get(cname,j);
292  }
293 
294  }
295 
296  if (this->intp_set) {
297  this->intp_set=false;
298  delete this->si;
299  }
300 
302 
303  }
304 
305  return *this;
306  }
307  //@}
308 
309  /** \brief Copy all rows matching a particular condition to
310  a new table
311 
312  This function begins by ensuring that all columns in the
313  current table are present in \c dest, creating new columns
314  (and copying their units) in \c dest if necessary. It then
315  copies all rows where \c func evaluates to a number greater
316  than 0.5 to table \c dest by adding rows at the end of the
317  table.
318  */
319  template<class vec2_t>
320  void copy_rows(std::string func, table_units<vec2_t> &dest) {
321 
322  // Set up columns
323  for(size_t i=0;i<this->get_ncolumns();i++) {
324  std::string cname=this->get_column_name(i);
325  if (dest.is_column(cname)==false) {
326  dest.new_column(cname);
327  }
328  dest.set_unit(cname,get_unit(cname));
329  }
330 
331  size_t new_lines=dest.get_nlines();
332  for(size_t i=0;i<this->get_nlines();i++) {
333  double val=this->row_function(func,i);
334  if (val>0.5) {
335  this->set_nlines_auto(new_lines+1);
336  for(size_t j=0;j<this->get_ncolumns();j++) {
337  std::string cname=this->get_column_name(j);
338  dest.set(cname,new_lines,this->get(cname,i));
339  }
340  new_lines++;
341  }
342  }
343 
344  return;
345  }
346 
347  /// \name Unit manipulation
348  //@{
349  /// Get the unit for column \c scol
350  std::string get_unit(std::string scol) const {
351 
352  uciter it=utree.find(scol);
353  if (it==utree.end()) {
354  // Not found in unit entry, look for column of data
355  typename table<vec_t>::aciter at=this->atree.find(scol);
356  if (at==this->atree.end()) {
357  O2SCL_ERR((((std::string)"Column '")+scol+
358  "' not found in table_units::get_unit().").c_str(),
359  exc_enotfound);
360  } else {
361  return "";
362  }
363  }
364 
365  return it->second;
366  }
367 
368  /** \brief Get the unit for column with index i
369 
370  \future Is there a way to make this function have O(1) time
371  rather than searching?
372  */
373  std::string get_unit(size_t i) const {
374  return get_unit(this->get_column_name(i));
375  }
376 
377  /// Remove the unit for column \c scol
378  void remove_unit(std::string scol) {
379 
380  uiter it=utree.find(scol);
381  if (it==utree.end()) {
382  O2SCL_ERR((((std::string)"Column '")+scol+
383  "' not found in table_units::get_unit().").c_str(),
384  exc_enotfound);
385  }
386 
387  if (utree.size()==0) {
388  O2SCL_ERR("No units specified in table_units::remove_unit().",
389  exc_efailed);
390  }
391 
392  utree.erase(it);
393  return;
394  }
395 
396  /// Set the unit for column \c scol to \c unit
397  void set_unit(std::string scol, std::string unit) {
398 
399  uiter it=utree.find(scol);
400  if (it==utree.end()) {
401  typename table<vec_t>::aiter at=this->atree.find(scol);
402  if (at==this->atree.end()) {
403  O2SCL_ERR((((std::string)"Column '")+scol+
404  "' not found in table_units::set_unit().").c_str(),
405  exc_enotfound);
406  }
407  utree.insert(make_pair(scol,unit));
408  } else {
409  it->second=unit;
410  }
411 
412  return;
413  }
414 
415  /// Convert the units of column \c scol to \c unit
416  int convert_to_unit(std::string scol, std::string unit,
417  bool err_on_fail=true) {
418 
419  // Find unit entry
420  uiter it=utree.find(scol);
421  if (it==utree.end()) {
422  if (err_on_fail) {
423  O2SCL_ERR((((std::string)"Column '")+scol+"' not found in "+
424  "table_units::convert_to_unit().").c_str(),
425  exc_enotfound);
426  } else {
427  return exc_enotfound;
428  }
429  };
430 
431  // If the units are equal, just do nothing
432  if (it->second==unit) return success;
433 
434  // Find column of data
435  typename table<vec_t>::aiter at=this->atree.find(scol);
436  if (at==this->atree.end()) {
437  if (err_on_fail) {
438  O2SCL_ERR((((std::string)"Column '")+scol+"' not found in "+
439  "table_units::convert_to_unit().").c_str(),
440  exc_enotfound);
441  } else {
442  return exc_enotfound;
443  }
444  };
445 
446  // Perform conversion
447  vec_t &vec=at->second.dat;
448  double conv=cup->convert(it->second,unit,1.0);
449 
450  for(size_t i=0;i<this->get_nlines();i++) {
451  vec[i]*=conv;
452  }
453 
454  // Set new unit entry
455  it->second=unit;
456 
457  return success;
458  }
459 
460  /// Return the number of columns with units
461  size_t get_nunits() {
462  return utree.size();
463  }
464 
465  /*
466  // Get the conversion factor from \c old_unit to \c new_unit
467  double get_conv(std::string old_unit, std::string new_unit);
468 
469  // Set the convert units object
470  void set_convert(convert_units &c) {
471  cup=&c;
472  return;
473  }
474 
475  // Show the unit cache as given by \ref convert_units::print_cache()
476  void show_units() {
477  cup->print_cache();
478  return;
479  }
480 
481  // The default object for unit conversions
482  convert_units def_cu;
483  */
484  //@}
485 
486  /// \name Virtual functions from \ref table
487  //@{
488  /// Delete column named \c scol
489  virtual void delete_column(std::string scol) {
490 
491  // Find the tree iterator for the element we want to erase
492  typename table<vec_t>::aiter it=this->atree.find(scol);
493  if (it==this->atree.end()) {
494  O2SCL_ERR((((std::string)"Column '")+scol+
495  " not found in table_units::delete_column().").c_str(),
496  exc_enotfound);
497  return;
498  }
499 
500  // Remove the unit for the specified column
501  if (get_unit(scol).length()>0) remove_unit(scol);
502 
503  // Find the corresponding list iterator
504  typename table<vec_t>::aviter vit=this->alist.begin();
505  vit+=it->second.index;
506 
507  // Find the last element in the list and it's corresponding table
508  // entry. Change it's index to the index of the column to be
509  // deleted.
510  this->alist[this->alist.size()-1]->second.index=it->second.index;
511 
512  // Erase the elements from the list and the tree
513  this->atree.erase(it);
514  this->alist.erase(vit);
515 
516  // Reset the list to reflect the proper iterators
517  this->reset_list();
518 
519  return;
520  }
521 
522  /** \brief Rename column named \c src to \c dest
523  \f$ {\cal O}(C) \f$
524  */
525  virtual void rename_column(std::string src, std::string dest) {
526  std::string unit=get_unit(src);
527  table<vec_t>::rename_column(src,dest);
528  set_unit(dest,unit);
529  return;
530  }
531 
532  /// Output a summary of the information stored
533  virtual void summary(std::ostream *out, size_t ncol=79) const {
534 
535  if (this->constants.size()==1) {
536  (*out) << "1 constant:" << std::endl;
537  } else {
538  (*out) << this->constants.size() << " constants:" << std::endl;
539  }
540  std::map<std::string,double>::const_iterator mit;
541  for(mit=this->constants.begin();mit!=this->constants.end();mit++) {
542  (*out) << mit->first << " " << mit->second << std::endl;
543  }
544 
545  // Output number of columns and preprend column numbers
546  size_t nh=this->get_ncolumns(), nh2;
547 
548  if (nh==0) {
549 
550  (*out) << "No columns." << std::endl;
551 
552  } else {
553 
554  if (nh==1) {
555  (*out) << "1 column: " << std::endl;
556  } else {
557  (*out) << nh << " columns: " << std::endl;
558  }
559  std::string *h=new std::string[nh];
560  for(size_t i=0;i<nh;i++) {
561  h[i]=szttos(i)+". "+this->get_column_name(i)+" ["+
562  get_unit(this->get_column_name(i))+"]";
563  }
564 
565  std::vector<std::string> h2;
566  // Convert to string with width 'ncol'
567  screenify(nh,h,h2,ncol);
568  nh2=h2.size();
569 
570  // Output column names
571  for(size_t i=0;i<nh2;i++) {
572  (*out) << h2[i] << std::endl;
573  }
574 
575  delete[] h;
576 
577  }
578 
579  if (this->get_nlines()==0) {
580  (*out) << "No lines of data." << std::endl;
581  } else if (this->get_nlines()==1) {
582  (*out) << "One line of data." << std::endl;
583  } else {
584  (*out) << this->get_nlines() << " lines of data." << std::endl;
585  }
586 
587  return;
588  }
589  //@}
590 
591  /// Return the type, \c "table_units".
592  virtual const char *type() { return "table_units"; }
593 
594  /** \brief Copy data from column named \c src to column named \c
595  dest, creating a new column if necessary \f$ {\cal O}(R
596  \log(C)) \f$
597 
598  This function also sets the units of column \c dest to be the
599  same as that in \c src, even if the column named \c dest
600  already exists and previously had different units.
601  */
602  virtual void copy_column(std::string src, std::string dest) {
603  if (!this->is_column(dest)) this->new_column(dest);
604 
605  typedef typename std::map<std::string,
606  typename table<vec_t>::col,std::greater<std::string> >::iterator aiter;
607 
608  aiter its=this->atree.find(src);
609  if (its==this->atree.end()) {
610  O2SCL_ERR((((std::string)"Column '")+src+
611  " not found in table_units::copy_column().").c_str(),
612  exc_enotfound);
613  return;
614  }
615  aiter itd=this->atree.find(dest);
616  if (itd==this->atree.end()) {
617  O2SCL_ERR((((std::string)"Destination column '")+dest+
618  " not found in table_units::copy_column().").c_str(),
619  exc_esanity);
620  return;
621  }
622  this->set_unit(dest,this->get_unit(src));
623  for(size_t i=0;i<this->nlines;i++) {
624  itd->second.dat[i]=its->second.dat[i];
625  }
626  return;
627  }
628 
629  /// Clear the current table and read from a generic data file
630  virtual int read_generic(std::istream &fin, int verbose=0) {
631 
632  double data;
633  std::string line;
634  std::string stemp;
635  std::istringstream *is;
636 
637  // Read first line and into list
638  std::vector<std::string> onames, nnames;
639  getline(fin,line);
640  is=new std::istringstream(line);
641  while ((*is) >> stemp) {
642  onames.push_back(stemp);
643  if (verbose>2) {
644  std::cout << "Read possible column name: " << stemp << std::endl;
645  }
646  }
647  delete is;
648 
649  // Count number of likely numbers in the first row
650  size_t n_nums=0;
651  for(size_t i=0;i<onames.size();i++) {
652  if (is_number(onames[i])) n_nums++;
653  }
654 
655  int irow=0;
656 
657  if (n_nums==onames.size()) {
658 
659  if (verbose>0) {
660  std::cout << "First row looks like it contains numerical values."
661  << std::endl;
662  std::cout << "Creating generic column names: ";
663  }
664 
665  for(size_t i=0;i<onames.size();i++) {
666  nnames.push_back(((std::string)"c")+szttos(i+1));
667  if (verbose>0) std::cout << nnames[i] << " ";
668 
669  }
670  if (verbose>0) std::cout << std::endl;
671 
672  // Make columns
673  for(size_t i=0;i<nnames.size();i++) {
674  this->new_column(nnames[i]);
675  }
676 
677  // Add first row of data
678  for(size_t i=0;i<onames.size();i++) {
679  this->set(i,irow,o2scl::stod(onames[i]));
680  }
681  irow++;
682 
683  } else {
684 
685  // Ensure good column names
686  for(size_t i=0;i<onames.size();i++) {
687  std::string temps=onames[i];
688  this->make_fp_varname(temps);
689  this->make_unique_name(temps,nnames);
690  nnames.push_back(temps);
691  if (temps!=onames[i] && verbose>0) {
692  std::cout << "Converted column named '" << onames[i] << "' to '"
693  << temps << "'." << std::endl;
694  }
695  }
696 
697  // Make columns
698  for(size_t i=0;i<nnames.size();i++) {
699  this->new_column(nnames[i]);
700  }
701 
702  // Read another line, and see if it looks like units
703  std::vector<std::string> units;
704  getline(fin,line);
705  is=new std::istringstream(line);
706  int num_units=0;
707  while ((*is) >> stemp) {
708  units.push_back(stemp);
709  if (stemp[0]=='[') num_units++;
710  if (verbose>2) {
711  std::cout << "Read word in second row: " << stemp << std::endl;
712  }
713  }
714  delete is;
715 
716  if (units.size()!=nnames.size()) {
717  std::cout << "Second row appears not to have same number of "
718  << "entries as the first." << std::endl;
719  std::cout << "Aborting." << std::endl;
720  return -1;
721  }
722 
723  if (num_units==((int)units.size()) || num_units>2) {
724  if (verbose>2) {
725  std::cout << "Looks like second row contains units." << std::endl;
726  }
727  for(size_t i=0;i<units.size();i++) {
728  // Remove brackets
729  stemp=units[i];
730  if (stemp[0]=='[') stemp=stemp.substr(1,stemp.length()-1);
731  if (stemp[stemp.length()-1]==']') {
732  stemp=stemp.substr(0,stemp.length()-1);
733  }
734  // Set the units
735  set_unit(nnames[i],stemp);
736  if (verbose>2) {
737  std::cout << "Name,unit: " << nnames[i] << " [" << stemp << "]"
738  << std::endl;
739  }
740  }
741 
742  } else {
743 
744  // Otherwise, assume this is a row of data
745  for(size_t i=0;i<units.size();i++) {
746  this->set(i,0,o2scl::stod(units[i]));
747  }
748  irow++;
749 
750  }
751 
752  }
753 
754  // Read remaining rows
755  while ((fin) >> data) {
756  this->set(0,irow,data);
757  for(size_t i=1;i<this->get_ncolumns();i++) {
758  (fin) >> data;
759  this->set(i,irow,data);
760  }
761  irow++;
762  }
763 
764  return 0;
765  }
766 
767  /** \brief Insert columns from a source table into the new
768  table by interpolation (or extrapolation)
769  */
770  template<class vec2_t>
771  void insert_table(table_units<vec2_t> &source, std::string src_index,
772  bool allow_extrap=true, std::string dest_index="") {
773 
774  if (dest_index=="") dest_index=src_index;
775 
776  // Find limits to avoid extrapolation if necessary
777  double min=source.min(src_index);
778  double max=source.max(src_index);
779  if (allow_extrap==false) {
780  if (!std::isfinite(min) || !std::isfinite(max)) {
781  O2SCL_ERR2("Minimum or maximum of source index not finite ",
782  "in table_units::insert_table().",exc_einval);
783  }
784  }
785 
786  // Create list of columns to interpolate
787  std::vector<std::string> col_list;
788  for(size_t i=0;i<source.get_ncolumns();i++) {
789  std::string col=source.get_column_name(i);
790  if (col!=src_index && col!=dest_index &&
791  this->is_column(col)==false) {
792  col_list.push_back(col);
793  }
794  }
795 
796  // Create new columns and perform interpolation
797  for(size_t i=0;i<col_list.size();i++) {
798  this->new_column(col_list[i]);
799  set_unit(col_list[i],source.get_unit(col_list[i]));
800  for(size_t j=0;j<this->get_nlines();j++) {
801  double val=this->get(dest_index,j);
802  if (allow_extrap || (val>=min && val<=max)) {
803  this->set(col_list[i],j,source.interp(src_index,val,col_list[i]));
804  }
805  }
806  }
807 
808  return;
809  }
810 
811  // ---------
812  // Allow HDF I/O functions to access table_units data
813  friend void o2scl_hdf::hdf_output
814  (o2scl_hdf::hdf_file &hf, table_units<> &t, std::string name);
815 
816  template<class vecf_t> friend void o2scl_hdf::hdf_input
817  (o2scl_hdf::hdf_file &hf, table_units<vecf_t> &t, std::string name);
818 
819  friend void o2scl_hdf::hdf_output_data
821 
822  template<class vecf_t> friend void o2scl_hdf::hdf_input_data
824 
825  // ---------
826 
827 #ifndef DOXYGEN_INTERNAL
828 
829  protected:
830 
831 
832  /// The pointer to the convert units object
834 
835  /// \name Unit map iterator types
836  //@{
837  typedef std::map<std::string,std::string,
838  std::greater<std::string> >::iterator uiter;
839  typedef std::map<std::string,std::string,
840  std::greater<std::string> >::const_iterator uciter;
841  //@}
842 
843  /// Unit map
844  std::map<std::string,std::string,std::greater<std::string> > utree;
845 
846 #endif
847 
848  };
849 
850 #ifdef O2SCL_MPI
851 
852  /** \brief Send a \ref o2scl::table_units object to
853  MPI rank \c dest_rank
854  */
855  template<class vec_t>
856  void o2scl_table_mpi_send(o2scl::table_units<vec_t> &t, size_t dest_rank) {
857 
858  int tag;
859  int ibuffer;
860  std::vector<double> dbuffer;
861  std::string cbuffer;
862 
863  // --------------------------------------------------------------
864  // Constant names and values
865 
866  for(size_t i=0;i<t.get_nconsts();i++) {
867  std::string name;
868  double val;
869  t.get_constant(i,name,val);
870  cbuffer+=name;
871  if (i<t.get_nconsts()-1) {
872  cbuffer+=' ';
873  }
874  dbuffer.push_back(val);
875  }
876 
877  ibuffer=cbuffer.length();
878 
879  tag=0;
880  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
881  tag,MPI_COMM_WORLD);
882  tag=1;
883  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
884  tag,MPI_COMM_WORLD);
885  tag=2;
886  MPI_Send(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,dest_rank,
887  tag,MPI_COMM_WORLD);
888  cbuffer.clear();
889  dbuffer.clear();
890 
891  // --------------------------------------------------------------
892  // Column names
893 
894  for(size_t i=0;i<t.get_ncolumns();i++) {
895  std::string name=t.get_column_name(i);
896  cbuffer+=name;
897  if (i<t.get_ncolumns()-1) {
898  cbuffer+=' ';
899  }
900  }
901 
902  ibuffer=cbuffer.length();
903  tag=3;
904  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
905  tag,MPI_COMM_WORLD);
906  tag=4;
907  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
908  tag,MPI_COMM_WORLD);
909  cbuffer.clear();
910 
911  // --------------------------------------------------------------
912  // Column units
913 
914  for(size_t i=0;i<t.get_ncolumns();i++) {
915  std::string unit=t.get_unit(t.get_column_name(i));
916  cbuffer+=unit;
917  if (i<t.get_ncolumns()-1) {
918  cbuffer+=' ';
919  }
920  }
921 
922  ibuffer=cbuffer.length();
923  tag=5;
924  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
925  tag,MPI_COMM_WORLD);
926  tag=6;
927  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
928  tag,MPI_COMM_WORLD);
929  cbuffer.clear();
930 
931  // --------------------------------------------------------------
932  // Interpolation type
933 
934  tag=7;
935  ibuffer=t.get_interp_type();
936  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
937  tag,MPI_COMM_WORLD);
938 
939  // --------------------------------------------------------------
940  // Column data
941 
942  ibuffer=t.get_nlines();
943  tag=8;
944  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
945  tag,MPI_COMM_WORLD);
946 
947  for(size_t i=0;i<t.get_ncolumns();i++) {
948  tag++;
949  MPI_Send(&(t[i][0]),t.get_nlines(),MPI_DOUBLE,dest_rank,
950  tag,MPI_COMM_WORLD);
951  }
952 
953  return;
954  }
955 
956  /** \brief Receive a \ref o2scl::table_units object from
957  MPI rank \c src_rank
958  */
959  template<class vec_t>
960  void o2scl_table_mpi_recv(size_t src_rank,
962  int tag;
963  int ibuffer;
964  // Not std::string because we need to guarantee contiguous storage?!
965  std::vector<char> cbuffer;
966  std::vector<double> dbuffer;
967 
968  std::vector<std::string> names;
969  std::string stemp;
970 
971  // --------------------------------------------------------------
972  // Constants
973 
974  // Names
975  tag=0;
976  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
977  MPI_STATUS_IGNORE);
978  cbuffer.resize(ibuffer);
979  tag=1;
980  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
981  MPI_STATUS_IGNORE);
982 
983  // Parse into std::vector<string>
984  for(size_t i=0;i<cbuffer.size();i++) {
985  if (cbuffer[i]!=' ') {
986  stemp+=cbuffer[i];
987  } else {
988  if (stemp.size()>0) {
989  names.push_back(stemp);
990  stemp="";
991  }
992  }
993  }
994  if (stemp.size()>0) {
995  names.push_back(stemp);
996  }
997  stemp="";
998 
999  // Load values
1000  dbuffer.resize(names.size());
1001 
1002  tag=2;
1003  MPI_Recv(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,
1004  src_rank,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
1005 
1006  // Set constants
1007  for(size_t i=0;i<names.size();i++) {
1008  t.add_constant(names[i],dbuffer[i]);
1009  }
1010  names.clear();
1011  dbuffer.clear();
1012 
1013  // --------------------------------------------------------------
1014  // Column names
1015 
1016  tag=3;
1017  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1018  MPI_STATUS_IGNORE);
1019  cbuffer.resize(ibuffer);
1020  tag=4;
1021  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1022  MPI_STATUS_IGNORE);
1023 
1024  // Parse into std::vector<string>
1025  for(size_t i=0;i<cbuffer.size();i++) {
1026  if (cbuffer[i]!=' ') {
1027  stemp+=cbuffer[i];
1028  } else {
1029  if (stemp.size()>0) {
1030  names.push_back(stemp);
1031  stemp="";
1032  }
1033  }
1034  }
1035  if (stemp.size()>0) {
1036  names.push_back(stemp);
1037  }
1038  stemp="";
1039 
1040  for(size_t i=0;i<names.size();i++) {
1041  t.new_column(names[i]);
1042  }
1043  names.clear();
1044 
1045  // --------------------------------------------------------------
1046  // Column units
1047 
1048  tag=5;
1049  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1050  MPI_STATUS_IGNORE);
1051  cbuffer.resize(ibuffer);
1052  tag=6;
1053  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1054  MPI_STATUS_IGNORE);
1055 
1056  // Parse into std::vector<string>
1057  for(size_t i=0;i<cbuffer.size();i++) {
1058  if (cbuffer[i]!=' ') {
1059  stemp+=cbuffer[i];
1060  } else {
1061  if (stemp.size()>0) {
1062  names.push_back(stemp);
1063  stemp="";
1064  }
1065  }
1066  }
1067  if (stemp.size()>0) {
1068  names.push_back(stemp);
1069  }
1070  stemp="";
1071 
1072  for(size_t i=0;i<names.size();i++) {
1073  t.set_unit(t.get_column_name(i),names[i]);
1074  }
1075  names.clear();
1076 
1077  // --------------------------------------------------------------
1078  // Column data
1079 
1080  tag=7;
1081  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1082  MPI_STATUS_IGNORE);
1083  t.set_interp_type(ibuffer);
1084 
1085  // --------------------------------------------------------------
1086  // Column data
1087 
1088  tag=8;
1089  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1090  MPI_STATUS_IGNORE);
1091  t.set_nlines(ibuffer);
1092 
1093  for(size_t i=0;i<t.get_ncolumns();i++) {
1094  tag++;
1095  std::vector<double> v(t.get_maxlines());
1096  MPI_Recv(&(v[0]),ibuffer,MPI_DOUBLE,src_rank,
1097  tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
1099  }
1100 
1101  return;
1102  }
1103 
1104 #endif
1105 
1106 #ifndef DOXYGEN_NO_O2NS
1107 }
1108 #endif
1109 
1110 #endif
table_units(int cmaxlines=0)
Create a new table_units with space for nlines<=cmaxlines.
Definition: table_units.h:95
double max(std::string scol) const
Return column maximum. Makes no assumptions about ordering, .
Definition: table.h:2001
double get(std::string scol, size_t row) const
Get value from row row of column named col. .
Definition: table.h:422
const double cup
cm^3
Definition: constants.h:187
void remove_unit(std::string scol)
Remove the unit for column scol.
Definition: table_units.h:378
The main O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl names...
Definition: anneal.h:42
size_t get_nlines() const
Return the number of lines.
Definition: table.h:465
double min(std::string scol) const
Return column minimum. Makes no assumptions about ordering, .
Definition: table.h:2032
void hdf_input_data(hdf_file &hf, o2scl::table< vec_t > &t)
Internal function for inputting a o2scl::table object.
Definition: hdf_io.h:95
void hdf_input(hdf_file &hf, o2scl::table_units< vec_t > &t, std::string name)
Input a o2scl::table_units object from a hdf_file.
Definition: hdf_io.h:181
virtual int read_generic(std::istream &fin, int verbose=0)
Clear the current table and read from a generic data file.
Definition: table_units.h:630
Data table table class.
Definition: table.h:49
void set_nlines(size_t il)
Set the number of lines.
Definition: table.h:475
virtual void delete_column(std::string scol)
Delete column named scol.
Definition: table_units.h:489
virtual const char * type()
Return the type, "table_units".
Definition: table_units.h:592
sanity check failed - shouldn&#39;t happen
Definition: err_hnd.h:65
lib_settings_class o2scl_settings
The global library settings object.
Convert units.
Definition: convert_units.h:88
invalid argument supplied by user
Definition: err_hnd.h:59
virtual size_t get_nconsts() const
Get the number of constants.
Definition: table.h:2370
std::map< std::string, col, std::greater< std::string > >::const_iterator aciter
Const map iterator type.
Definition: table.h:2833
Generic "not found" result.
Definition: err_hnd.h:117
int convert_to_unit(std::string scol, std::string unit, bool err_on_fail=true)
Convert the units of column scol to unit.
Definition: table_units.h:416
generic failure
Definition: err_hnd.h:61
size_t get_interp_type() const
Get the interpolation type.
Definition: table.h:1570
virtual double get_constant(std::string name) const
Get a constant.
Definition: table.h:2360
virtual void summary(std::ostream *out, size_t ncol=79) const
Output a summary of the information stored.
Definition: table_units.h:533
void insert_table(table_units< vec2_t > &source, std::string src_index, bool allow_extrap=true, std::string dest_index="")
Insert columns from a source table into the new table by interpolation (or extrapolation) ...
Definition: table_units.h:771
virtual void rename_column(std::string src, std::string dest)
Rename column named src to dest .
Definition: table_units.h:525
std::map< std::string, double > constants
The list of constants.
Definition: table.h:2753
void set_unit(std::string scol, std::string unit)
Set the unit for column scol to unit.
Definition: table_units.h:397
size_t get_maxlines()
Return the maximum number of lines before a reallocation is required.
Definition: table.h:497
double interp(std::string sx, double x0, std::string sy)
Interpolate value x0 from column named sx into column named sy.
Definition: table.h:1581
convert_units * cup
The pointer to the convert units object.
Definition: table_units.h:833
size_t get_nunits()
Return the number of columns with units.
Definition: table_units.h:461
table_units & operator=(const table_units &t)
Copy with operator= from table_units.
Definition: table_units.h:196
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
Column structure for table [protected].
Definition: table.h:2817
The O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl namespace ...
Definition: table.h:53
void hdf_input_data(hdf_file &hf, o2scl::table_units< vec_t > &t)
Internal function for inputting a o2scl::table_units object.
Definition: hdf_io.h:217
std::map< std::string, std::string, std::greater< std::string > > utree
Unit map.
Definition: table_units.h:844
convert_units & get_convert_units()
Get the global convert_units object.
Definition: lib_settings.h:149
void screenify(size_t nin, const string_arr_t &in_cols, std::vector< std::string > &out_cols, size_t max_size=80)
Reformat the columns for output of width size.
Definition: misc.h:124
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
void copy_rows(std::string func, table_units< vec2_t > &dest)
Copy all rows matching a particular condition to a new table.
Definition: table_units.h:320
virtual void add_constant(std::string name, double val)
Add a constant, or if the constant already exists, change its value.
Definition: table.h:2318
void set_interp_type(size_t interp_type)
Set the base interpolation objects.
Definition: table.h:1559
bool is_number(std::string s)
Return true if the string s is likely a integral or floating point number.
size_t get_ncolumns() const
Return the number of columns.
Definition: table.h:457
double stod(std::string s)
Convert a string to a double.
Data table table class with units.
Definition: table_units.h:42
void new_column(std::string head)
Add a new column owned by the table table .
Definition: table.h:742
void clear()
Clear everything.
Definition: table.h:2150
aiter end()
Return the end of the column tree.
Definition: table.h:2876
bool is_column(std::string scol) const
Return true if scol is a column in the current table table .
Definition: table.h:953
table_units(const table< vec_t > &t)
Copy with constructor from table.
Definition: table_units.h:149
table_units & operator=(const table< vec_t > &t)
Copy with operator= from table.
Definition: table_units.h:251
std::map< std::string, col, std::greater< std::string > >::iterator aiter
Map iterator type.
Definition: table.h:2829
virtual void copy_column(std::string src, std::string dest)
Copy data from column named src to column named dest, creating a new column if necessary ...
Definition: table_units.h:602
Store data in an O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$sc...
Definition: hdf_file.h:100
std::string get_unit(std::string scol) const
Get the unit for column scol.
Definition: table_units.h:350
void set(std::string scol, size_t row, double val)
Set row row of column named col to value val . .
Definition: table.h:329
std::string get_unit(size_t i) const
Get the unit for column with index i.
Definition: table_units.h:373
std::string get_column_name(size_t icol) const
Returns the name of column col .
Definition: table.h:810
std::string szttos(size_t x)
Convert a size_t to a string.
void hdf_input(hdf_file &hf, o2scl::table< vec_t > &t, std::string name)
Input a o2scl::table object from a hdf_file.
Definition: hdf_io.h:59
vec_t dat
Pointer to column.
Definition: table.h:2820
std::vector< aiter >::iterator aviter
Vector iterator type.
Definition: table.h:2835
int index
Column index.
Definition: table.h:2822
Success.
Definition: err_hnd.h:47
virtual void swap_column_data(std::string scol, vec_t &v)
Swap the data in column scol with that in vector v.
Definition: table.h:829
table_units(const table_units &t)
Copy with constructor from table_units.
Definition: table_units.h:106
virtual void rename_column(std::string src, std::string dest)
Rename column named src to dest .
Definition: table.h:848

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).