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_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 }
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 }
00073
00074 }
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
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 )
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
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 }
00268
00269 }
00270
00271 }
00272
00273 #endif