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 #include <sofa/component/forcefield/TriangularAnisotropicFEMForceField.h>
00026 #include <sofa/core/ObjectFactory.h>
00027 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00028 #include <sofa/helper/gl/template.h>
00029 #include <sofa/component/topology/TriangleData.inl>
00030 #include <sofa/component/topology/EdgeData.inl>
00031 #include <sofa/component/topology/PointData.inl>
00032 #include <sofa/helper/system/gl.h>
00033 #include <fstream>
00034 #include <iostream>
00035 #include <vector>
00036 #include <algorithm>
00037 #include <sofa/defaulttype/Vec3Types.h>
00038 #include <assert.h>
00039
00040 #ifdef _WIN32
00041 #include <windows.h>
00042 #endif
00043
00044
00045
00046
00047 namespace sofa
00048 {
00049
00050 namespace component
00051 {
00052
00053 namespace forcefield
00054 {
00055
00056 using namespace sofa::defaulttype;
00057 using namespace sofa::component::topology;
00058 using namespace core::componentmodel::topology;
00059
00060 using std::cerr;
00061 using std::cout;
00062 using std::endl;
00063
00064 SOFA_DECL_CLASS(TriangularAnisotropicFEMForceField)
00065
00066 template <class DataTypes>
00067 TriangularAnisotropicFEMForceField<DataTypes>::TriangularAnisotropicFEMForceField()
00068 : f_young2(initData(&f_young2,(Real)(0.5*Inherited::f_young.getValue()),"transverseYoungModulus","Young modulus along transverse direction"))
00069 , f_theta(initData(&f_theta,(Real)(0.0),"fiberAngle","Fiber angle in global reference frame (in degrees)"))
00070 , f_fiberCenter(initData(&f_fiberCenter,"fiberCenter","Concentric fiber center in global reference frame"))
00071 , showFiber(initData(&showFiber,true,"showFiber","Flag activating rendering of fiber directions within each triangle"))
00072 {
00073
00074 }
00075
00076 template< class DataTypes>
00077 void TriangularAnisotropicFEMForceField<DataTypes>::TRQSTriangleCreationFunction (int triangleIndex, void* param,
00078 TriangleInformation &,
00079 const Triangle& ,
00080 const sofa::helper::vector< unsigned int > &,
00081 const sofa::helper::vector< double >&)
00082 {
00083 TriangularAnisotropicFEMForceField<DataTypes> *ff= (TriangularAnisotropicFEMForceField<DataTypes> *)param;
00084 if (ff) {
00085
00086 const Triangle &t = ff->_topology->getTriangle(triangleIndex);
00087
00088 Index a = t[0];
00089 Index b = t[1];
00090 Index c = t[2];
00091
00092 switch(ff->method)
00093 {
00094 case SMALL :
00095 ff->computeMaterialStiffness(triangleIndex, a, b, c);
00096 ff->initSmall();
00097 break;
00098 case LARGE :
00099 ff->computeMaterialStiffness(triangleIndex, a, b, c);
00100 ff->initLarge(triangleIndex,a,b,c);
00101 break;
00102 }
00103 }
00104 }
00105
00106 template< class DataTypes>
00107 void TriangularAnisotropicFEMForceField<DataTypes>::init()
00108 {
00109 Inherited::init();
00110
00111 _topology = getContext()->getMeshTopology();
00112
00113
00114 }
00115
00116 template <class DataTypes>void TriangularAnisotropicFEMForceField<DataTypes>::reinit()
00117 {
00118 f_poisson2.setValue(Inherited::f_poisson.getValue()*(f_young2.getValue()/Inherited::f_young.getValue()));
00119 Inherited::reinit();
00120 }
00121
00122 template <class DataTypes>
00123 void TriangularAnisotropicFEMForceField<DataTypes>::computeMaterialStiffness(int i, Index& v1, Index& v2, Index& v3)
00124 {
00125 TriangleInformation *tinfo = &Inherited::triangleInfo[i];
00126
00127 Real Q11, Q12, Q22, Q66;
00128 Q11 = Inherited::f_young.getValue()/(1-Inherited::f_poisson.getValue()*f_poisson2.getValue());
00129 Q12 = Inherited::f_poisson.getValue()*f_young2.getValue()/(1-Inherited::f_poisson.getValue()*f_poisson2.getValue());
00130 Q22 = f_young2.getValue()/(1-Inherited::f_poisson.getValue()*f_poisson2.getValue());
00131 Q66 = (Real)(Inherited::f_young.getValue() / (2.0*(1 + Inherited::f_poisson.getValue())));
00132
00133 Mat<3,3,Real> bary,baryInv;
00134 bary[0] = (*Inherited::_initialPoints)[v2]-(*Inherited::_initialPoints)[v1];
00135 bary[1] = (*Inherited::_initialPoints)[v3]-(*Inherited::_initialPoints)[v1];
00136 bary[2] = cross(bary[0],bary[1]);
00137 Coord fiberDir;
00138 if (!f_fiberCenter.getValue().empty())
00139 {
00140 Coord tcenter = ((*Inherited::_initialPoints)[v1]+(*Inherited::_initialPoints)[v2]+(*Inherited::_initialPoints)[v3])*(Real)(1.0/3.0);
00141 Coord fcenter = f_fiberCenter.getValue()[0];
00142 fiberDir = cross(bary[2],fcenter-tcenter);
00143 }
00144 else
00145 {
00146 double theta = (double)f_theta.getValue()*M_PI/180.0;
00147
00148
00149 fiberDir = Coord((Real)cos(theta), (Real)sin(theta), 0);
00150 }
00151 bary.transpose();
00152 baryInv.invert(bary);
00153 if (i >= (int) fiberDirRefs.size())
00154 fiberDirRefs.resize(i+1);
00155 Deriv& fiberDirRef = fiberDirRefs[i];
00156 fiberDirRef = baryInv * fiberDir;
00157 fiberDirRef[2] = 0;
00158 fiberDirRef.normalize();
00159
00160 Real c, s, c2, s2, c3, s3,c4, s4;
00161 c = fiberDirRef[0];
00162 s = fiberDirRef[1];
00163 c2 = c*c;
00164 s2 = s*s;
00165 c3 = c2*c;
00166 s3 = s2*s;
00167 s4 = s2*s2;
00168 c4 = c2*c2;
00169
00170 Real K11= c4 * Q11 + 2 *c2*s2 *(Q12+2*Q66) + s4 * Q22;
00171 Real K12 = c2*s2 * (Q11+Q22-4*Q66) + (c4+ s4) * Q12;
00172 Real K22 = s4* Q11 + 2 *c2*s2 * (Q12+2*Q66) + c4 * Q22;
00173 Real K16 = c3 * s * (Q11 - Q12) + c*s3* (Q12 - Q22) - 2*c*s* (c2 -s2) * Q66;
00174 Real K26 = c*s3 * (Q11-Q12) + c3*s* (Q12 - Q22) + 2*c*s* (c2 -s2) * Q66;
00175 Real K66 = c2*s2 * (Q11+Q22-2*Q12 - 2*Q66) + (c4+ s4) * Q66;
00176
00177 tinfo->materialMatrix[0][0] = K11;
00178 tinfo->materialMatrix[0][1] = K12;
00179 tinfo->materialMatrix[0][2] = K16;
00180 tinfo->materialMatrix[1][0] = K12;
00181 tinfo->materialMatrix[1][1] = K22;
00182 tinfo->materialMatrix[1][2] = K26;
00183 tinfo->materialMatrix[2][0] = K16;
00184 tinfo->materialMatrix[2][1] = K26;
00185 tinfo->materialMatrix[2][2] = K66;
00186
00187 tinfo->materialMatrix *= (Real)(1.0/12.0);
00188
00189 cout << "Young1=" << Inherited::f_young.getValue() << endl;
00190 cout << "Young2=" << f_young2.getValue() << endl;
00191 cout << "Poisson1=" << Inherited::f_poisson.getValue() << endl;
00192 cout << "Poisson2=" << f_poisson2.getValue() << endl;
00193 }
00194
00195
00196 template <class DataTypes>void TriangularAnisotropicFEMForceField<DataTypes>::draw()
00197 {
00198 glPolygonOffset(1.0, 2.0);
00199 glEnable(GL_POLYGON_OFFSET_FILL);
00200 Inherited::draw();
00201 glDisable(GL_POLYGON_OFFSET_FILL);
00202 if (!getContext()->getShowForceFields())
00203 return;
00204 if (showFiber.getValue() && !fiberDirRefs.empty())
00205 {
00206 const VecCoord& x = *this->mstate->getX();
00207 int nbTriangles=_topology->getNbTriangles();
00208 glColor3f(1,1,1);
00209 glBegin(GL_LINES);
00210
00211 int i;
00212 for(i=0;i<nbTriangles; ++i)
00213 {
00214 Index a = _topology->getTriangle(i)[0];
00215 Index b = _topology->getTriangle(i)[1];
00216 Index c = _topology->getTriangle(i)[2];
00217 Coord center = (x[a]+x[b]+x[c])/3;
00218 Coord d = (x[b]-x[a])*fiberDirRefs[i][0] + (x[c]-x[a])*fiberDirRefs[i][1];
00219 d*=0.4;
00220 helper::gl::glVertexT(center-d);
00221 helper::gl::glVertexT(center+d);
00222 }
00223 glEnd();
00224 }
00225 }
00226
00227
00228
00229 int TriangularAnisotropicFEMForceFieldClass = core::RegisterObject("Triangular finite element model using anisotropic material")
00230 #ifndef SOFA_FLOAT
00231 .add< TriangularAnisotropicFEMForceField<Vec3dTypes> >()
00232 #endif
00233 #ifndef SOFA_DOUBLE
00234 .add< TriangularAnisotropicFEMForceField<Vec3fTypes> >()
00235 #endif
00236 ;
00237
00238 #ifndef SOFA_FLOAT
00239 template class TriangularAnisotropicFEMForceField<Vec3dTypes>;
00240 #endif
00241 #ifndef SOFA_DOUBLE
00242 template class TriangularAnisotropicFEMForceField<Vec3fTypes>;
00243 #endif
00244
00245
00246 }
00247
00248 }
00249
00250 }