CudaSpringForceField.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
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 } // extern "C"
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 } // namespace cuda
00102 
00103 } // namespace gpu
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 // -- InteractionForceField interface
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 /*bFactor*/)
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 // I know using macros is bad design but this is the only way not to repeat the code for all CUDA types
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 } // namespace forcefield
00364 
00365 } // namespace component
00366 
00367 } // namespace sofa
00368 
00369 #endif

Generated on Sun Nov 23 04:02:03 2008 for Sofa by  doxygen 1.5.7.1