CudaTetrahedronFEMForceField.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_CUDATETRAHEDRONFEMFORCEFIELD_INL
00026 #define SOFA_GPU_CUDA_CUDATETRAHEDRONFEMFORCEFIELD_INL
00027 
00028 #include "CudaTetrahedronFEMForceField.h"
00029 #include <sofa/component/forcefield/TetrahedronFEMForceField.inl>
00030 
00031 namespace sofa
00032 {
00033 
00034 namespace gpu
00035 {
00036 
00037 namespace cuda
00038 {
00039 
00040 extern "C"
00041 {
00042 void TetrahedronFEMForceFieldCuda3f_addForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, void* state, void* eforce, const void* velems, void* f, const void* x, const void* v);
00043 void TetrahedronFEMForceFieldCuda3f_addDForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, const void* state, void* eforce, const void* velems, void* df, const void* dx, double factor);
00044 
00045 void TetrahedronFEMForceFieldCuda3f1_addForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, void* state, void* eforce, const void* velems, void* f, const void* x, const void* v);
00046 void TetrahedronFEMForceFieldCuda3f1_addDForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, const void* state, void* eforce, const void* velems, void* df, const void* dx, double factor);
00047 
00048 
00049 } // extern "C"
00050 
00051 template<>
00052 class CudaKernelsTetrahedronFEMForceField<CudaVec3fTypes>
00053 {
00054 public:
00055     static void addForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, void* state, void* eforce, const void* velems, void* f, const void* x, const void* v)
00056     {   TetrahedronFEMForceFieldCuda3f_addForce(nbElem, nbVertex, nbElemPerVertex, elems, state, eforce, velems, f, x, v); }
00057     static void addDForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, const void* state, void* eforce, const void* velems, void* df, const void* dx, double factor)
00058     {   TetrahedronFEMForceFieldCuda3f_addDForce(nbElem, nbVertex, nbElemPerVertex, elems, state, eforce, velems, df, dx, factor); }
00059 };
00060 
00061 template<>
00062 class CudaKernelsTetrahedronFEMForceField<CudaVec3f1Types>
00063 {
00064 public:
00065     static void addForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, void* state, void* eforce, const void* velems, void* f, const void* x, const void* v)
00066     {   TetrahedronFEMForceFieldCuda3f1_addForce(nbElem, nbVertex, nbElemPerVertex, elems, state, eforce, velems, f, x, v); }
00067     static void addDForce(unsigned int nbElem, unsigned int nbVertex, unsigned int nbElemPerVertex, const void* elems, const void* state, void* eforce, const void* velems, void* df, const void* dx, double factor)
00068     {   TetrahedronFEMForceFieldCuda3f1_addDForce(nbElem, nbVertex, nbElemPerVertex, elems, state, eforce, velems, df, dx, factor); }
00069 };
00070 
00071 
00072 } // namespace cuda
00073 
00074 } // namespace gpu
00075 
00076 namespace component
00077 {
00078 
00079 namespace forcefield
00080 {
00081 
00082 using namespace gpu::cuda;
00083 
00084 template<class TCoord, class TDeriv, class TReal>
00085 void TetrahedronFEMForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::reinit(Main* m)
00086 {
00087     Data& data = m->data;
00088     m->_strainDisplacements.resize( m->_indexedElements->size() );
00089     m->_materialsStiffnesses.resize(m->_indexedElements->size() );
00090 
00091     const VecElement& elems = *m->_indexedElements;
00092 
00093     VecCoord& p = *m->mstate->getX0();
00094     (*m->f_initialPoints.beginEdit()) = p;
00095 
00096     m->_rotations.resize( m->_indexedElements->size() );
00097     m->_initialRotations.resize( m->_indexedElements->size() );
00098     m->_rotationIdx.resize(m->_indexedElements->size() *4);
00099     m->_rotatedInitialElements.resize(m->_indexedElements->size());
00100 
00101     std::vector<int> activeElems;
00102     for (unsigned int i=0;i<elems.size();i++)
00103     {
00104         {
00105             activeElems.push_back(i);
00106         }
00107     }
00108 
00109     for (unsigned int i=0;i<activeElems.size();i++)
00110     {
00111         int ei = activeElems[i];
00112     Index a = elems[ei][0];
00113     Index b = elems[ei][1];
00114     Index c = elems[ei][2];
00115     Index d = elems[ei][3];
00116     m->computeMaterialStiffness(ei,a,b,c,d);
00117     m->initLarge(ei,a,b,c,d);
00118     }
00119 
00120     std::map<int,int> nelems;
00121     for (unsigned int i=0;i<activeElems.size();i++)
00122     {
00123         int ei = activeElems[i];
00124         const Element& e = elems[ei];
00125         for (unsigned int j=0;j<e.size();j++)
00126             ++nelems[e[j]];
00127     }
00128     int nmax = 0;
00129     for (std::map<int,int>::const_iterator it = nelems.begin(); it != nelems.end(); ++it)
00130         if (it->second > nmax)
00131             nmax = it->second;
00132     int v0 = 0;
00133     int nbv = 0;
00134     if (!nelems.empty())
00135     {
00136         v0 = nelems.begin()->first;
00137         nbv = nelems.rbegin()->first - v0 + 1;
00138     }
00139     data.init(activeElems.size(), v0, nbv, nmax);
00140 
00141     nelems.clear();
00142     for (unsigned int i=0;i<activeElems.size();i++)
00143     {
00144         int ei = activeElems[i];
00145         const Element& e = elems[ei];
00146         const Coord& a = m->_rotatedInitialElements[ei][0];
00147         const Coord& b = m->_rotatedInitialElements[ei][1];
00148         const Coord& c = m->_rotatedInitialElements[ei][2];
00149         const Coord& d = m->_rotatedInitialElements[ei][3];
00150         data.setE(i, e, a, b, c, d, m->_materialsStiffnesses[ei], m->_strainDisplacements[ei]);
00151         for (unsigned int j=0;j<e.size();j++)
00152             data.setV(e[j], nelems[e[j]]++, i*e.size()+j);
00153     }
00154 }
00155 
00156 template<class TCoord, class TDeriv, class TReal>
00157 void TetrahedronFEMForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::addForce(Main* m, VecDeriv& f, const VecCoord& x, const VecDeriv& v)
00158 {
00159     if (m->needUpdateTopology)
00160     {
00161         reinit(m);
00162         m->needUpdateTopology = false;
00163     }
00164     Data& data = m->data;
00165 
00166     f.resize(x.size());
00167     Kernels::addForce(
00168         data.size(),
00169         data.nbVertex,
00170         data.nbElementPerVertex,
00171         data.elems.deviceRead(),
00172         data.state.deviceWrite(),
00173         data.eforce.deviceWrite(),
00174         data.velems.deviceRead(),
00175         (      Deriv*)f.deviceWrite() + data.vertex0,
00176         (const Coord*)x.deviceRead()  + data.vertex0,
00177         (const Deriv*)v.deviceRead()  + data.vertex0);
00178 
00179 #if 0
00180     // compare with CPU version
00181 
00182     const VecElement& elems = *m->_indexedElements;
00183     for (unsigned int i=0;i<elems.size();i++)
00184     {
00185     Index a = elems[i][0];
00186     Index b = elems[i][1];
00187     Index c = elems[i][2];
00188     Index d = elems[i][3];
00189         typename Main::Transformation Rt;
00190         m->computeRotationLarge(Rt, x, a, b, c);
00191         const GPUElementState& s = data.state[i];
00192         const GPUElement& e = data.elems[i];
00193         Mat3x3f Rdiff = Rt-s.Rt;
00194         if ((Rdiff[0].norm2()+Rdiff[1].norm2()+Rdiff[2].norm2()) > 0.000001f)
00195         {
00196             std::cout << "CPU Rt "<<i<<" = "<<Rt<<std::endl;
00197             std::cout << "GPU Rt "<<i<<" = "<<s.Rt<<std::endl;
00198             std::cout << "DIFF   "<<i<<" = "<<Rdiff<<std::endl;
00199         }
00200         Coord xb = Rt*(x[b]-x[a]);
00201         Coord xc = Rt*(x[c]-x[a]);
00202         Coord xd = Rt*(x[d]-x[a]);
00203 
00204         typename Main::Displacement D;
00205         D[0] = 0;
00206     D[1] = 0;
00207     D[2] = 0;
00208     D[3] = m->_rotatedInitialElements[i][1][0] - xb[0];
00209     D[4] = m->_rotatedInitialElements[i][1][1] - xb[1];
00210     D[5] = m->_rotatedInitialElements[i][1][2] - xb[2];
00211     D[6] = m->_rotatedInitialElements[i][2][0] - xc[0];
00212     D[7] = m->_rotatedInitialElements[i][2][1] - xc[1];
00213     D[8] = m->_rotatedInitialElements[i][2][2] - xc[2];
00214     D[9] = m->_rotatedInitialElements[i][3][0] - xd[0];
00215     D[10]= m->_rotatedInitialElements[i][3][1] - xd[1];
00216     D[11]= m->_rotatedInitialElements[i][3][2] - xd[2];
00217         Vec<6,Real> S = -((m->_materialsStiffnesses[i]) * ((m->_strainDisplacements[i]).multTranspose(D)))*(e.bx);
00218 
00219         Vec<6,Real> Sdiff = S-s.S;
00220 
00221         if (Sdiff.norm2() > 0.0001f)
00222         {
00223             std::cout << "    D "<<i<<" = "<<D<<std::endl;
00224             std::cout << "CPU S "<<i<<" = "<<S<<std::endl;
00225             std::cout << "GPU S "<<i<<" = "<<s.S<<std::endl;
00226             std::cout << "DIFF   "<<i<<" = "<<Sdiff<<std::endl;
00227         }
00228 
00229     }
00230 #endif
00231 
00232 }
00233 
00234 template<class TCoord, class TDeriv, class TReal>
00235 void TetrahedronFEMForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::addDForce (Main* m, VecDeriv& df, const VecDeriv& dx, double kFactor, double /*bFactor*/)
00236 {
00237     Data& data = m->data;
00238     df.resize(dx.size());
00239     Kernels::addDForce(
00240         data.size(),
00241         data.nbVertex,
00242         data.nbElementPerVertex,
00243         data.elems.deviceRead(),
00244         data.state.deviceRead(),
00245         data.eforce.deviceWrite(),
00246         data.velems.deviceRead(),
00247         (      Deriv*)df.deviceWrite() + data.vertex0,
00248         (const Deriv*)dx.deviceRead()  + data.vertex0,
00249         kFactor);
00250 }
00251 
00252 // I know using macros is bad design but this is the only way not to repeat the code for all CUDA types
00253 #define CudaTetrahedronFEMForceField_ImplMethods(T) \
00254     template<> void TetrahedronFEMForceField< T >::reinit() \
00255     { data.reinit(this); } \
00256     template<> void TetrahedronFEMForceField< T >::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& v) \
00257     { data.addForce(this, f, x, v); } \
00258     template<> void TetrahedronFEMForceField< T >::addDForce(VecDeriv& df, const VecDeriv& dx, double kFactor, double bFactor) \
00259     { data.addDForce(this, df, dx, kFactor, bFactor); }
00260 
00261 CudaTetrahedronFEMForceField_ImplMethods(gpu::cuda::CudaVec3fTypes);
00262 CudaTetrahedronFEMForceField_ImplMethods(gpu::cuda::CudaVec3f1Types);
00263 
00264 
00265 #undef CudaTetrahedronFEMForceField_ImplMethods
00266 
00267 } // namespace forcefield
00268 
00269 } // namespace component
00270 
00271 } // namespace sofa
00272 
00273 #endif

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