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

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