00001 #ifndef SimTK_CPODES_NVECTOR_SimTK_H_ 00002 #define SimTK_CPODES_NVECTOR_SimTK_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK CPodes * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2006-7 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00040 #include "SimTKcommon.h" 00041 00042 #include "sundials/sundials_nvector.h" 00043 00044 #include <cassert> 00045 00046 namespace SimTK { 00047 00048 // This is the object to which the generic N_Vector struct's "content" 00049 // entry points. 00050 class N_VectorContent_SimTK { 00051 public: 00052 N_VectorContent_SimTK() 00053 : treatAsConst(false), ownVector(true), data(new Vector()) { 00054 } 00055 00056 N_VectorContent_SimTK(const Vector& v) 00057 : treatAsConst(true), ownVector(false), 00058 data(const_cast<Vector*>(&v)) { 00059 } 00060 00061 N_VectorContent_SimTK(Vector& v) 00062 : treatAsConst(false), ownVector(false), data(&v) { 00063 } 00064 00065 // Copy constructor makes a deep (new) copy. 00066 N_VectorContent_SimTK(const N_VectorContent_SimTK& nv) 00067 : treatAsConst(false), ownVector(true), data(new Vector(*nv.data)) { 00068 } 00069 00070 // Assignment fails if target is const, otherwise reallocates as needed. 00071 N_VectorContent_SimTK& operator=(const N_VectorContent_SimTK& nv) { 00072 if (&nv != this) { 00073 assert(!treatAsConst); 00074 *data = *nv.data; 00075 } 00076 return *this; 00077 } 00078 00079 ~N_VectorContent_SimTK() { 00080 if (ownVector) delete data; 00081 data = 0; 00082 } 00083 00084 const Vector& getVector() const { 00085 assert(data); 00086 return *data; 00087 } 00088 00089 Vector& updVector() { 00090 assert(data); 00091 assert(!treatAsConst); 00092 return *data; 00093 } 00094 00095 private: 00096 bool treatAsConst; // is this logically const? 00097 bool ownVector; // if true, destruct Vector along with this 00098 Vector* data; 00099 00100 }; 00101 00102 // This singleton class defines the operations needed by the abstract 00103 // N_Vector in terms of operations performed on SimTK Vectors. 00104 // The "virtual function table" is filled in once and used 00105 // in *all* N_Vector_SimTK objects. 00106 class N_Vector_Ops_SimTK : public _generic_N_Vector_Ops { 00107 public: 00108 // Return a reference to the singleton object. You can use 00109 // the address of this reference to check whether a given N_Vector 00110 // is really an N_Vector_SimTK. 00111 static const _generic_N_Vector_Ops& getOps() { 00112 return Ops; 00113 } 00114 00115 // Sundials isn't const correct so it is going to want a 00116 // non-const pointer to the Ops class here, which is const. 00117 // We'll just have to trust it. 00118 static _generic_N_Vector_Ops* getSundialsOpsPtr() { 00119 return const_cast<N_Vector_Ops_SimTK*>(&Ops); 00120 } 00121 00122 private: 00123 N_Vector_Ops_SimTK(); // initialize 00124 SUNDIALS_EXPORT static const N_Vector_Ops_SimTK Ops; 00125 }; 00126 00127 // This is the object to which an N_Vector points when we are using 00128 // SimTK's N_Vector implementation. 00129 class N_Vector_SimTK : public _generic_N_Vector { 00130 public: 00131 // Default constructor creates an owned, empty, resizable vector. 00132 N_Vector_SimTK() { 00133 content = (void*)new N_VectorContent_SimTK(); 00134 ops = N_Vector_Ops_SimTK::getSundialsOpsPtr(); 00135 } 00136 00137 // This constructor produces a read-only *reference* to an existing Vector. 00138 // Destruction of the N_Vector_SimTK leaves the original Vector as it was. 00139 N_Vector_SimTK(const Vector& v) { 00140 content = (void*)new N_VectorContent_SimTK(v); 00141 ops = N_Vector_Ops_SimTK::getSundialsOpsPtr(); 00142 } 00143 00144 // This constructor produces a writable *reference* to an existing 00145 // Vector. Destruction of the N_Vector_SimTK leaves the original 00146 // Vector in existence, although its value may have changed. 00147 N_Vector_SimTK(Vector& v) { 00148 content = (void*)new N_VectorContent_SimTK(v); 00149 ops = N_Vector_Ops_SimTK::getSundialsOpsPtr(); 00150 } 00151 00152 // Copy constructor makes a deep copy. The result will be an owned, 00153 // resizable vector that will evaporate upon destruction of the 00154 // N_Vector_SimTK object. 00155 N_Vector_SimTK(const N_Vector_SimTK& nv) { 00156 assert(nv.ops == &N_Vector_Ops_SimTK::getOps()); 00157 content = (void*)new N_VectorContent_SimTK(nv.getContent()); 00158 ops = N_Vector_Ops_SimTK::getSundialsOpsPtr(); 00159 } 00160 00161 // Assignment will fail if this isn't writable. 00162 N_Vector_SimTK& operator=(const N_Vector_SimTK& nv) { 00163 assert( ops == &N_Vector_Ops_SimTK::getOps() 00164 && nv.ops == &N_Vector_Ops_SimTK::getOps()); 00165 if (&nv != this) 00166 updContent() = nv.getContent(); 00167 return *this; 00168 } 00169 00170 ~N_Vector_SimTK() { 00171 assert(ops == &N_Vector_Ops_SimTK::getOps()); 00172 delete reinterpret_cast<N_VectorContent_SimTK*>(content); 00173 content = 0; 00174 ops = 0; 00175 } 00176 00177 static bool isA(const N_Vector nv) { 00178 return nv && (nv->ops == &N_Vector_Ops_SimTK::getOps()); 00179 } 00180 00181 static const N_Vector_SimTK* downcast(const N_Vector nv) { 00182 assert(isA(nv)); 00183 return reinterpret_cast<const N_Vector_SimTK*>(nv); 00184 } 00185 00186 static N_Vector_SimTK* updDowncast(N_Vector nv) { 00187 assert(isA(nv)); 00188 return reinterpret_cast<N_Vector_SimTK*>(nv); 00189 } 00190 00191 static N_Vector_SimTK* nvclone(const N_Vector nv) { 00192 assert(isA(nv)); 00193 const N_Vector_SimTK& nvs = *reinterpret_cast<const N_Vector_SimTK*>(nv); 00194 return new N_Vector_SimTK(nvs); 00195 } 00196 00197 static const Vector& getVector(const N_Vector nv) { 00198 assert(isA(nv)); 00199 const N_Vector_SimTK& nvs = *reinterpret_cast<const N_Vector_SimTK*>(nv); 00200 return nvs.getContent().getVector(); 00201 } 00202 00203 static Vector& updVector(N_Vector nv) { 00204 assert(isA(nv)); 00205 N_Vector_SimTK& nvs = *reinterpret_cast<N_Vector_SimTK*>(nv); 00206 return nvs.updContent().updVector(); 00207 } 00208 00209 private: 00210 const N_VectorContent_SimTK& getContent() const { 00211 return *reinterpret_cast<const N_VectorContent_SimTK*>(content); 00212 } 00213 N_VectorContent_SimTK& updContent() { 00214 return *reinterpret_cast<N_VectorContent_SimTK*>(content); 00215 } 00216 00217 }; 00218 00219 } // namespace SimTK 00220 00221 #endif // SimTK_NVECTOR_SimTK_H_