Object-oriented Scientific Computing Library: Version 0.910
table3d.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_TABLE3D_H
00024 #define O2SCL_TABLE3D_H
00025 
00026 #include <iostream>
00027 #include <fstream>
00028 #include <vector>
00029 #include <string>
00030 #include <cmath>
00031 #include <sstream>
00032 #include <o2scl/misc.h>
00033 #include <o2scl/err_hnd.h>
00034 #include <o2scl/multi_funct.h>
00035 #include <o2scl/search_vec.h>
00036 #include <o2scl/ovector_tlate.h>
00037 #include <o2scl/interp.h>
00038 #include <o2scl/smart_interp.h>
00039 #include <o2scl/table.h>
00040 
00041 #ifndef DOXYGENP
00042 namespace o2scl {
00043 #endif
00044   
00045   /** \brief A data structure containing many slices of two-dimensional
00046       data points defined on a grid
00047 
00048       \future Improve interpolation and derivative caching
00049       \future Make a 'const' version of the interpolation functions
00050       \future Should there be a clear_grid() function separate from
00051       clear_data() and clear_table()?
00052   */
00053   class table3d {
00054     
00055   public:
00056   
00057     /** \brief Create a new 3D \table
00058      */
00059     table3d();
00060 
00061     virtual ~table3d();
00062 
00063     /// \name Initialization
00064     //@{
00065     /** \brief Initialize the x-y grid
00066         
00067         This function will not allow you to redefine the grid when
00068         there is data in the \table if a grid of a different size was
00069         already set from a previous call to either set_xy() or
00070         set_size(). However, you may freely redefine the grid after a
00071         call to clear_data() or clear_table(). You may change
00072         individual grid points at any time with set_grid_x() and
00073         set_grid_y().
00074 
00075     */
00076     template<class vec2_t> int set_xy(std::string x_name, size_t nx, 
00077                                       const vec2_t &x, std::string y_name,
00078                                       size_t ny, const vec2_t &y) {
00079       if (has_slice && (size_set || xy_set) && (nx!=numx || ny!=numy)) {
00080         O2SCL_ERR_RET("Size cannot be reset in table3d::set_xy().",
00081                       o2scl::gsl_einval);
00082       }
00083       if (xy_set) {
00084         xval.free();
00085         yval.free();
00086       }
00087       numx=nx;
00088       numy=ny;
00089       xname=x_name;
00090       yname=y_name;
00091       xval.allocate(nx);
00092       yval.allocate(ny);
00093       for(size_t i=0;i<nx;i++) (xval)[i]=x[i];
00094       for(size_t i=0;i<ny;i++) (yval)[i]=y[i];
00095       size_set=true;
00096       xy_set=true;
00097       return 0;
00098     }
00099 
00100     /** \brief Initialize \table size
00101 
00102         This function will not allow you to resize the \table if it
00103         already has data or if the size has already been set with the
00104         set_xy() function, unless you clear the data with clear_data()
00105         or the \table with clear_table() first.
00106     */
00107     int set_size(size_t nx, size_t ny);
00108     //@}
00109 
00110     // --------------------------------------------------------
00111     /// \name On-grid get and set methods 
00112     //@{
00113 
00114     /** \brief Set element in slice \c name at location <tt>ix,iy</tt> 
00115         to value \c val
00116     */
00117     int set(size_t ix, size_t iy, std::string name, double val);
00118 
00119     /** \brief Set element in slice of index \c z at location
00120         <tt>ix,iy</tt> to value \c val .
00121     */
00122     int set(size_t ix, size_t iy, size_t z, double val);
00123 
00124     /** \brief Get element in slice \c name at location
00125         <tt>ix,iy</tt>
00126     */
00127     double &get(size_t ix, size_t iy, std::string name);
00128 
00129     /** \brief Get element in slice \c name at location
00130         <tt>ix,iy</tt> (const version)
00131     */
00132     const double &get(size_t ix, size_t iy, std::string name) const;
00133 
00134     /** \brief Get element in slice of index \c z at location
00135         <tt>ix,iy</tt>
00136     */
00137     double &get(size_t ix, size_t iy, size_t z);
00138 
00139     /** \brief Get element in slice of index \c z at location
00140         <tt>ix,iy</tt> (const version)
00141     */
00142     const double &get(size_t ix, size_t iy, size_t z) const;
00143     //@}
00144 
00145     // --------------------------------------------------------
00146     /** \name Off-grid get and set methods 
00147 
00148         These methods return the value of a slice on the grid
00149         point nearest to a user-specified location. For
00150         interpolation into a point off the grid, use 
00151         \ref table3d::interp().
00152      */
00153     //@{
00154 
00155     /** \brief Set element in slice \c name at the nearest location to
00156         <tt>x,y</tt> to value \c val
00157     */
00158     int set_val(double x, double y, std::string name, double val);
00159 
00160     /** \brief Set element in slice of index \c z at the nearest
00161         location to <tt>x,y</tt> to value \c val
00162     */
00163     int set_val(double x, double y, size_t z, double val);
00164     
00165     /** \brief Get element in slice \c name at location closest to
00166         <tt>x,y</tt>
00167     */
00168     double &get_val(double x, double y, std::string name);
00169     
00170     /** \brief Get element in slice \c name at location closest to
00171         <tt>x,y</tt>
00172     */
00173     const double &get_val(double x, double y, std::string name) const;
00174     
00175     /** \brief Get element in slice of index \c z at location closest
00176         to <tt>x,y</tt>
00177     */
00178     double &get_val(double x, double y, size_t z);
00179 
00180     /** \brief Get element in slice of index \c z at location closest
00181         to <tt>x,y</tt>
00182     */
00183     const double &get_val(double x, double y, size_t z) const;
00184 
00185     /** \brief Set elements in the first <tt>nv</tt> slices at the
00186         nearest location to <tt>x,y</tt> to value \c val
00187     */
00188     template<class vec_t> 
00189       int set_slices(double x, double y, size_t nv, vec_t &vals) {
00190       size_t ix, iy;
00191       lookup_x(x,ix);
00192       lookup_y(y,iy);
00193 
00194       for(size_t i=0;i<nv && i<list.size();i++) {
00195         list[i][ix][iy]=vals[i];
00196       }
00197       return 0;
00198     }
00199     
00200     /** \brief Get the data for every slice at the nearest location to
00201         <tt>x,y</tt>
00202     */
00203     template<class vec_t>
00204       int get_slices(double x, double y, size_t nv, vec_t &v) {
00205 
00206       size_t ix, iy;
00207 
00208       lookup_x(x,ix);
00209       lookup_y(y,iy);
00210 
00211       for(size_t i=0;i<nv && i<list.size();i++) {
00212         v[i]=list[i][ix][iy];
00213       }
00214 
00215       return 0;
00216     }
00217 
00218     //@}
00219 
00220     // --------------------------------------------------------
00221     /// \name Off-grid get and set methods returning nearest point
00222     //@{
00223 
00224     /** \brief Set element in slice \c name at the nearest location to
00225         <tt>x,y</tt> to value \c val
00226     */
00227     int set_val_ret(double &x, double &y, std::string name, double val);
00228 
00229     /** \brief Set element in slice of index \c z at the nearest
00230         location to <tt>x,y</tt> to value \c val
00231     */
00232     int set_val_ret(double &x, double &y, size_t z, double val);
00233     
00234     /** \brief Get element in slice \c name at location closest to
00235         <tt>x,y</tt>, and also return the corresponding values of \c x
00236         and \c y
00237     */
00238     double &get_val_ret(double &x, double &y, std::string name);
00239     
00240     /** \brief Get element in slice \c name at location closest to
00241         <tt>x,y</tt>, and also return the corresponding values of \c x
00242         and \c y
00243     */
00244     const double &get_val_ret(double &x, double &y, std::string name) const;
00245     
00246     /** \brief Get element in slice of index \c z at location closest
00247         to <tt>x,y</tt>, and also return the corresponding values of
00248         \c x and \c y
00249     */
00250     double &get_val_ret(double &x, double &y, size_t z);
00251 
00252     /** \brief Get element in slice of index \c z at location closest
00253         to <tt>x,y</tt>, and also return the corresponding values of
00254         \c x and \c y
00255     */
00256     const double &get_val_ret(double &x, double &y, size_t z) const;
00257 
00258     /** \brief Set elements in the first <tt>nv</tt> slices at the
00259         nearest location to <tt>x,y</tt> to values \c vals
00260     */
00261     template<class vec_t> 
00262       int set_slices_ret(double &x, double &y, size_t nv, vec_t &vals) {
00263       size_t ix, iy;
00264       lookup_x(x,ix);
00265       lookup_y(y,iy);
00266       x=xval[ix];
00267       y=yval[iy];
00268 
00269       for(size_t i=0;i<nv && i<list.size();i++) {
00270         list[i][ix][iy]=vals[i];
00271       }
00272       return 0;
00273     }
00274 
00275     /** \brief Get elements in the first <tt>nv</tt> slices at the
00276         nearest location to <tt>x,y</tt> to value \c val
00277     */
00278     template<class vec_t> 
00279       int get_slices_ret(double &x, double &y, size_t nv, vec_t &vals) {
00280       size_t ix, iy;
00281       lookup_x(x,ix);
00282       lookup_y(y,iy);
00283       x=xval[ix];
00284       y=yval[iy];
00285       
00286       for(size_t i=0;i<nv && i<list.size();i++) {
00287         vals[i]=list[i][ix][iy];
00288       }
00289       return 0;
00290     }
00291     
00292     //@}
00293 
00294     // --------------------------------------------------------
00295     /// \name Grid information get and set methods
00296     //@{
00297 
00298     /// Set x grid point at index \c ix
00299     int set_grid_x(size_t ix, double val);
00300     
00301     /// Set y grid point at index \c iy
00302     int set_grid_y(size_t iy, double val);
00303     
00304     /// Get x grid point at index \c ix
00305     double get_grid_x(size_t ix);
00306 
00307     /// Get y grid point at index \c iy
00308     double get_grid_y(size_t iy);
00309 
00310     /// Get the name of the x grid variable
00311     std::string get_x_name() const {
00312       return xname;
00313     }
00314 
00315     /// Get the name of the y grid variable
00316     std::string get_y_name() const {
00317       return yname;
00318     }
00319 
00320     /// Set the name of the x grid variable
00321     int set_x_name(std::string name) {
00322       xname=name;
00323       return 0;
00324     }
00325     
00326     /// Set the name of the y grid variable
00327     int set_y_name(std::string name) {
00328       yname=name;
00329       return 0;
00330     }
00331 
00332     /// Get a const reference to the full x grid
00333     const ovector &get_x_data() const { return xval; }
00334 
00335     /// Get a const reference to the full y grid
00336     const ovector &get_y_data() const { return yval; }
00337 
00338     //@}
00339 
00340     // --------------------------------------------------------
00341     /// \name Size get methods
00342     //@{
00343 
00344     /// Get the size of the slices
00345     int get_size(size_t &nx, size_t &ny) const;
00346 
00347     /// Get the x size
00348     int get_nx() const {
00349       return numx;
00350     }
00351     
00352     /// Get the y size
00353     int get_ny() const {
00354       return numy;
00355     }
00356 
00357     /// Get the number of slices
00358     int get_nslices() const;
00359     //@}
00360 
00361     // --------------------------------------------------------
00362     /// \name Slice manipulation 
00363     //@{
00364     
00365     /// Create a set of new slices specified in the string \c names
00366     int line_of_names(std::string names);
00367 
00368     /** \brief Returns the name of slice with index \c z
00369      */
00370     std::string get_slice_name(size_t z) const;
00371 
00372     /** \brief Add a new slice
00373      */
00374     int new_slice(std::string name);
00375 
00376     /** \brief Set all of the values in slice \c name to \c val
00377      */
00378     int set_slice_all(std::string name, double val);
00379 
00380     /** \brief Find the index for column named \c name
00381     */
00382     int lookup_slice(std::string name, size_t &ix) const;
00383     
00384     /** \brief Return true if slice is already present
00385     */
00386     bool is_slice(std::string name, int &ix);
00387     
00388     /** \brief Rename slice named \c olds to \c news
00389         
00390         This is slow since we have to delete the column and re-insert
00391         it. This process in turn mangles all of the iterators in the
00392         list.
00393     */
00394     int rename_slice(std::string olds, std::string news);
00395     
00396     /** \brief Make a new slice named \c dest which is a copy 
00397         of the slice with name given in \c src. 
00398      */
00399     int copy_slice(std::string src, std::string dest);
00400     
00401     /** \brief Initialize all values of slice named \c scol to \c val 
00402      */
00403     int init_slice(std::string scol, double val);
00404 
00405     /// Return a constant reference to a slice
00406     const omatrix &get_slice(std::string scol) const;
00407 
00408     /// Return a constant reference to a slice
00409     const omatrix &get_slice(size_t iz) const;
00410 
00411     /// Return a constant reference to a slice
00412     omatrix &get_slice(std::string scol);
00413     
00414     /// Return a constant reference to a slice
00415     omatrix &get_slice(size_t iz);
00416     
00417     /** \brief Return a constant reference to all the slice data
00418 
00419         \comment
00420         This isn't designated const, i.e. as
00421         const std::vector<omatrix> &get_data() const;
00422         because it would then have to be 
00423         const std::vector<const omatrix> &get_data() const;
00424         \endcomment
00425      */
00426     const std::vector<omatrix> &get_data();
00427     //@}
00428   
00429     // --------------------------------------------------------
00430     /// \name Lookup and search methods
00431     //@{
00432   
00433     /** \brief Look for a value in the x grid
00434     */
00435     int lookup_x(double val, size_t &ix) const;
00436   
00437     /** \brief Look for a value in the y grid
00438     */
00439     int lookup_y(double val, size_t &iy) const;
00440 
00441     /** \brief Look for a value in a specified slice
00442     */
00443     int lookup(double val, std::string slice, size_t &ix, size_t &iy) const;
00444     //@}
00445 
00446     // --------------------------------------------------------
00447     /// \name Interpolation, differentiation, and integration
00448     //@{
00449 
00450     /** \brief Specify the base interpolation objects to use
00451     */
00452     int set_interp(base_interp_mgr<ovector_const_view> &b1,
00453                    base_interp_mgr<ovector_const_subvector> &b2);
00454     
00455     /** \brief Interpolate \c x and \c y in slice named \c name
00456     */
00457     double interp(double x, double y, std::string name);
00458 
00459     /** \brief Interpolate the derivative of the data with respect to
00460         the x grid at point \c x and \c y in slice named \c name
00461     */
00462     double deriv_x(double x, double y, std::string name);
00463 
00464     /** \brief Interpolate the derivative of the data with respect to
00465         the y grid at point \c x and \c y in slice named \c name
00466     */
00467     double deriv_y(double x, double y, std::string name);
00468 
00469     /** \brief Interpolate the mixed second derivative of the data at
00470         point \c x and \c y in slice named \c name
00471     */
00472     double deriv_xy(double x, double y, std::string name);
00473 
00474     /** \brief Interpolate the integral of the data 
00475         respect to the x grid 
00476     */
00477     double integ_x(double x1, double x2, double y, std::string name);
00478 
00479     /** \brief Interpolate the integral of the data 
00480         respect to the y grid 
00481     */
00482     double integ_y(double x, double y1, double y2, std::string name);
00483 
00484     /** \brief Fill a vector of interpolated values from each slice at the
00485         point <tt>x,y</tt>
00486      */
00487     template<class vec_t>
00488       int interp_slices(double x, double y, size_t nv, vec_t &v) {
00489       
00490       for (size_t i=0;i<list.size();i++) {
00491         std::string name=get_slice_name(i);
00492         v[i]=interp(x,y,name);
00493       }
00494 
00495       return 0;
00496     }
00497 
00498     //@}
00499 
00500     // --------------------------------------------------------
00501     /// \name Extract 2-dimensional tables
00502     //@{
00503     /** \brief Extract a table at a fixed x grid point 
00504 
00505         \note All of the information previously stored in \c t will
00506         be lost.
00507      */
00508     int extract_x(double x, table &t);
00509     
00510     /** \brief Extract a table at a fixed y grid point 
00511 
00512         \note All of the information previously stored in \c t will
00513         be lost.
00514      */
00515     int extract_y(double y, table &t);
00516     //@}
00517 
00518     // --------------------------------------------------------
00519     /// \name Clear methods 
00520     //@{
00521     /** \brief Zero the data entries but keep the slice names
00522         and grid
00523     */
00524     int zero_table();
00525 
00526     /** \brief Clear the table and the slice names
00527      */
00528     void clear_table();
00529 
00530     /** \brief Remove all of the data by setting the number
00531         of lines to zero
00532 
00533         This leaves the column names intact and does not remove
00534         the constants.
00535     */
00536     void clear_data();
00537     //@}
00538 
00539     // --------------------------------------------------------
00540     /// \name Summary method 
00541     //@{
00542     /** \brief Output a summary of the information stored
00543         
00544         Outputs the number of constants, the grid information,
00545         and a list of the slice names
00546     */
00547     int summary(std::ostream *out, int ncol=79) const;
00548     //@}
00549 
00550     // --------------------------------------------------------
00551     /** \name Histogram-like functions
00552      */
00553     //@{
00554     /** \brief Update a histogram entry
00555 
00556         Assuming that the histogram bins are given in column named \c
00557         ix_col, this updates the histogram found in column \c scol at
00558         index location \c ix by incrementing it by an amount given in
00559         \c inc.
00560     */
00561     int hist_update(double ix, double iy, std::string scol, double inc=1.0);
00562 
00563     /** \brief Get a histogram entry
00564 
00565         Assuming that the histogram bins are given in column
00566         named \c ix_col, this returns the histogram entry found
00567         in column \c scol at index location \c ix .
00568     */
00569     double hist_get(double ix, double iy, std::string scol) const;
00570 
00571     /** \brief Set a histogram entry
00572 
00573         Assuming that the histogram bins are given in column
00574         named \c ix_col, this sets the histogram entry found
00575         in column \c scol at index location \c ix to the
00576         value given in \c value .
00577     */
00578     int hist_set(double ix, double iy, std::string scol, double value);
00579     //@}
00580 
00581     bool is_size_set() const {
00582       return size_set;
00583     }
00584 
00585     bool is_xy_set() const {
00586       return xy_set;
00587     }
00588   
00589 #ifdef O2SCL_NEVER_DEFINED
00590 
00591     // --------------------------------------------------------
00592     /// \name Contour lines method
00593     //@{
00594 
00595     /** \brief Create contour lines from the slice named \c name
00596 
00597         This uses \ref contour to compute contour lines (stored in \c
00598         clines) from slice \c name given \c nlev contour levels in \c
00599         levs .
00600      */
00601     template<class vec_t> 
00602       int slice_contours(std::string name, size_t nlev, vec_t &levs,
00603                          std::vector<contour_line> &clines) {
00604       size_t z=0;
00605       int ret=lookup_slice(name,z);
00606       
00607       contour co;
00608       // Note that the contour class stores the matrix data in (y,x)
00609       // order, not (x,y) so the order has to be reversed here.
00610       co.set_data(numy,numx,yval,xval,list[z]);
00611       co.set_levels(nlev,levs);
00612       co.calc_contours(clines);
00613 
00614       return 0;
00615     }
00616     //@}
00617 
00618 #endif
00619     
00620     // --------------------------------------------------------
00621     /// \name Manipulating constants
00622     //@{
00623     /// Add a constant
00624     virtual int add_constant(std::string name, double val);
00625 
00626     /// Remove a constant
00627     virtual int remove_constant(std::string name);
00628     
00629     /// Add a constant
00630     virtual int set_constant(std::string name, double val);
00631 
00632     /// Get a constant
00633     virtual double get_constant(std::string name);
00634 
00635     /// Get a constant by index
00636     virtual int get_constant(size_t ix, std::string &name, double &val) const;
00637 
00638     /// Get the number of constants
00639     virtual size_t get_nconsts() const {
00640       return constants.size();
00641     }
00642     //@}
00643 
00644     /// \name Default interpolation objects
00645     //@{
00646     def_interp_mgr<ovector_const_view,cspline_interp> dim1;
00647 
00648     def_interp_mgr<ovector_const_subvector,cspline_interp> dim2;
00649     //@}
00650 
00651     /// Return the type, \c "table3d".
00652     virtual const char *type() { return "table3d"; }
00653 
00654   protected:
00655 
00656 #ifndef DOXYGEN_INTERNAL
00657     
00658     /// \name Interpolation data
00659     //@{
00660     /// The base interpolation object
00661     base_interp_mgr<ovector_const_view> *bimp1;
00662 
00663     /// The subvector base interpolation object
00664     base_interp_mgr<ovector_const_subvector> *bimp2;
00665 
00666     /// The array of sm_interp_vec pointers 
00667     sm_interp_vec **si;
00668 
00669     /// Matrices for interpolation
00670     omatrix_col **aci;
00671     //@}
00672     
00673     /// \name Iterator types
00674     //@{
00675     typedef std::map<std::string,size_t, string_comp>::iterator map_iter;
00676     typedef std::map<std::string,size_t, string_comp>::const_iterator 
00677       map_const_iter;
00678     //@}
00679   
00680     /// \name Data storage
00681     //@{
00682     /// The list of constants
00683     std::map<std::string,double> constants;
00684 
00685     /// The size of the x grid
00686     size_t numx;
00687 
00688     /// The size of the y grid
00689     size_t numy;
00690 
00691     /// A tree connecting column names to list indexes
00692     std::map<std::string,size_t,string_comp> tree;
00693 
00694     /// The name for the x grid
00695     std::string xname;
00696 
00697     /// The name for the y grid
00698     std::string yname;
00699 
00700     /// The pointers to the matrices
00701     std::vector<omatrix> list;
00702 
00703     /// The x grid
00704     ovector xval;
00705 
00706     /// The y grid
00707     ovector yval;
00708 
00709     /// True if the grid has been set
00710     bool xy_set;
00711 
00712     /// True if the size of the grid has been set
00713     bool size_set;
00714 
00715     /// True if the table has at least one slice
00716     bool has_slice;
00717     //@}
00718   
00719     /// \name Tree iterator boundaries
00720     //@{
00721     /// Return the beginning of the slice tree
00722     map_iter begin() {return tree.begin();};
00723     /// Return the end of the slice tree
00724     map_iter end() {return tree.end();};
00725     /// Return the beginning of the slice tree
00726     map_const_iter const_begin() const {return tree.begin();};
00727     /// Return the end of the slice tree
00728     map_const_iter const_end() const {return tree.end();};
00729     //@}
00730 
00731 #endif
00732 
00733   };
00734 
00735 #ifndef DOXYGENP
00736 }
00737 #endif
00738 
00739 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.