diff --git a/Solver/elasticitySolver.cpp b/Solver/elasticitySolver.cpp index eb86ec0d4b697e34d1f9bf5123d79940085a7089..262a8329b0154283ddb242fd18b6eb1d23eb352e 100644 --- a/Solver/elasticitySolver.cpp +++ b/Solver/elasticitySolver.cpp @@ -17,20 +17,51 @@ #include "quadratureRules.h" #include "solverField.h" #include "MPoint.h" +#include "DILevelset.h" #if defined(HAVE_POST) #include "PView.h" #include "PViewData.h" #endif +static void printLinearSystem(linearSystemCSRTaucs<double> *lsys) +{ + int *startIndex; + int *columns; + double *values; + lsys->getMatrix(startIndex, columns, values); + for(int i = 0; i < lsys->getNbUnk(); i++){ + std::cout<<"a "; + for(int j = 0; j < lsys->getNbUnk(); j++){ + double val = 0.; + for(int k = startIndex[i]; k < startIndex[i+1]; k++){ + if(columns[k] == j) {val = values[k]; break;} + } + std::cout<< val <<" "; + } + std::cout<<std::endl; + }std::cout<<std::endl; + for(int i = 0; i < lsys->getNbUnk(); i++) { + double val; lsys->getFromRightHandSide(i,val); + std::cout<<"b "<<val<<std::endl; + }std::cout<<std::endl; + for(int i = 0; i < lsys->getNbUnk(); i++) { + double val; lsys->getFromSolution(i,val); + std::cout<<"x "<<val<<std::endl; + } +} + void elasticitySolver::setMesh(const std::string &meshFileName) { pModel = new GModel(); pModel->readMSH(meshFileName.c_str()); _dim = pModel->getNumRegions() ? 3 : 2; + if (LagSpace) delete LagSpace; - if (_dim==3) LagSpace=new VectorLagrangeFunctionSpace(_tag); - if (_dim==2) LagSpace=new VectorLagrangeFunctionSpace(_tag,VectorLagrangeFunctionSpace::VECTOR_X,VectorLagrangeFunctionSpace::VECTOR_Y); + if (_dim==3) LagSpace=new VectorLagrangeFunctionSpaceOfParent(_tag); + if (_dim==2) LagSpace=new VectorLagrangeFunctionSpaceOfParent(_tag,VectorLagrangeFunctionSpaceOfParent::VECTOR_X,VectorLagrangeFunctionSpaceOfParent::VECTOR_Y); + if (LagrangeMultiplierSpace) delete LagrangeMultiplierSpace; + LagrangeMultiplierSpace = new ScalarLagrangeFunctionSpace(_tag+1); } void elasticitySolver::readInputFile(const std::string &fn) @@ -47,12 +78,26 @@ void elasticitySolver::readInputFile(const std::string &fn) field.g = new groupOfElements (_dim, physical); elasticFields.push_back(field); } + if (!strcmp(what, "LagrangeMultipliers")){ + LagrangeMultiplierField field; + int physical; + double d1, d2, d3, val; + if(fscanf(f, "%d %lf %lf %lf %lf %lf %d", &physical, &field._tau, + &d1, &d2, &d3, &val, &field._tag) != 7) return; + field._tag = _tag; + field._d = SVector3(d1, d2, d3); + field._f = simpleFunction<double>(val); + field.g = new groupOfElements (_dim - 1, physical); + LagrangeMultiplierFields.push_back(field); + } else if (!strcmp(what, "Void")){ - // elasticField field; - // create enrichment ... - // create the group ... - // assign a tag - // elasticFields.push_back(field); + elasticField field; + int physical; + if(fscanf(f, "%d", &physical) != 1) return; + field._E = field._nu = 0; + field.g = new groupOfElements (_dim, physical); + field._tag = 0; + elasticFields.push_back(field); } else if (!strcmp(what, "NodeDisplacement")){ double val; @@ -139,6 +184,20 @@ void elasticitySolver::readInputFile(const std::string &fn) if(fscanf(f, "%s", name) != 1) return; setMesh(name); } + else if (!strcmp(what, "CutMeshPlane")){ + double a, b, c, d; + if(fscanf(f, "%lf %lf %lf %lf", &a, &b, &c, &d) != 4) return; + int tag=1; + gLevelsetPlane ls(a,b,c,d,tag); + pModel = pModel->buildCutGModel(&ls); + } + else if (!strcmp(what, "CutMeshSphere")){ + double x, y, z, r; + if(fscanf(f, "%lf %lf %lf %lf", &x, &y, &z, &r) != 4) return; + int tag=1; + gLevelsetSphere ls(x,y,z,r,tag); + pModel = pModel->buildCutGModel(&ls); + } else { Msg::Error("Invalid input : %s", what); // return; @@ -164,23 +223,30 @@ void elasticitySolver::solve() // give priority to fixations : when a dof is fixed, it cannot be // numbered afterwards - std::cout << "Dirichlet BC"<< std::endl; + // Dirichlet conditions for (unsigned int i = 0; i < allDirichlet.size(); i++) { FilterDofComponent filter(allDirichlet[i]._comp); FixNodalDofs(*LagSpace,allDirichlet[i].g->begin(),allDirichlet[i].g->end(),*pAssembler,allDirichlet[i]._f,filter); } - - // we number the dofs : when a dof is numbered, it cannot be numbered - // again with another number. + // LagrangeMultipliers + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i) + { + NumberDofs(*LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), *pAssembler); + } + // Elastic Fields for (unsigned int i = 0; i < elasticFields.size(); ++i) { - NumberDofs(*LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(),*pAssembler); + if(elasticFields[i]._E != 0.) + NumberDofs(*LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(),*pAssembler); } - - // Now we start the assembly process - // First build the force vector - + // Voids + for (unsigned int i = 0; i < elasticFields.size(); ++i) + { + if(elasticFields[i]._E == 0.) + FixVoidNodalDofs(*LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(), *pAssembler); + } + // Neumann conditions GaussQuadrature Integ_Boundary(GaussQuadrature::Val); std::cout << "Neumann BC"<< std::endl; for (unsigned int i = 0; i < allNeumann.size(); i++) @@ -188,20 +254,37 @@ void elasticitySolver::solve() LoadTerm<SVector3> Lterm(*LagSpace,allNeumann[i]._f); Assemble(Lterm,*LagSpace,allNeumann[i].g->begin(),allNeumann[i].g->end(),Integ_Boundary,*pAssembler); } + // Assemble cross term, laplace term and rhs term for LM + GaussQuadrature Integ_LagrangeMult(GaussQuadrature::ValVal); + GaussQuadrature Integ_Laplace(GaussQuadrature::GradGrad); + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); i++) + { + LagrangeMultiplierTerm LagTerm(*LagSpace, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i]._d); + Assemble(LagTerm, *LagSpace, *LagrangeMultiplierSpace, + LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), Integ_LagrangeMult, *pAssembler); -// bulk material law + LaplaceTerm<double,double> LapTerm(*LagrangeMultiplierSpace, LagrangeMultiplierFields[i]._tau); + Assemble(LapTerm, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), Integ_Laplace, *pAssembler); + LoadTerm<double> Lterm(*LagrangeMultiplierSpace, LagrangeMultiplierFields[i]._f); + Assemble(Lterm, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), Integ_Boundary, *pAssembler); + } + // Assemble elastic term for GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); for (unsigned int i = 0; i < elasticFields.size(); i++) { IsotropicElasticTerm Eterm(*LagSpace,elasticFields[i]._E,elasticFields[i]._nu); -// LaplaceTerm<SVector3,SVector3> Eterm(*LagSpace); Assemble(Eterm,*LagSpace,elasticFields[i].g->begin(),elasticFields[i].g->end(),Integ_Bulk,*pAssembler); } + printf("nDofs=%d\n",pAssembler->sizeOfR()); + printf("nFixed=%d\n",pAssembler->sizeOfF()); printf("-- done assembling!\n"); lsys->systemSolve(); printf("-- done solving!\n"); + + printLinearSystem(lsys); + double energ=0; for (unsigned int i = 0; i < elasticFields.size(); i++) { @@ -214,7 +297,6 @@ void elasticitySolver::solve() } - #if defined(HAVE_POST) static double vonMises(dofManager<double> *a, MElement *e, @@ -259,42 +341,91 @@ static double vonMises(dofManager<double> *a, MElement *e, PView* elasticitySolver::buildDisplacementView (const std::string &postFileName) { + std::cout << "build Displacement View"<< std::endl; std::set<MVertex*> v; + std::map<MVertex*,MElement*> vCut; for (unsigned int i = 0; i < elasticFields.size(); ++i) { - for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) - { + if(elasticFields[i]._E == 0.) continue; + for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it){ MElement *e=*it; - for (int j = 0; j < e->getNumVertices(); ++j) v.insert(e->getVertex(j)); + if(e->getParent()) { + for (int j = 0; j < e->getNumVertices(); ++j) { + if(vCut.find(e->getVertex(j)) == vCut.end()) + vCut[e->getVertex(j)] = e->getParent(); + } + } + else { + for (int j = 0; j < e->getNumVertices(); ++j) + v.insert(e->getVertex(j)); + } } } std::map<int, std::vector<double> > data; SolverField<SVector3> Field(pAssembler, LagSpace); - for ( std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it) - { + for (std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it){ SVector3 val; MPoint p(*it); Field.f(&p,0,0,0,val); std::vector<double> vec(3);vec[0]=val(0);vec[1]=val(1);vec[2]=val(2); data[(*it)->getNum()]=vec; } + for (std::map<MVertex*,MElement*>::iterator it = vCut.begin(); it != vCut.end(); ++it){ + SVector3 val; + double uvw[3]; + double xyz[3] = {it->first->x(), it->first->y(), it->first->z()}; + it->second->xyz2uvw(xyz, uvw); + Field.f(it->second,uvw[0],uvw[1],uvw[2],val); + std::vector<double> vec(3);vec[0]=val(0);vec[1]=val(1);vec[2]=val(2); + data[it->first->getNum()]=vec; + } + PView *pv = new PView (postFileName, "NodeData", pModel, data, 0.0); + return pv; +} + +PView* elasticitySolver::buildLagrangeMultiplierView (const std::string &postFileName) +{ + std::cout << "build Lagrange Multiplier View"<< std::endl; + if(!LagrangeMultiplierSpace) return new PView(); + std::set<MVertex*> v; + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i) + { + for(groupOfElements::elementContainer::const_iterator it = LagrangeMultiplierFields[i].g->begin(); it != LagrangeMultiplierFields[i].g->end(); ++it) + { + MElement *e = *it; + for (int j = 0; j < e->getNumVertices(); ++j) v.insert(e->getVertex(j)); + } + } + std::map<int, std::vector<double> > data; + SolverField<double> Field(pAssembler, LagrangeMultiplierSpace); + for(std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it) + { + double val; + MPoint p(*it); + Field.f(&p, 0, 0, 0, val); + std::vector<double> vec; + vec.push_back(val); + data[(*it)->getNum()] = vec; + } PView *pv = new PView (postFileName, "NodeData", pModel, data, 0.0); return pv; } PView *elasticitySolver::buildElasticEnergyView(const std::string &postFileName) { + std::cout << "build Elastic Energy View"<< std::endl; std::map<int, std::vector<double> > data; GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); for (unsigned int i = 0; i < elasticFields.size(); ++i) { + if(elasticFields[i]._E == 0.) continue; SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); ScalarTermConstant One(1.0); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) { - MElement *e=*it; + MElement *e = *it; double energ; double vol; IntPt *GP; @@ -303,7 +434,7 @@ PView *elasticitySolver::buildElasticEnergyView(const std::string &postFileName) One.get(e,npts,GP,vol); std::vector<double> vec; vec.push_back(energ/vol); - data[(*it)->getNum()]=vec; + data[e->getNum()]=vec; } } PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0); @@ -311,7 +442,7 @@ PView *elasticitySolver::buildElasticEnergyView(const std::string &postFileName) } PView *elasticitySolver::buildVonMisesView(const std::string &postFileName) -{ +{std::cout << "build elastic view"<< std::endl; std::map<int, std::vector<double> > data; GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); for (unsigned int i = 0; i < elasticFields.size(); ++i) @@ -337,7 +468,13 @@ PView *elasticitySolver::buildVonMisesView(const std::string &postFileName) #else -PView* elasticitySolver::buildDisplacementView (const std::string &postFileName) +PView* elasticitySolver::buildDisplacementView(const std::string &postFileName) +{ + Msg::Error("Post-pro module not available"); + return 0; +} + +PView* elasticitySolver::buildLagrangeMultiplierView (const std::string &postFileName) { Msg::Error("Post-pro module not available"); return 0; @@ -349,5 +486,10 @@ PView* elasticitySolver::buildElasticEnergyView(const std::string &postFileName) return 0; } +PView* elasticitySolver::buildVonMisesView(const std::string &postFileName) +{ + Msg::Error("Post-pro module not available"); + return 0; +} #endif diff --git a/Solver/elasticitySolver.h b/Solver/elasticitySolver.h index fe1d228d5b61a1c7070a748ce3cda3ee77d410f8..b70f3c25383b7b45574ffc45b16cf3dbad0476b7 100644 --- a/Solver/elasticitySolver.h +++ b/Solver/elasticitySolver.h @@ -17,6 +17,15 @@ class GModel; class PView; class groupOfElements; +struct LagrangeMultiplierField { + int _tag; + groupOfElements *g; + double _tau; + SVector3 _d; + simpleFunction<double> _f; + LagrangeMultiplierField() : g(0),_tag(0){} +}; + struct elasticField { int _tag; // tag for the dofManager groupOfElements *g; // support for this field @@ -54,25 +63,29 @@ class elasticitySolver int _dim, _tag; dofManager<double> *pAssembler; FunctionSpace<SVector3> *LagSpace; + FunctionSpace<double> *LagrangeMultiplierSpace; // young modulus and poisson coefficient per physical std::vector<elasticField> elasticFields; + std::vector<LagrangeMultiplierField> LagrangeMultiplierFields; // neumann BC std::vector<neumannBC> allNeumann; // dirichlet BC std::vector<dirichletBC> allDirichlet; public: - elasticitySolver(int tag) : _tag(tag),LagSpace(0),pAssembler(0) {} + elasticitySolver(int tag) : _tag(tag),LagSpace(0),pAssembler(0),LagrangeMultiplierSpace(0) {} virtual ~elasticitySolver() { if (LagSpace) delete LagSpace; + if (LagrangeMultiplierSpace) delete LagrangeMultiplierSpace; if (pAssembler) delete pAssembler; } void readInputFile(const std::string &meshFileName); - void setMesh(const std::string &meshFileName); + virtual void setMesh(const std::string &meshFileName); virtual void solve(); virtual PView *buildDisplacementView(const std::string &postFileName); + virtual PView *buildLagrangeMultiplierView(const std::string &posFileName); virtual PView *buildElasticEnergyView(const std::string &postFileName); virtual PView *buildVonMisesView(const std::string &postFileName); // std::pair<PView *, PView*> buildErrorEstimateView diff --git a/Solver/functionSpace.cpp b/Solver/functionSpace.cpp index fed1efa9045ff667d19c0f1529b96ac7497f6b52..47067cd4ad8199db126da2018e7779bdb33ecb77 100644 --- a/Solver/functionSpace.cpp +++ b/Solver/functionSpace.cpp @@ -12,4 +12,4 @@ #include "functionSpace.h" const SVector3 VectorLagrangeFunctionSpace::BasisVectors[3]={SVector3(1,0,0),SVector3(0,1,0),SVector3(0,0,1)}; - +const SVector3 VectorLagrangeFunctionSpaceOfParent::BasisVectors[3]={SVector3(1,0,0),SVector3(0,1,0),SVector3(0,0,1)}; diff --git a/Solver/functionSpace.h b/Solver/functionSpace.h index 53ea4afd43807e5aa2aa78beb1a753c7fc0cac3e..e5bb028499d6d57f8da6aaa1eaa57948f8703a23 100644 --- a/Solver/functionSpace.h +++ b/Solver/functionSpace.h @@ -54,12 +54,9 @@ class FunctionSpace : public FunctionSpaceBase typedef typename TensorialTraits<T>::GradType GradType; typedef typename TensorialTraits<T>::HessType HessType; virtual void f(MElement *ele, double u, double v, double w, std::vector<ValType> &vals) = 0; - virtual void gradf(MElement *ele, double u, double v, double w, - std::vector<GradType> &grads) = 0; - virtual void gradfuvw(MElement *ele, double u, double v, double w, - std::vector<GradType> &grads) {} // should return to pure virtual once all is done. - virtual void hessfuvw(MElement *ele, double u, double v, double w, - std::vector<HessType> &hess) = 0; + virtual void gradf(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) = 0; + virtual void gradfuvw(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) {} // should return to pure virtual once all is done. + virtual void hessfuvw(MElement *ele, double u, double v, double w, std::vector<HessType> &hess) = 0; virtual int getNumKeys(MElement *ele) = 0; // if one needs the number of dofs virtual void getKeys(MElement *ele, std::vector<Dof> &keys) = 0; }; @@ -85,17 +82,24 @@ class ScalarLagrangeFunctionSpace : public FunctionSpace<double> virtual int getId(void) const {return _iField;} virtual void f(MElement *ele, double u, double v, double w, std::vector<ValType> &vals) { - if (ele->getParent()) ele = ele->getParent(); + if(ele->getParent()) { + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + ele->movePointFromParentSpaceToElementSpace(u, v, w); + } + } int ndofs = ele->getNumVertices(); int curpos = vals.size(); vals.resize(curpos + ndofs); ele->getShapeFunctions(u, v, w, &(vals[curpos])); } - // Fonction renvoyant un vecteur contenant le grandient de chaque FF virtual void gradf(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) { - if (ele->getParent()) ele = ele->getParent(); + if(ele->getParent()) { + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + ele->movePointFromParentSpaceToElementSpace(u, v, w); + } + } int ndofs = ele->getNumVertices(); grads.reserve(grads.size() + ndofs); double gradsuvw[256][3]; @@ -110,9 +114,14 @@ class ScalarLagrangeFunctionSpace : public FunctionSpace<double> invjac[1][0] * gradsuvw[i][0] + invjac[1][1] * gradsuvw[i][1] + invjac[1][2] * gradsuvw[i][2], invjac[2][0] * gradsuvw[i][0] + invjac[2][1] * gradsuvw[i][1] + invjac[2][2] * gradsuvw[i][2])); } - // Fonction renvoyant un vecteur contenant le hessien [][] de chaque FF dans l'espace ISOPARAMETRIQUE + // Fonction renvoyant un vecteur contenant le hessien [][] de chaque FF dans l'espace ISOPARAMETRIQUE virtual void hessfuvw(MElement *ele, double u, double v, double w, std::vector<HessType> &hess) { + if(ele->getParent()) { + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + ele->movePointFromParentSpaceToElementSpace(u, v, w); + } + } int ndofs = ele->getNumVertices(); // ATTENTION RETOURNE LE NBBRE DE NOEUDS ET PAS LE NBRE DE DDL hess.reserve(hess.size() + ndofs); // permet de mettre les composantes suivantes à la suite du vecteur double hessuvw[256][3][3]; @@ -128,27 +137,26 @@ class ScalarLagrangeFunctionSpace : public FunctionSpace<double> virtual void gradfuvw(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) { - if (ele->getParent()) ele = ele->getParent(); + if(ele->getParent()) { + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + ele->movePointFromParentSpaceToElementSpace(u, v, w); + } + } int ndofs = ele->getNumVertices(); grads.reserve(grads.size() + ndofs); double gradsuvw[256][3]; ele->getGradShapeFunctions(u, v, w, gradsuvw); for (int i = 0; i < ndofs; ++i) - grads.push_back(GradType( - gradsuvw[i][0], - gradsuvw[i][1], - gradsuvw[i][2])); + grads.push_back(GradType(gradsuvw[i][0], gradsuvw[i][1], gradsuvw[i][2])); } virtual int getNumKeys(MElement *ele) { - if (ele->getParent()) ele = ele->getParent(); return ele->getNumVertices(); } virtual void getKeys(MElement *ele, std::vector<Dof> &keys) // appends ... { - if (ele->getParent()) ele = ele->getParent(); int ndofs = ele->getNumVertices(); keys.reserve(keys.size() + ndofs); for (int i = 0; i < ndofs; ++i) @@ -156,6 +164,92 @@ class ScalarLagrangeFunctionSpace : public FunctionSpace<double> } }; +class ScalarLagrangeFunctionSpaceOfParent : public FunctionSpace<double> +{ + public: + typedef TensorialTraits<double>::ValType ValType; + typedef TensorialTraits<double>::GradType GradType; + typedef TensorialTraits<double>::HessType HessType; + + protected: + int _iField; // field number (used to build dof keys) + + private: + virtual void getKeys(MVertex *ver, std::vector<Dof> &keys) + { + keys.push_back(Dof(ver->getNum(), _iField)); + } + public: + ScalarLagrangeFunctionSpaceOfParent(int i = 0) : _iField(i) {} + virtual int getId(void) const {return _iField;} + virtual void f(MElement *ele, double u, double v, double w, std::vector<ValType> &vals) + { + if(ele->getParent()) ele = ele->getParent(); + int ndofs = ele->getNumVertices(); + int curpos = vals.size(); + vals.resize(curpos + ndofs); + ele->getShapeFunctions(u, v, w, &(vals[curpos])); + } + + // Fonction renvoyant un vecteur contenant le grandient de chaque FF + virtual void gradf(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) + { + if(ele->getParent()) ele = ele->getParent(); + int ndofs = ele->getNumVertices(); + grads.reserve(grads.size() + ndofs); + double gradsuvw[256][3]; + ele->getGradShapeFunctions(u, v, w, gradsuvw); + double jac[3][3]; + double invjac[3][3]; + const double detJ = ele->getJacobian(u, v, w, jac); // redondant : on fait cet appel a l'exterieur + inv3x3(jac, invjac); + for (int i = 0; i < ndofs; ++i) + grads.push_back(GradType( + invjac[0][0] * gradsuvw[i][0] + invjac[0][1] * gradsuvw[i][1] + invjac[0][2] * gradsuvw[i][2], + invjac[1][0] * gradsuvw[i][0] + invjac[1][1] * gradsuvw[i][1] + invjac[1][2] * gradsuvw[i][2], + invjac[2][0] * gradsuvw[i][0] + invjac[2][1] * gradsuvw[i][1] + invjac[2][2] * gradsuvw[i][2])); + } + // Fonction renvoyant un vecteur contenant le hessien [][] de chaque FF dans l'espace ISOPARAMETRIQUE + virtual void hessfuvw(MElement *ele, double u, double v, double w, std::vector<HessType> &hess) + { + if(ele->getParent()) ele = ele->getParent(); + int ndofs = ele->getNumVertices(); // ATTENTION RETOURNE LE NBBRE DE NOEUDS ET PAS LE NBRE DE DDL + hess.reserve(hess.size() + ndofs); // permet de mettre les composantes suivantes à la suite du vecteur + double hessuvw[256][3][3]; + ele->getHessShapeFunctions(u, v, w, hessuvw); + HessType hesst; + for (int i = 0; i < ndofs; ++i){ + hesst(0,0) = hessuvw[i][0][0]; hesst(0,1) = hessuvw[i][0][1]; hesst(0,2) = hessuvw[i][0][2]; + hesst(1,0) = hessuvw[i][1][0]; hesst(1,1) = hessuvw[i][1][1]; hesst(1,2) = hessuvw[i][1][2]; + hesst(2,0) = hessuvw[i][2][0]; hesst(2,1) = hessuvw[i][2][1]; hesst(2,2) = hessuvw[i][2][2]; + hess.push_back(hesst); + } + } + virtual void gradfuvw(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) + { + if(ele->getParent()) ele = ele->getParent(); + int ndofs = ele->getNumVertices(); + grads.reserve(grads.size() + ndofs); + double gradsuvw[256][3]; + ele->getGradShapeFunctions(u, v, w, gradsuvw); + for (int i = 0; i < ndofs; ++i) + grads.push_back(GradType(gradsuvw[i][0], gradsuvw[i][1], gradsuvw[i][2])); + } + virtual int getNumKeys(MElement *ele) + { + if(ele->getParent()) ele = ele->getParent(); + return ele->getNumVertices(); + } + + virtual void getKeys(MElement *ele, std::vector<Dof> &keys) // appends ... + { + if(ele->getParent()) ele = ele->getParent(); + int ndofs = ele->getNumVertices(); + keys.reserve(keys.size() + ndofs); + for (int i = 0; i < ndofs; ++i) + getKeys(ele->getVertex(i), keys); + } +}; template <class T> class ScalarToAnyFunctionSpace : public FunctionSpace<T> { @@ -295,6 +389,31 @@ class VectorLagrangeFunctionSpace : public ScalarToAnyFunctionSpace<SVector3> {} }; +class VectorLagrangeFunctionSpaceOfParent : public ScalarToAnyFunctionSpace<SVector3> +{ + protected: + static const SVector3 BasisVectors[3]; + public: + enum Along { VECTOR_X = 0, VECTOR_Y = 1, VECTOR_Z = 2 }; + typedef TensorialTraits<SVector3>::ValType ValType; + typedef TensorialTraits<SVector3>::GradType GradType; + VectorLagrangeFunctionSpaceOfParent(int id) : + ScalarToAnyFunctionSpace<SVector3>::ScalarToAnyFunctionSpace(ScalarLagrangeFunctionSpaceOfParent(id), + SVector3(1.,0.,0.), VECTOR_X, SVector3(0.,1.,0.), VECTOR_Y, SVector3(0.,0.,1.), VECTOR_Z) + {} + VectorLagrangeFunctionSpaceOfParent(int id,Along comp1) : + ScalarToAnyFunctionSpace<SVector3>::ScalarToAnyFunctionSpace(ScalarLagrangeFunctionSpaceOfParent(id), + BasisVectors[comp1], comp1) + {} + VectorLagrangeFunctionSpaceOfParent(int id,Along comp1,Along comp2) : + ScalarToAnyFunctionSpace<SVector3>::ScalarToAnyFunctionSpace(ScalarLagrangeFunctionSpaceOfParent(id), + BasisVectors[comp1], comp1, BasisVectors[comp2], comp2) + {} + VectorLagrangeFunctionSpaceOfParent(int id,Along comp1,Along comp2, Along comp3) : + ScalarToAnyFunctionSpace<SVector3>::ScalarToAnyFunctionSpace(ScalarLagrangeFunctionSpaceOfParent(id), + BasisVectors[comp1], comp1, BasisVectors[comp2], comp2, BasisVectors[comp3], comp3) + {} +}; template<class T> class CompositeFunctionSpace : public FunctionSpace<T> @@ -489,7 +608,7 @@ template <class T> int xFemFunctionSpace<T>::getNumKeys(MElement *ele) MElement * elep; if (ele->getParent()) elep = ele->getParent(); else elep = ele; - int nbdofs = xFemFunctionSpace<T>::_spacebase->getNumKeys(ele); + int nbdofs = xFemFunctionSpace<T>::_spacebase->getNumKeys(elep); return nbdofs; } @@ -617,7 +736,4 @@ template <class T,class F> void FilteredFunctionSpace<T,F>::getKeys(MElement *el } - - - #endif diff --git a/Solver/quadratureRules.h b/Solver/quadratureRules.h index 4ae9438c0edeba1d25f41b4acd54a3d9252107da..12c12b3dc006f418276875438f1d1a67605ed527 100644 --- a/Solver/quadratureRules.h +++ b/Solver/quadratureRules.h @@ -56,7 +56,7 @@ class GaussQuadrature : public QuadratureBase integrationOrder=2*geoorder; break; case GradGrad : - integrationOrder=3*(geoorder-1); + integrationOrder=3*(geoorder-1)+1; break; default : integrationOrder=1; } diff --git a/Solver/solverAlgorithms.h b/Solver/solverAlgorithms.h index ac501538e771c2aa840db4a65e5c1cc60569f2ef..33f5a2b88665b3f20f998fdbc9b85378207089d9 100644 --- a/Solver/solverAlgorithms.h +++ b/Solver/solverAlgorithms.h @@ -38,42 +38,44 @@ template<class Iterator,class Assembler> void Assemble(BilinearTermBase &term,Fu } } +template<class Assembler> void Assemble(BilinearTermBase &term,FunctionSpaceBase &space,MElement *e,QuadratureBase &integrator,Assembler &assembler) // symmetric +{ + fullMatrix<typename Assembler::dataMat> localMatrix; + std::vector<Dof> R; + IntPt *GP; + int npts=integrator.getIntPoints(e,&GP); + term.get(e,npts,GP,localMatrix); + space.getKeys(e,R); + assembler.assemble(R, localMatrix); +} + template<class Iterator,class Assembler> void Assemble(BilinearTermBase &term, - FunctionSpaceBase &shapeFcts, - FunctionSpaceBase &testFcts, - Iterator itbegin, - Iterator itend, - QuadratureBase &integrator, - Assembler &assembler) // non symmetric + FunctionSpaceBase &shapeFcts, + FunctionSpaceBase &testFcts, + Iterator itbegin, + Iterator itend, + QuadratureBase &integrator, + Assembler &assembler) // non symmetric { fullMatrix<typename Assembler::dataMat> localMatrix; std::vector<Dof> R; std::vector<Dof> C; - for (Iterator it = itbegin;it!=itend; ++it) + for (Iterator it = itbegin; it != itend; ++it) { MElement *e = *it; R.clear(); C.clear(); IntPt *GP; - int npts=integrator.getIntPoints(e,&GP); - term.get(e,npts,GP,localMatrix); - shapeFcts.getKeys(e,R); - testFcts.getKeys(e,C); + int npts = integrator.getIntPoints(e, &GP); + term.get(e, npts, GP, localMatrix); + shapeFcts.getKeys(e, R); + testFcts.getKeys(e, C); assembler.assemble(R, C, localMatrix); + assembler.assemble(C, R, localMatrix.transpose()); } } -template<class Assembler> void Assemble(BilinearTermBase &term,FunctionSpaceBase &space,MElement *e,QuadratureBase &integrator,Assembler &assembler) // symmetric -{ - fullMatrix<typename Assembler::dataMat> localMatrix; - std::vector<Dof> R; - IntPt *GP; - int npts=integrator.getIntPoints(e,&GP); - term.get(e,npts,GP,localMatrix); - space.getKeys(e,R); - assembler.assemble(R, localMatrix); -} template<class Iterator,class Assembler> void Assemble(LinearTermBase &term,FunctionSpaceBase &space,Iterator itbegin,Iterator itend,QuadratureBase &integrator,Assembler &assembler) { @@ -125,7 +127,6 @@ template<class Iterator,class dataMat> void Assemble(ScalarTermBase &term,MEleme } - template<class Assembler> void FixDofs(Assembler &assembler,std::vector<Dof> &dofs,std::vector<typename Assembler::dataVec> &vals) { int nbff=dofs.size(); @@ -141,7 +142,7 @@ class FilterDof virtual bool operator()(Dof key)=0; }; -class FilterDofTrivial +class FilterDofTrivial : public FilterDof { public: virtual bool operator()(Dof key) {return true;} @@ -197,6 +198,13 @@ template<class Iterator,class Assembler> void FixNodalDofs(FunctionSpaceBase &sp } } +template<class Iterator,class Assembler> void FixVoidNodalDofs(FunctionSpaceBase &space,Iterator itbegin,Iterator itend,Assembler &assembler) +{ + FilterDofTrivial filter; + simpleFunction<typename Assembler::dataVec> fct(0.); + FixNodalDofs(space, itbegin, itend, assembler, fct, filter); +} + template<class Iterator,class Assembler> void NumberDofs(FunctionSpaceBase &space,Iterator itbegin,Iterator itend,Assembler &assembler) { for (Iterator it=itbegin;it!=itend;++it) diff --git a/Solver/terms.h b/Solver/terms.h index f629943724b894fefb515d4c9bae263c0e1eda86..7a4ba1bdfd0fa8f912472c5d2d3fb86098e9dd30 100644 --- a/Solver/terms.h +++ b/Solver/terms.h @@ -35,7 +35,7 @@ template<class T1,class T2> class BilinearTerm : public BilinearTermBase FunctionSpace<T1>& space1; FunctionSpace<T2>& space2; public : - BilinearTerm(FunctionSpace<T1>& space1_,FunctionSpace<T1>& space2_) : space1(space1_),space2(space2_) {} + BilinearTerm(FunctionSpace<T1>& space1_,FunctionSpace<T2>& space2_) : space1(space1_),space2(space2_) {} virtual ~BilinearTerm() {} }; @@ -129,8 +129,9 @@ template<class T1,class T2> class LaplaceTerm : public BilinearTerm<T1,T2> template<class T1> class LaplaceTerm<T1,T1> : public BilinearTerm<T1,T1> // symmetric { + double diffusivity; public : - LaplaceTerm(FunctionSpace<T1>& space1_) : BilinearTerm<T1,T1>(space1_,space1_) + LaplaceTerm(FunctionSpace<T1>& space1_, double diff=1) : BilinearTerm<T1,T1>(space1_,space1_), diffusivity(diff) {} virtual ~LaplaceTerm() {} virtual void get(MElement *ele,int npts,IntPt *GP,fullMatrix<double> &m) @@ -149,7 +150,7 @@ template<class T1> class LaplaceTerm<T1,T1> : public BilinearTerm<T1,T1> // symm { for (int k = j; k < nbFF; k++) { - double contrib=weight * detJ * dot(Grads[j],Grads[k]); + double contrib=weight * detJ * dot(Grads[j],Grads[k]) * diffusivity; m(j,k)+=contrib; if (j!=k) m(k,j)+=contrib; } @@ -161,8 +162,6 @@ template<class T1> class LaplaceTerm<T1,T1> : public BilinearTerm<T1,T1> // symm }; // class - - class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> { protected : @@ -202,8 +201,8 @@ class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> virtual ~IsotropicElasticTerm() {} virtual void get(MElement *ele,int npts,IntPt *GP,fullMatrix<double> &m) { - if (ele->getParent()) ele=ele->getParent(); - if (sym) + if (ele->getParent()) ele=ele->getParent(); + if (sym) { int nbFF = BilinearTerm<SVector3,SVector3>::space1.getNumKeys(ele); double jac[3][3]; @@ -217,7 +216,6 @@ class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> for (int i = 0; i < npts; i++) { const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); std::vector<TensorialTraits<SVector3>::GradType> Grads; BilinearTerm<SVector3,SVector3>::space1.gradf(ele,u, v, w, Grads); // a optimiser ?? @@ -285,7 +283,6 @@ class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> inline double dot(const double &a, const double &b) { return a*b; } - template<class T1> class LoadTerm : public LinearTerm<T1> { simpleFunction<typename TensorialTraits<T1>::ValType> &Load; @@ -295,29 +292,56 @@ template<class T1> class LoadTerm : public LinearTerm<T1> virtual void get(MElement *ele,int npts,IntPt *GP,fullVector<double> &m) { - if (ele->getParent()) ele=ele->getParent(); - int nbFF=LinearTerm<T1>::space1.getNumKeys(ele); + if (ele->getParent()) ele=ele->getParent(); + int nbFF=LinearTerm<T1>::space1.getNumKeys(ele); double jac[3][3]; m.resize(nbFF); m.scale(0.); for (int i = 0; i < npts; i++) { - const double u = GP[i].pt[0];const double v = GP[i].pt[1];const double w = GP[i].pt[2]; - const double weight = GP[i].weight;const double detJ = ele->getJacobian(u, v, w, jac); + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); std::vector<typename TensorialTraits<T1>::ValType> Vals; - LinearTerm<T1>::space1.f(ele,u, v, w, Vals); + LinearTerm<T1>::space1.f(ele, u, v, w, Vals); SPoint3 p; ele->pnt(u, v, w, p); typename TensorialTraits<T1>::ValType load=Load(p.x(),p.y(),p.z()); for (int j = 0; j < nbFF ; ++j) { - m(j)+=dot(Vals[j],load)*weight*detJ; + m(j) += dot(Vals[j], load) * weight * detJ; } } } }; - - +class LagrangeMultiplierTerm : public BilinearTerm<SVector3,double> +{ + SVector3 _d; + public : + LagrangeMultiplierTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<double>& space2_, const SVector3 &d) : + BilinearTerm<SVector3,double>(space1_, space2_) {for(int i=0; i < 3; i++) _d(i) = d(i);} + virtual ~LagrangeMultiplierTerm() {} + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) + { + int nbFF1 = BilinearTerm<SVector3,double>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent + int nbFF2 = BilinearTerm<SVector3,double>::space2.getNumKeys(ele); //nbVertices of boundary + double jac[3][3]; + m.resize(nbFF1, nbFF2); + m.setAll(0.); + for (int i = 0; i < npts; i++) { + double u = GP[i].pt[0]; double v = GP[i].pt[1]; double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<TensorialTraits<SVector3>::ValType> Vals; + std::vector<TensorialTraits<double>::ValType> ValsT; + BilinearTerm<SVector3,double>::space1.f(ele, u, v, w, Vals); + BilinearTerm<SVector3,double>::space2.f(ele, u, v, w, ValsT); + for (int j = 0; j < nbFF1; j++) { + for (int k = 0; k < nbFF2; k++) { + m(j, k) += dot(Vals[j], _d) * ValsT[k] * weight * detJ; + } + } + } + } +}; #endif// _TERMS_H_