00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_GPU_CUDA_CUDASPRINGFORCEFIELD_INL
00026 #define SOFA_GPU_CUDA_CUDASPRINGFORCEFIELD_INL
00027
00028 #include "CudaSpringForceField.h"
00029 #include <sofa/component/forcefield/SpringForceField.inl>
00030 #include <sofa/component/forcefield/StiffSpringForceField.inl>
00031 #include <sofa/component/forcefield/MeshSpringForceField.inl>
00032 #include <sofa/component/forcefield/TriangleBendingSprings.inl>
00033 #include <sofa/component/forcefield/QuadBendingSprings.inl>
00034
00035 namespace sofa
00036 {
00037
00038 namespace gpu
00039 {
00040
00041 namespace cuda
00042 {
00043
00044 extern "C"
00045 {
00046 void SpringForceFieldCuda3f_addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v);
00047 void SpringForceFieldCuda3f_addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2);
00048 void StiffSpringForceFieldCuda3f_addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v, void* dfdx);
00049 void StiffSpringForceFieldCuda3f_addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2, void* dfdx);
00050 void StiffSpringForceFieldCuda3f_addDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* dx, const void* x, const void* dfdx, double factor);
00051 void StiffSpringForceFieldCuda3f_addExternalDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* dx1, const void* x1, const void* dx2, const void* x2, const void* dfdx, double factor);
00052
00053 void SpringForceFieldCuda3f1_addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v);
00054 void SpringForceFieldCuda3f1_addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2);
00055 void StiffSpringForceFieldCuda3f1_addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v, void* dfdx);
00056 void StiffSpringForceFieldCuda3f1_addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2, void* dfdx);
00057 void StiffSpringForceFieldCuda3f1_addDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* dx, const void* x, const void* dfdx, double factor);
00058 void StiffSpringForceFieldCuda3f1_addExternalDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* dx1, const void* x1, const void* dx2, const void* x2, const void* dfdx, double factor);
00059
00060
00061 }
00062
00063
00064 template<>
00065 class CudaKernelsSpringForceField<CudaVec3fTypes>
00066 {
00067 public:
00068 static void addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v)
00069 { SpringForceFieldCuda3f_addForce(nbVertex, nbSpringPerVertex, springs, f, x, v); }
00070 static void addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2)
00071 { SpringForceFieldCuda3f_addExternalForce(nbVertex, nbSpringPerVertex, springs, f1, x1, v1, x2, v2); }
00072 static void addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v, void* dfdx)
00073 { StiffSpringForceFieldCuda3f_addForce(nbVertex, nbSpringPerVertex, springs, f, x, v, dfdx); }
00074 static void addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2, void* dfdx)
00075 { StiffSpringForceFieldCuda3f_addExternalForce(nbVertex, nbSpringPerVertex, springs, f1, x1, v1, x2, v2, dfdx); }
00076 static void addDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* dx, const void* x, const void* dfdx, double factor)
00077 { StiffSpringForceFieldCuda3f_addDForce(nbVertex, nbSpringPerVertex, springs, f, dx, x, dfdx, factor); }
00078 static void addExternalDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* dx1, const void* x1, const void* dx2, const void* x2, const void* dfdx, double factor)
00079 { StiffSpringForceFieldCuda3f_addExternalDForce(nbVertex, nbSpringPerVertex, springs, f1, dx1, x1, dx2, x2, dfdx, factor); }
00080 };
00081
00082 template<>
00083 class CudaKernelsSpringForceField<CudaVec3f1Types>
00084 {
00085 public:
00086 static void addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v)
00087 { SpringForceFieldCuda3f1_addForce(nbVertex, nbSpringPerVertex, springs, f, x, v); }
00088 static void addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2)
00089 { SpringForceFieldCuda3f1_addExternalForce(nbVertex, nbSpringPerVertex, springs, f1, x1, v1, x2, v2); }
00090 static void addForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* x, const void* v, void* dfdx)
00091 { StiffSpringForceFieldCuda3f1_addForce(nbVertex, nbSpringPerVertex, springs, f, x, v, dfdx); }
00092 static void addExternalForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* x1, const void* v1, const void* x2, const void* v2, void* dfdx)
00093 { StiffSpringForceFieldCuda3f1_addExternalForce(nbVertex, nbSpringPerVertex, springs, f1, x1, v1, x2, v2, dfdx); }
00094 static void addDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f, const void* dx, const void* x, const void* dfdx, double factor)
00095 { StiffSpringForceFieldCuda3f1_addDForce(nbVertex, nbSpringPerVertex, springs, f, dx, x, dfdx, factor); }
00096 static void addExternalDForce(unsigned int nbVertex, unsigned int nbSpringPerVertex, const void* springs, void* f1, const void* dx1, const void* x1, const void* dx2, const void* x2, const void* dfdx, double factor)
00097 { StiffSpringForceFieldCuda3f1_addExternalDForce(nbVertex, nbSpringPerVertex, springs, f1, dx1, x1, dx2, x2, dfdx, factor); }
00098 };
00099
00100
00101 }
00102
00103 }
00104
00105 namespace component
00106 {
00107
00108 namespace forcefield
00109 {
00110
00111 using namespace gpu::cuda;
00112
00113 template<class TCoord, class TDeriv, class TReal>
00114 void SpringForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::init(Main* m, bool stiff)
00115 {
00116 Data& data = m->data;
00117 m->Inherit::init();
00118 const sofa::helper::vector<Spring>& springs = m->springs.getValue();
00119 if (!springs.empty())
00120 {
00121 bool external = (m->mstate1!=m->mstate2);
00122 if (external)
00123 {
00124 std::map<int,int> nsprings1;
00125 std::map<int,int> nsprings2;
00126 for (unsigned int i=0;i<springs.size();i++)
00127 {
00128 nsprings1[springs[i].m1]++;
00129 nsprings2[springs[i].m2]++;
00130 }
00131
00132 int nmax1 = 0;
00133 for (std::map<int,int>::const_iterator it = nsprings1.begin(); it != nsprings1.end(); ++it)
00134 if (it->second > nmax1)
00135 nmax1 = it->second;
00136 data.springs1.init(nsprings1.begin()->first, nsprings1.rbegin()->first - nsprings1.begin()->first + 1, nmax1);
00137
00138 int nmax2 = 0;
00139 for (std::map<int,int>::const_iterator it = nsprings2.begin(); it != nsprings2.end(); ++it)
00140 if (it->second > nmax2)
00141 nmax2 = it->second;
00142 data.springs2.init(nsprings2.begin()->first, nsprings2.rbegin()->first - nsprings2.begin()->first + 1, nmax2);
00143
00144 nsprings1.clear();
00145 nsprings2.clear();
00146 for (unsigned int i=0;i<springs.size();i++)
00147 {
00148 int m1 = springs[i].m1 - data.springs1.vertex0;
00149 int m2 = springs[i].m2 - data.springs2.vertex0;
00150 data.springs1.set(m1, nsprings1[m1]++, m2,
00151 (float)springs[i].initpos,
00152 (float)springs[i].ks,
00153 (float)springs[i].kd);
00154 data.springs2.set(m2, nsprings2[m2]++, m1,
00155 (float)springs[i].initpos,
00156 (float)springs[i].ks,
00157 (float)springs[i].kd);
00158 }
00159 }
00160 else
00161 {
00162 std::map<int,int> nsprings;
00163 for (unsigned int i=0;i<springs.size();i++)
00164 {
00165 nsprings[springs[i].m1]++;
00166 nsprings[springs[i].m2]++;
00167 }
00168
00169 int nmax = 0;
00170 for (std::map<int,int>::const_iterator it = nsprings.begin(); it != nsprings.end(); ++it)
00171 if (it->second > nmax)
00172 nmax = it->second;
00173 data.springs1.init(nsprings.begin()->first, nsprings.rbegin()->first - nsprings.begin()->first + 1, nmax);
00174 std::cout << "CUDA SpringForceField: "<<springs.size()<<" springs, "<<data.springs1.nbVertex<<" attached points, max "<<data.springs1.nbSpringPerVertex<<" springs per point."<<std::endl;
00175 nsprings.clear();
00176 for (unsigned int i=0;i<springs.size();i++)
00177 {
00178 int m1 = springs[i].m1 - data.springs1.vertex0;
00179 int m2 = springs[i].m2 - data.springs1.vertex0;
00180 data.springs1.set(m1, nsprings[m1]++, m2,
00181 (float)springs[i].initpos,
00182 (float)springs[i].ks,
00183 (float)springs[i].kd);
00184 data.springs1.set(m2, nsprings[m2]++, m1,
00185 (float)springs[i].initpos,
00186 (float)springs[i].ks,
00187 (float)springs[i].kd);
00188 }
00189 }
00190 }
00191 if (stiff)
00192 {
00193 data.springs1.dfdx.resize(data.springs1.springs.size());
00194 data.springs2.dfdx.resize(data.springs2.springs.size());
00195 }
00196 }
00197
00198
00199 template<class TCoord, class TDeriv, class TReal>
00200 void SpringForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::addForce(Main* m, bool stiff, VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00201 {
00202 Data& data = m->data;
00203 if (m->mstate1 == m->mstate2)
00204 {
00205 VecDeriv& f = f1;
00206 const VecCoord& x = x1;
00207 const VecDeriv& v = v1;
00208 f.resize(x.size());
00209 int d = data.springs1.vertex0;
00210 if (data.springs1.nbSpringPerVertex > 0)
00211 {
00212 if (!stiff)
00213 Kernels::addForce(data.springs1.nbVertex,
00214 data.springs1.nbSpringPerVertex,
00215 data.springs1.springs.deviceRead(),
00216 ( Deriv*)f.deviceWrite() + d,
00217 (const Coord*)x.deviceRead() + d,
00218 (const Deriv*)v.deviceRead() + d);
00219 else
00220 Kernels::addForce(data.springs1.nbVertex,
00221 data.springs1.nbSpringPerVertex,
00222 data.springs1.springs.deviceRead(),
00223 ( Deriv*)f.deviceWrite() + d,
00224 (const Coord*)x.deviceRead() + d,
00225 (const Deriv*)v.deviceRead() + d,
00226 data.springs1.dfdx.deviceWrite());
00227 }
00228 }
00229 else
00230 {
00231 f1.resize(x1.size());
00232 f2.resize(x2.size());
00233 int d1 = data.springs1.vertex0;
00234 int d2 = data.springs2.vertex0;
00235 if (data.springs1.nbSpringPerVertex > 0)
00236 {
00237 if (!stiff)
00238 Kernels::addExternalForce(data.springs1.nbVertex,
00239 data.springs1.nbSpringPerVertex,
00240 data.springs1.springs.deviceRead(),
00241 ( Deriv*)f1.deviceWrite() + d1,
00242 (const Coord*)x1.deviceRead() + d1,
00243 (const Deriv*)v1.deviceRead() + d1,
00244 (const Coord*)x2.deviceRead() + d2,
00245 (const Deriv*)v2.deviceRead() + d2);
00246 else
00247 Kernels::addExternalForce(data.springs1.nbVertex,
00248 data.springs1.nbSpringPerVertex,
00249 data.springs1.springs.deviceRead(),
00250 ( Deriv*)f1.deviceWrite() + d1,
00251 (const Coord*)x1.deviceRead() + d1,
00252 (const Deriv*)v1.deviceRead() + d1,
00253 (const Coord*)x2.deviceRead() + d2,
00254 (const Deriv*)v2.deviceRead() + d2,
00255 data.springs1.dfdx.deviceWrite());
00256 }
00257 if (data.springs2.nbSpringPerVertex > 0)
00258 {
00259 if (!stiff)
00260 Kernels::addExternalForce(data.springs2.nbVertex,
00261 data.springs2.nbSpringPerVertex,
00262 data.springs2.springs.deviceRead(),
00263 ( Deriv*)f2.deviceWrite() + d2,
00264 (const Coord*)x2.deviceRead() + d2,
00265 (const Deriv*)v2.deviceRead() + d2,
00266 (const Coord*)x1.deviceRead() + d1,
00267 (const Deriv*)v1.deviceRead() + d1);
00268 else
00269 Kernels::addExternalForce(data.springs2.nbVertex,
00270 data.springs2.nbSpringPerVertex,
00271 data.springs2.springs.deviceRead(),
00272 ( Deriv*)f2.deviceWrite() + d2,
00273 (const Coord*)x2.deviceRead() + d2,
00274 (const Deriv*)v2.deviceRead() + d2,
00275 (const Coord*)x1.deviceRead() + d1,
00276 (const Deriv*)v1.deviceRead() + d1,
00277 data.springs2.dfdx.deviceWrite());
00278 }
00279 }
00280 }
00281
00282 template<class TCoord, class TDeriv, class TReal>
00283 void SpringForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::addDForce(Main* m, bool stiff, VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double )
00284 {
00285 if (!stiff) return;
00286 Data& data = m->data;
00287 if (m->mstate1 == m->mstate2)
00288 {
00289 VecDeriv& df = df1;
00290 const VecDeriv& dx = dx1;
00291 const VecCoord& x = *m->mstate1->getX();
00292 df.resize(x.size());
00293 int d = data.springs1.vertex0;
00294 if (data.springs1.nbSpringPerVertex > 0)
00295 {
00296 Kernels::addDForce(data.springs1.nbVertex,
00297 data.springs1.nbSpringPerVertex,
00298 data.springs1.springs.deviceRead(),
00299 ( Deriv*)df.deviceWrite() + d,
00300 (const Deriv*)dx.deviceRead() + d,
00301 (const Coord*)x.deviceRead() + d,
00302 data.springs1.dfdx.deviceRead(),
00303 kFactor);
00304 }
00305 }
00306 else
00307 {
00308 const VecCoord& x1 = *m->mstate1->getX();
00309 const VecCoord& x2 = *m->mstate2->getX();
00310 df1.resize(x1.size());
00311 df2.resize(x2.size());
00312 int d1 = data.springs1.vertex0;
00313 int d2 = data.springs2.vertex0;
00314 if (data.springs1.nbSpringPerVertex > 0)
00315 {
00316 Kernels::addExternalDForce(data.springs1.nbVertex,
00317 data.springs1.nbSpringPerVertex,
00318 data.springs1.springs.deviceRead(),
00319 ( Deriv*)df1.deviceWrite() + d1,
00320 (const Coord*)x1.deviceRead() + d1,
00321 (const Deriv*)dx1.deviceRead() + d1,
00322 (const Coord*)x2.deviceRead() + d2,
00323 (const Deriv*)dx2.deviceRead() + d2,
00324 data.springs1.dfdx.deviceRead(),
00325 kFactor);
00326 }
00327 if (data.springs2.nbSpringPerVertex > 0)
00328 {
00329 Kernels::addExternalDForce(data.springs2.nbVertex,
00330 data.springs2.nbSpringPerVertex,
00331 data.springs2.springs.deviceRead(),
00332 ( Deriv*)df2.deviceWrite() + d2,
00333 (const Deriv*)dx2.deviceRead() + d2,
00334 (const Coord*)x2.deviceRead() + d2,
00335 (const Deriv*)dx1.deviceRead() + d1,
00336 (const Coord*)x1.deviceRead() + d1,
00337 data.springs2.dfdx.deviceRead(),
00338 kFactor);
00339 }
00340 }
00341 }
00342
00343
00344
00345 #define CudaSpringForceField_ImplMethods(T) \
00346 template<> void SpringForceField< T >::init() \
00347 { data.init(this, false); } \
00348 template<> void SpringForceField< T >::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2) \
00349 { data.addForce(this, false, f1, f2, x1, x2, v1, v2); } \
00350 template<> void StiffSpringForceField< T >::init() \
00351 { data.init(this, true); } \
00352 template<> void StiffSpringForceField< T >::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2) \
00353 { data.addForce(this, true, f1, f2, x1, x2, v1, v2); } \
00354 template<> void StiffSpringForceField< T >::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double bFactor) \
00355 { data.addDForce(this, true, df1, df2, dx1, dx2, kFactor, bFactor); }
00356
00357 CudaSpringForceField_ImplMethods(gpu::cuda::CudaVec3fTypes);
00358 CudaSpringForceField_ImplMethods(gpu::cuda::CudaVec3f1Types);
00359
00360
00361 #undef CudaSpringForceField_ImplMethods
00362
00363 }
00364
00365 }
00366
00367 }
00368
00369 #endif