/************************************************************************* Copyright Rice University, 2004-2015. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. **************************************************************************/ #ifndef __RVL_GS #define __RVL_GS #include "space.hh" #include "productspace.hh" #include "functions.hh" #include "contentpackage.hh" #include "locallinalg.hh" #include "write.hh" #include "except.hh" #include "utils.h" #include "TSOp.hh" /* tolerance parameter - in C++ would get from numeric limits. use: two grid locations x and y are identified if abs(x-y) < TOL*d. */ #define TOLFAC 100.0 // define boundary index between external, internal extended axis indices #define EXTINT 100 namespace RVL { /** Axis: Basic Metadata element for regular grids. Defines a uniformly sampled axis, after the fashion of SEPlib77 or RSF. Struct part of RVLGrid Axis class. Innovative feature: each axis carries an integer token (axis.id) meant to signify its position in a global ordering of axes (hence its physical meaning).. Commensurable constraint: all axes may either subgrids of the integer (primal) lattice scaled by d, or the dual integer+1/2 lattice scaled by d, or neither. This status is hecked on construction, and a flag set to signify lattice type: atype=0 for primal, atype=1 for dual, atype=-1 for neither. For indexed operations, it is convenient to refer to a global latice, with origin in the base grid cell [0, d). The first and last grid indices with respect to this lattice are gs0 and ge0. It is also possible to defined an axis subinterval or window, with limits gs >= gs0 and ge <= ge0. These are defaulted to gs0 and ge0 on construction, and may be reset post-construction. */ class Axis { private: /** number of gridpoints on axis */ size_t n; /** step between gridpoints */ float d; /** coordinate of first gridpoint */ float o; /** axis index */ int id; /** axis type (primal or dual), computed */ int atype; /** indices of axis start and end in global grid with origin at zero vector */ int gs0; int ge0; /** active window limits - default to ends of axis */ mutable int gs; mutable int ge; public: Axis(size_t _n = 0, float _d = 1.0f, float _o = 0.0f, int _id = 0) : n(_n), d(_d), o(_o), id(_id) { if (d::epsilon()) { RVLException e; e<<"Error: Axis constructor\n"; e<<" step d="<::epsilon(); else gs0 = (o/d)+TOLFAC*std::numeric_limits::epsilon(); ge0 = gs0+n-1; gs=gs0; ge=ge0; if (abs(o-gs0*d) < TOLFAC*std::numeric_limits::epsilon()) atype=0; else if (abs(o-(0.5+gs0)*d) < TOLFAC*std::numeric_limits::epsilon()) atype=1; else { atype=-1; // signifies neither primal nor dual } } Axis(Axis const & a) : n(a.n), d(a.d), o(a.o), id(a.id), atype(a.atype), gs0(a.gs0), ge0(a.ge0), gs(a.gs), ge(a.ge) {} bool operator==(Axis const & a) const { float tol=std::numeric_limits::epsilon(); tol *=TOLFAC; bool err=true; err = err && (n == a.n); err = err && (fabs(d-a.d) < tol*min(d,a.d)); err = err && (fabs(o-a.o) < tol*min(d,a.d)); err = err && (id == a.id); return err; } void operator=(Axis const & a) { n=a.n; d=a.d; o=a.o; id=a.id; atype=a.atype; gs0=a.gs0; ge0=a.ge0; gs=a.gs; ge=a.ge; } size_t getLength() const { return n; } float getStep() const { return d; } float getOrigin() const { return o; } int getID() const { return id; } int getAxisType() const { return atype; } int getAxisStartIndex() const { return gs0; } int getAxisEndIndex() const { return ge0; } int getSubAxisStartIndex() const { return gs; } int getSubAxisEndIndex() const { return ge; } void setSubAxisStartIndex(int _gs) const { if (_gs= gs0;\n"; e<<" gs="<<_gs<<" gs0="<ge0) { RVLException e; e<<"Error: Axis::setSubAxisEndIndex\n"; e<<" ge must be <= ge0;\n"; e<<" ge="<<_ge<<" ge0="< axes; mutable bool init; mutable IPNT gs0; mutable IPNT gs; mutable IPNT ge0; mutable IPNT ge; public: Grid(size_t _gdim=0): gdim(_gdim), init(false) {} Grid(Grid const & g) : gdim(g.gdim), init(g.init) { for (size_t i=0; i ostream & writeMeta(Grid const & g, ostream & e); template<> size_t getDataSize(Grid const & g); template<> size_t getMetaSize(Grid const & g); template<> char * serialize(Axis const & a, size_t & len); template<> Axis * deserialize(char * cbuf, size_t len); template<> char * serialize(Grid const & g, size_t & len); template<> Grid * deserialize(char * cbuf, size_t len); /** divvy up an array of n T's into an array of arrays of Ts, each chunklen long - like matlab reshape of vector into matrix */ template T** dimView(T* x, size_t n, size_t chunklen) { size_t nchunks = n/chunklen; if (n != nchunks*chunklen) { RVLException e; e<<"Error: dimView\n"; e<<" length of input array = "< { private: mutable float * data1ds; mutable float ** data2d; mutable float ** data2ds; mutable float *** data3d; mutable float *** data3ds; mutable float **** data4d; mutable float ***** data5d; public: GridDC(Grid const & g) : ContentPackage() { this->initialize(g); data1ds=NULL; data2d=NULL; data2ds=NULL; data3d=NULL; data3ds=NULL; data4d=NULL; data5d=NULL; } GridDC(GridDC const & d) : ContentPackage(d) { data1ds=NULL; data2d=NULL; data2ds=NULL; data3d=NULL; data3ds=NULL; data4d=NULL; data5d=NULL; } ~GridDC() { IPNT gs0; IPNT ge0; Grid const & g = this->getMetadata(); g.getAxisLimits(gs0,ge0); if (data2d) userfree_(data2d); if (data2ds) userfree_(data2ds+gs0[1]); if (data3d) userfree_(data3d); if (data3ds) userfree_(data3ds+gs0[2]); if (data4d) userfree_(data4d); if (data5d) userfree_(data5d); } float * getData1DGlobal() { if (!data1ds) { Grid const & g = this->getMetadata(); if (g.getDimension() < 1) { RVLException e; e<<"Error: GridDC::getData2DGlobal\n"; e<<" dimension of grid = "<getData() - gs0[0]; } return data1ds; } float ** getData2D() { if (!data2d) { Grid const & g = this->getMetadata(); if (g.getDimension() < 2) { RVLException e; e<<"Error: GridDC::getData2D\n"; e<<" dimension of grid = "<(g); data2d=dimView(this->getData(),n,g.getAxis(0).getLength()); } return data2d; } float ** getData2DGlobal() { if (!data2ds) { Grid const & g = this->getMetadata(); if (g.getDimension() < 2) { RVLException e; e<<"Error: GridDC::getData2DGlobal\n"; e<<" dimension of grid = "<(g); data2ds=dimView(this->getData1DGlobal(),n,g.getAxis(0).getLength()); IPNT gs0; IPNT ge0; g.getAxisLimits(gs0,ge0); data2ds -= gs0[1]; } return data2ds; } float *** getData3D() { if (!data3d) { Grid const & g = this->getMetadata(); if (g.getDimension() < 3) { RVLException e; e<<"Error: GridDC::getData3D\n"; e<<" dimension of grid = "<(g)/ g.getAxis(0).getLength(); data3d=dimView(this->getData2D(),n,g.getAxis(1).getLength()); } return data3d; } float *** getData3DGlobal() { if (!data3ds) { Grid const & g = this->getMetadata(); if (g.getDimension() < 3) { RVLException e; e<<"Error: GridDC::getData3DGlobal\n"; e<<" dimension of grid = "<(g)/ g.getAxis(0).getLength(); data3ds=dimView(this->getData2DGlobal(),n,g.getAxis(1).getLength()); IPNT gs0; IPNT ge0; g.getAxisLimits(gs0,ge0); data3ds -= gs0[2]; } return data3ds; } float **** getData4D() { if (!data4d) { Grid const & g = this->getMetadata(); if (g.getDimension() < 4) { RVLException e; e<<"Error: GridDC::getData4D\n"; e<<" dimension of grid = "<(g)/ (g.getAxis(1).getLength()* g.getAxis(0).getLength()); data4d=dimView(this->getData3D(),n,g.getAxis(2).getLength()); } return data4d; } float ***** getData5D() { if (!data5d) { Grid const & g = this->getMetadata(); if (g.getDimension() < 5) { RVLException e; e<<"Error: GridDC::getData5D\n"; e<<" dimension of grid = "<(g)/ (g.getAxis(1).getLength()* g.getAxis(0).getLength()* g.getAxis(2).getLength()); data5d=dimView(this->getData4D(),n,g.getAxis(3).getLength()); } return data5d; } }; class GridDCFactory: public DataContainerFactory { private: Grid g; protected: GridDC * buildDC() const { try { GridDC * dc = new GridDC(g); return dc; } catch (RVLException & e) { e<<"\ncalled from GridDCFactory::buildDC\n"; throw e; } } DataContainer * build() const { return buildDC(); } public: GridDCFactory(Grid const & _g): g(_g) {} GridDCFactory(GridDCFactory const & gf): g(gf.g) {} bool compare(DataContainerFactory const & dcf) const { try { GridDCFactory const & gdcf = dynamic_cast(dcf); return (gdcf.g == g); } catch (bad_cast) { return false; } } bool isCompatible(DataContainer const & dc) const { try { GridDC const & gdc = dynamic_cast(dc); Grid const & gdcg = gdc.getMetadata(); return (gdcg == g); } catch (bad_cast) { return false; } } Grid const & getGrid() const { return g; } ostream & write(ostream & str) const { str<<"GridDCFactory based on Grid:\n"; g.write(str); return str; } }; class GridSpace: public StdSpace { private: GridDCFactory f; RVLLinearAlgebraPackage l; protected: Space * clone() const { return new GridSpace(*this); } public: GridSpace(Grid const & g) : f(g), l(g.getCellVolume()) {} GridSpace(GridSpace const & sp) : f(sp.f), l(sp.l) {} LinearAlgebraPackage const & getLAP() const { return l; } DataContainerFactory const & getDCF() const { return f; } // convenience Grid const & getGrid() const { return f.getGrid(); } ostream & write(ostream & str) const { str<<"GridSpace: vector space class for gridded data\n"; f.getGrid().write(str); return str; } }; class GridDomain: public TSSpace { private: std::vector gsa; std::vector gea; std::vector gsc; std::vector gec; std::map ind; int gdim; std::vector dxs; public: GridDomain(std::vector ctrlgrids, std::vector stategrids, std::map _ind) : TSSpace(2), gsa(stategrids.size()), gea(stategrids.size()), gsc(stategrids.size()), gec(stategrids.size()), ind(_ind), gdim((*(ctrlgrids[0])).getDimension()), dxs(gdim) { TSSpace csp(ctrlgrids.size()); for (size_t i=0; iset(csp,0); TSSpace ssp(stategrids.size()); for (size_t i=0; iset(ssp,1); for (int i=0; i< gdim; i++) { dxs[i] = (*(ctrlgrids[0])).getAxis(i).getStep(); } } GridDomain(GridDomain const & gd) : TSSpace(gd), gsa(gd.gsc.size()), gea(gd.gec.size()), gsc(gd.gsc.size()), gec(gd.gec.size()), ind(gd.ind), gdim(gd.gdim), dxs(gdim) { try { for (int i=0; i const & ctrlsp = dynamic_cast const &>(gd[0]); GridSpace const & primsp = dynamic_cast(ctrlsp[0]); for (int i=0; i< gdim; i++) { dxs[i] = primsp.getGrid().getAxis(i).getStep(); } } catch (bad_cast) { RVLException e; e<<"Error: GridDomain copy constructor\n"; e<<" structural error - comp 0 not TSSpace or its comp 0 not GridSpace\n"; throw e; } } std::vector const & get_gsa() const { return gsa; } std::vector const & get_gea() const { return gea; } std::vector const & get_gsc() const { return gsc; } std::vector const & get_gec() const { return gec; } std::map get_ind() const { return ind; } int getDimension() const { return gdim; } std::vector getSteps() const { return dxs; } ostream & write(ostream & str) const { str<<"\n++++++++++++ begin GridDomain +++++++++++++++\n"; str<<"GridDomain specialization of TSSpace\n"; str<<"+++++++++++++++++++++++++++++++++++++++++++++\n"; str<<" all final leaves are GridSpaces\n"; str<<" control subspace:\n"; (*this)[0].write(str); str<<"+++++++++++++++++++++++++++++++++++++++++++++\n"; str<<" state subspace:\n"; (*this)[1].write(str); str<<"+++++++++++++ end GridDomain ++++++++++++++++\n\n"; return str; } }; } #endif