diff --git a/CMakeLists.txt b/CMakeLists.txt index ddcc217f08ae130239b9740285a101aa1b625db4..6f491a28dbe9be5cef6507ad4739d19ef81684fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ set(GMSH_API Numeric/Numeric.h Numeric/GaussIntegration.h Numeric/polynomialBasis.h Numeric/JacobianBasis.h Numeric/MetricBasis.h Numeric/bezierBasis.h Numeric/fullMatrix.h Numeric/simpleFunction.h Numeric/cartesian.h Numeric/ElementType.h + Numeric/BasisFactory.h Geo/GModel.h Geo/GEntity.h Geo/GPoint.h Geo/GVertex.h Geo/GEdge.h Geo/GFace.h Geo/GRegion.h Geo/GEdgeLoop.h Geo/GEdgeCompound.h Geo/GFaceCompound.h Geo/GRegionCompound.h Geo/GRbf.h Geo/MVertex.h @@ -131,6 +132,7 @@ set(GMSH_API Solver/linearSystem.h Solver/linearSystemGMM.h Solver/linearSystemCSR.h Solver/linearSystemFull.h Solver/elasticitySolver.h Solver/sparsityPattern.h Solver/groupOfElements.h Solver/linearSystemPETSc.h Solver/linearSystemMUMPS.h + Solver/thermicSolver.h Post/PView.h Post/PViewData.h Plugin/PluginManager.h Post/OctreePost.h Post/PViewDataList.h Post/PViewDataGModel.h Post/PViewOptions.h Post/ColorTable.h Numeric/nodalBasis.h diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt index a4d1657167df2d0bdbabf1e03d90118e35128a66..4b14fb8f1ed1c990e27cd4fd46d8d29c0460eebc 100644 --- a/Solver/CMakeLists.txt +++ b/Solver/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRC groupOfElements.cpp elasticityTerm.cpp elasticitySolver.cpp + thermicSolver.cpp SElement.cpp eigenSolver.cpp multiscaleLaplace.cpp diff --git a/Solver/elasticitySolver.cpp b/Solver/elasticitySolver.cpp index 58d1aa06968da333c12de9b687d668ee6a869e69..610785068bb2be0beb8ea243d57a98fc401b40ea 100644 --- a/Solver/elasticitySolver.cpp +++ b/Solver/elasticitySolver.cpp @@ -119,12 +119,11 @@ void elasticitySolver::solve() // printLinearSystem(lsys); double energ=0; - for (unsigned int i = 0; i < elasticFields.size(); i++) - { + for (unsigned int i = 0; i < elasticFields.size(); i++){ SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); - Assemble(Elastic_Energy_Term,elasticFields[i].g->begin(),elasticFields[i].g->end(), + Assemble(Elastic_Energy_Term, elasticFields[i].g->begin(), elasticFields[i].g->end(), Integ_Bulk,energ); } printf("elastic energy=%f\n",energ); @@ -135,8 +134,7 @@ void elasticitySolver::postSolve() GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); double energ=0; - for (unsigned int i = 0; i < elasticFields.size(); i++) - { + for (unsigned int i = 0; i < elasticFields.size(); i++){ SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); @@ -156,12 +154,12 @@ void elasticitySolver::readInputFile(const std::string &fn) return; } if(what[0]=='#'){ - /* + char *line=NULL; size_t l = 0; - int r = getline(&line,&l,f); + getline(&line,&l,f); free(line); - */ + } else if (!strcmp(what, "ElasticDomain")){ elasticField field; @@ -185,7 +183,7 @@ void elasticitySolver::readInputFile(const std::string &fn) } field._tag = _tag; field._d = SVector3(d1, d2, d3); - field._f = simpleFunction<double>(val); + field._f = new simpleFunction<double>(val); field.g = new groupOfElements (_dim - 1, physical); LagrangeMultiplierFields.push_back(field); } @@ -319,6 +317,7 @@ void elasticitySolver::readInputFile(const std::string &fn) int tag=1; gLevelsetPlane ls(a,b,c,d,tag); pModel = pModel->buildCutGModel(&ls); + pModel->writeMSH("cutMesh.msh"); } else if (!strcmp(what, "CutMeshSphere")){ double x, y, z, r; @@ -329,6 +328,19 @@ void elasticitySolver::readInputFile(const std::string &fn) int tag=1; gLevelsetSphere ls(x,y,z,r,tag); pModel = pModel->buildCutGModel(&ls); + pModel->writeMSH("cutMesh.msh"); + } + else if (!strcmp(what, "CutMeshMathExpr")){ + char expr[256]; + if(fscanf(f, "%s", expr) != 1){ + fclose(f); + return; + } + std::string exprS(expr); + int tag=1; + gLevelsetMathEval ls(exprS,tag); + pModel = pModel->buildCutGModel(&ls); + pModel->writeMSH("cutMesh.msh"); } else { Msg::Error("Invalid input : '%s'", what); @@ -338,7 +350,8 @@ void elasticitySolver::readInputFile(const std::string &fn) } -void elasticitySolver::addDirichletBC (int dim, int entityId, int component, double value) { +void elasticitySolver::addDirichletBC(int dim, int entityId, int component, double value) +{ dirichletBC diri; diri.g = new groupOfElements (dim, entityId); diri._f= new simpleFunction<double>(value); @@ -353,8 +366,14 @@ void elasticitySolver::addDirichletBC (int dim, int entityId, int component, dou allDirichlet.push_back(diri); } +void elasticitySolver::addDirichletBC(int dim, std::string phys, int component, double value) +{ + int entityId = pModel->getPhysicalNumber(dim, phys); + addDirichletBC(dim, entityId, component, value); +} -void elasticitySolver::addNeumannBC (int dim, int entityId, const std::vector<double> value) { +void elasticitySolver::addNeumannBC(int dim, int entityId, const std::vector<double> value) +{ if(value.size()!=3) return; neumannBC neu; neu.g = new groupOfElements (dim, entityId); @@ -369,9 +388,14 @@ void elasticitySolver::addNeumannBC (int dim, int entityId, const std::vector<do allNeumann.push_back(neu); } +void elasticitySolver::addNeumannBC(int dim, std::string phys, const std::vector<double> value) +{ + int entityId = pModel->getPhysicalNumber(dim, phys); + addNeumannBC(dim, entityId, value); +} - -void elasticitySolver::addElasticDomain (int physical, double e, double nu){ +void elasticitySolver::addElasticDomain(int physical, double e, double nu) +{ elasticField field; field._tag = _tag; field._E = e; @@ -380,6 +404,12 @@ void elasticitySolver::addElasticDomain (int physical, double e, double nu){ elasticFields.push_back(field); } +void elasticitySolver::addElasticDomain(std::string phys, double e, double nu) +{ + int entityId = pModel->getPhysicalNumber(_dim, phys); + addElasticDomain(entityId, e, nu); +} + elasticitySolver::elasticitySolver(GModel *model, int tag) { pModel = model; @@ -387,7 +417,9 @@ elasticitySolver::elasticitySolver(GModel *model, int tag) _tag = tag; pAssembler = NULL; if (_dim==3) LagSpace=new VectorLagrangeFunctionSpace(_tag); - if (_dim==2) LagSpace=new VectorLagrangeFunctionSpace(_tag,VectorLagrangeFunctionSpace::VECTOR_X,VectorLagrangeFunctionSpace::VECTOR_Y); + if (_dim==2) LagSpace=new VectorLagrangeFunctionSpace(_tag, + VectorLagrangeFunctionSpace::VECTOR_X, + VectorLagrangeFunctionSpace::VECTOR_Y); LagrangeMultiplierSpace = new ScalarLagrangeFunctionSpace(_tag+1); } @@ -401,28 +433,24 @@ void elasticitySolver::assemble(linearSystem<double> *lsys) // numbered afterwards // Dirichlet conditions - for (unsigned int i = 0; i < allDirichlet.size(); i++) - { + 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); + FixNodalDofs(*LagSpace, allDirichlet[i].g->begin(), allDirichlet[i].g->end(), + *pAssembler, *allDirichlet[i]._f, filter); } // LagrangeMultipliers - for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i) - { + 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) - { + for (unsigned int i = 0; i < elasticFields.size(); ++i){ if(elasticFields[i]._E != 0.) NumberDofs(*LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(), *pAssembler); } // Voids - for (unsigned int i = 0; i < elasticFields.size(); ++i) - { + 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); @@ -430,19 +458,17 @@ void elasticitySolver::assemble(linearSystem<double> *lsys) // Neumann conditions GaussQuadrature Integ_Boundary(GaussQuadrature::Val); - for (unsigned int i = 0; i < allNeumann.size(); i++) - { - LoadTerm<SVector3> Lterm(*LagSpace,*allNeumann[i]._f); - Assemble(Lterm,*LagSpace,allNeumann[i].g->begin(),allNeumann[i].g->end(), + for (unsigned int i = 0; i < allNeumann.size(); i++){ + 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); + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); i++){ + LagrangeMultiplierTerm<SVector3> LagTerm(*LagSpace, *LagrangeMultiplierSpace, + LagrangeMultiplierFields[i]._d); Assemble(LagTerm, *LagSpace, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), Integ_LagrangeMult, *pAssembler); @@ -458,11 +484,10 @@ void elasticitySolver::assemble(linearSystem<double> *lsys) } // Assemble elastic term for GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); - for (unsigned int i = 0; i < elasticFields.size(); i++) - { + for (unsigned int i = 0; i < elasticFields.size(); i++){ IsotropicElasticTerm Eterm(*LagSpace,elasticFields[i]._E,elasticFields[i]._nu); - Assemble(Eterm,*LagSpace,elasticFields[i].g->begin(),elasticFields[i].g->end(), - Integ_Bulk,*pAssembler); + Assemble(Eterm, *LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(), + Integ_Bulk, *pAssembler); } /*for (int i=0;i<pAssembler->sizeOfR();i++){ @@ -479,14 +504,9 @@ void elasticitySolver::assemble(linearSystem<double> *lsys) } -void elasticitySolver::getSolutionOnElement (MElement *el, fullMatrix<double> &sol) { - -} - -#if defined(HAVE_POST) -/* static void deformation(dofManager<double> *a, MElement *e, - double u, double v, double w, int _tag, double *eps){ + double u, double v, double w, int _tag, double *eps) +{ double valx[256]; double valy[256]; double valz[256]; @@ -512,27 +532,10 @@ static void deformation(dofManager<double> *a, MElement *e, static double vonMises(dofManager<double> *a, MElement *e, double u, double v, double w, - double E, double nu, int _tag){ - - double valx[256]; - double valy[256]; - double valz[256]; - for (int k = 0; k < e->getNumVertices(); k++){ - a->getDofValue(e->getVertex(k), 0, _tag, valx[k]); - a->getDofValue(e->getVertex(k), 1, _tag, valy[k]); - a->getDofValue(e->getVertex(k), 2, _tag, valz[k]); - } - double gradux[3]; - double graduy[3]; - double graduz[3]; - e->interpolateGrad(valx, u, v, w, gradux); - e->interpolateGrad(valy, u, v, w, graduy); - e->interpolateGrad(valz, u, v, w, graduz); - - double eps[6] = {gradux[0], graduy[1], graduz[2], - 0.5 * (gradux[1] + graduy[0]), - 0.5 * (gradux[2] + graduz[0]), - 0.5 * (graduy[2] + graduz[1])}; + double E, double nu, int _tag) +{ + double eps[6]; + deformation(a, e, u, v, w, _tag, eps); double A = E / (1. + nu); double B = A * (nu / (1. - 2 * nu)); double trace = eps[0] + eps[1] + eps[2] ; @@ -547,19 +550,123 @@ static double vonMises(dofManager<double> *a, MElement *e, return ComputeVonMises(s); } -*/ + +void elasticitySolver::computeEffectiveStiffness(std::vector<double> stiff) +{ + double st[6] = {0., 0., 0., 0., 0., 0.}; + double volTot = 0.; + for (unsigned int i = 0; i < elasticFields.size(); ++i){ + double E = elasticFields[i]._E; + double nu = elasticFields[i]._nu; + SolverField<SVector3> Field(pAssembler, LagSpace); + for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; + double vol = e->getVolume() * e->getVolumeSign(); + int nbVertex = e->getNumVertices(); + std::vector<SVector3> val(nbVertex); + + double valx[256]; + double valy[256]; + double valz[256]; + for (int k = 0; k < nbVertex; k++){ + MVertex *v = e->getVertex(k); + MPoint p(v); + Field.f(&p, 0, 0, 0, val[k]); + valx[k] = val[k](0); + valy[k] = val[k](1); + valz[k] = val[k](2); + } + + double gradux[3]; + double graduy[3]; + double graduz[3]; + SPoint3 center = e->barycenterUVW(); + double u = center.x(), v = center.y(), w = center.z(); + e->interpolateGrad(valx, u, v, w, gradux); + e->interpolateGrad(valy, u, v, w, graduy); + e->interpolateGrad(valz, u, v, w, graduz); + + double eps[6] = {gradux[0], graduy[1], graduz[2], + 0.5 * (gradux[1] + graduy[0]), + 0.5 * (gradux[2] + graduz[0]), + 0.5 * (graduy[2] + graduz[1])}; + + double A = E / (1. + nu); + double B = A * (nu / (1. - 2 * nu)); + double trace = eps[0] + eps[1] + eps[2] ; + st[0] += (A * eps[0] + B * trace) * vol; + st[1] += (A * eps[1] + B * trace) * vol; + st[2] += (A * eps[2] + B * trace) * vol; + st[3] += (A * eps[3]) * vol; + st[4] += (A * eps[4]) * vol; + st[5] += (A * eps[5]) * vol; + volTot += vol; + } + } + for(int i = 0; i < 6;i++) + stiff[i] = st[i] / volTot; +} + +void elasticitySolver::computeEffectiveStrain(std::vector<double> strain) +{ + double st[6] = {0., 0., 0., 0., 0., 0.}; + double volTot = 0.; + for (unsigned int i = 0; i < elasticFields.size(); ++i){ + SolverField<SVector3> Field(pAssembler, LagSpace); + for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; + double vol = e->getVolume() * e->getVolumeSign(); + int nbVertex = e->getNumVertices(); + std::vector<SVector3> val(nbVertex); + + double valx[256]; + double valy[256]; + double valz[256]; + for (int k = 0; k < nbVertex; k++){ + MVertex *v = e->getVertex(k); + MPoint p(v); + Field.f(&p, 0, 0, 0, val[k]); + valx[k] = val[k](0); + valy[k] = val[k](1); + valz[k] = val[k](2); + } + + double gradux[3]; + double graduy[3]; + double graduz[3]; + SPoint3 center = e->barycenterUVW(); + double u = center.x(), v = center.y(), w = center.z(); + e->interpolateGrad(valx, u, v, w, gradux); + e->interpolateGrad(valy, u, v, w, graduy); + e->interpolateGrad(valz, u, v, w, graduz); + + st[0] += gradux[0] * vol; + st[1] += graduy[1] * vol; + st[2] += graduz[2] * vol; + st[3] += 0.5 * (gradux[1] + graduy[0]) * vol; + st[4] += 0.5 * (gradux[2] + graduz[0]) * vol; + st[5] += 0.5 * (graduy[2] + graduz[1]) * vol; + volTot += vol; + } + } + for(int i = 0; i < 6;i++) + strain[i] = st[i] / volTot; +} + +#if defined(HAVE_POST) 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) - { + std::map<MVertex*, MElement*> vCut; + for (unsigned int i = 0; i < elasticFields.size(); ++i){ 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; + MElement *e = *it; if(e->getParent()) { for (int j = 0; j < e->getNumVertices(); ++j) { if(vCut.find(e->getVertex(j)) == vCut.end()) @@ -577,18 +684,20 @@ PView* elasticitySolver::buildDisplacementView (const std::string postFileName) 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; + 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; + 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; @@ -596,20 +705,19 @@ PView* elasticitySolver::buildDisplacementView (const std::string postFileName) PView* elasticitySolver::buildStressesView (const std::string postFileName) { + double sti[6] = {0., 0., 0., 0., 0., 0.}; + double str[6] = {0., 0., 0., 0., 0., 0.}; + double volTot = 0.; std::cout << "build stresses view"<< std::endl; std::map<int, std::vector<double> > data; - GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad); - for (unsigned int i = 0; i < elasticFields.size(); ++i) - { + for (unsigned int i = 0; i < elasticFields.size(); ++i){ double E = elasticFields[i]._E; double nu = elasticFields[i]._nu; SolverField<SVector3> Field(pAssembler, LagSpace); - IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); - it != elasticFields[i].g->end(); ++it) - { - MElement *e=*it; + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; + double vol = e->getVolume() * e->getVolumeSign(); int nbVertex = e->getNumVertices(); std::vector<SVector3> val(nbVertex); @@ -619,16 +727,17 @@ PView* elasticitySolver::buildStressesView (const std::string postFileName) for (int k = 0; k < nbVertex; k++){ MVertex *v = e->getVertex(k); MPoint p(v); - Field.f(&p,0,0,0,val[k]); - valx[k] =val[k](0); - valy[k] =val[k](1); - valz[k] =val[k](2); + Field.f(&p, 0, 0, 0, val[k]); + valx[k] = val[k](0); + valy[k] = val[k](1); + valz[k] = val[k](2); } double gradux[3]; double graduy[3]; double graduz[3]; - double u=0.33, v=0.33, w=0.0; + SPoint3 center = e->barycenterUVW(); + double u = center.x(), v = center.y(), w = center.z(); e->interpolateGrad(valx, u, v, w, gradux); e->interpolateGrad(valy, u, v, w, graduy); e->interpolateGrad(valz, u, v, w, graduz); @@ -638,7 +747,6 @@ PView* elasticitySolver::buildStressesView (const std::string postFileName) 0.5 * (gradux[2] + graduz[0]), 0.5 * (graduy[2] + graduz[1])}; - double A = E / (1. + nu); double B = A * (nu / (1. - 2 * nu)); double trace = eps[0] + eps[1] + eps[2] ; @@ -650,15 +758,79 @@ PView* elasticitySolver::buildStressesView (const std::string postFileName) double syz = A * eps[5]; std::vector<double> vec(9); - vec[0]=sxx; vec[1]=sxy; vec[2]=sxz; vec[3]=sxy; vec[4]=syy; - vec[5]=syz; vec[6]=sxz; vec[7]=syz; vec[8]=szz; - - data[e->getNum()]=vec; + vec[0] = sxx; vec[1] = sxy; vec[2] = sxz; + vec[3] = sxy; vec[4] = syy; vec[5] = syz; + vec[6] = sxz; vec[7] = syz; vec[8] = szz; + + data[e->getNum()] = vec; + + for(int k = 0; k < 6; k++) + str[k] += eps[k] * vol; + sti[0] += sxx * vol; + sti[1] += syy * vol; + sti[2] += szz * vol; + sti[3] += sxy * vol; + sti[4] += sxz * vol; + sti[5] += syz * vol; + volTot += vol; } } + for(int i = 0; i < 6; i++){ + str[i] = str[i] / volTot; + sti[i] = sti[i] / volTot; + } + printf("effective stiffn = ");for(int i = 0; i < 6; i++) printf("%g ",sti[i]);printf("\n"); + printf("effective strain = ");for(int i = 0; i < 6; i++) printf("%g ",str[i]);printf("\n"); + PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0); return pv; +} + +PView* elasticitySolver::buildStrainView (const std::string postFileName) +{ + std::cout << "build strain view"<< std::endl; + std::map<int, std::vector<double> > data; + for (unsigned int i = 0; i < elasticFields.size(); ++i){ + SolverField<SVector3> Field(pAssembler, LagSpace); + for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; + int nbVertex = e->getNumVertices(); + std::vector<SVector3> val(nbVertex); + + double valx[256]; + double valy[256]; + double valz[256]; + for (int k = 0; k < nbVertex; k++){ + MVertex *v = e->getVertex(k); + MPoint p(v); + Field.f(&p, 0, 0, 0, val[k]); + valx[k] = val[k](0); + valy[k] = val[k](1); + valz[k] = val[k](2); + } + + double gradux[3]; + double graduy[3]; + double graduz[3]; + double u = 0.33, v = 0.33, w = 0.0; + e->interpolateGrad(valx, u, v, w, gradux); + e->interpolateGrad(valy, u, v, w, graduy); + e->interpolateGrad(valz, u, v, w, graduz); + std::vector<double> vec(9); + vec[0] = gradux[0]; + vec[4] = graduy[1]; + vec[8] = graduy[2]; + vec[1] = vec[3] = 0.5 * (gradux[0] + graduy[1]); + vec[2] = vec[6] = 0.5 * (gradux[0] + graduz[2]); + vec[5] = vec[7] = 0.5 * (gradux[1] + graduz[2]); + + data[e->getNum()] = vec; + } + } + PView *pv = new PView(postFileName, "ElementData", pModel, data, 0.0); + return pv; } PView* elasticitySolver::buildLagrangeMultiplierView (const std::string postFileName) @@ -666,20 +838,17 @@ PView* elasticitySolver::buildLagrangeMultiplierView (const std::string postFile 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 (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i){ for(groupOfElements::elementContainer::const_iterator it = LagrangeMultiplierFields[i].g->begin(); - it != LagrangeMultiplierFields[i].g->end(); ++it) - { + 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) - { + for(std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it){ double val; MPoint p(*it); Field.f(&p, 0, 0, 0, val); @@ -697,60 +866,95 @@ 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) - { + 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); + IsotropicElasticTerm Eterm(Field, elasticFields[i]._E, elasticFields[i]._nu); BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); ScalarTermConstant<double> One(1.0); for (groupOfElements::elementContainer::const_iterator it = - elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) - { + elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it){ MElement *e = *it; double energ; double vol; IntPt *GP; - int npts=Integ_Bulk.getIntPoints(e,&GP); - Elastic_Energy_Term.get(e,npts,GP,energ); - One.get(e,npts,GP,vol); + int npts = Integ_Bulk.getIntPoints(e, &GP); + Elastic_Energy_Term.get(e, npts, GP, energ); + One.get(e, npts, GP, vol); std::vector<double> vec; - vec.push_back(energ/vol); - data[e->getNum()]=vec; + vec.push_back(energ / vol); + data[e->getNum()] = vec; } } PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0); return pv; } +PView *elasticitySolver::buildVolumeView(const std::string postFileName) +{ + std::cout << "build Volume View"; + std::map<int, std::vector<double> > data; + double voltot = 0; double length = 0; + GaussQuadrature Integ_Vol(GaussQuadrature::Val); + for (unsigned int i = 0; i < elasticFields.size(); ++i){ + ScalarTermConstant<double> One(1.0); + for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; + double vol; + IntPt *GP; + int npts = Integ_Vol.getIntPoints(e, &GP); + One.get(e, npts, GP, vol); + voltot += vol; + std::vector<double> vec; + vec.push_back(vol); + data[e->getNum()] = vec; + } + } + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i){ + ScalarTermConstant<double> One(1.0); + for (groupOfElements::elementContainer::const_iterator it = LagrangeMultiplierFields[i].g->begin(); + it != LagrangeMultiplierFields[i].g->end(); ++it){ + MElement *e = *it; + double l; + IntPt *GP; + int npts = Integ_Vol.getIntPoints(e, &GP); + One.get(e, npts, GP, l); + length += l; + } + std::cout << " : length " << LagrangeMultiplierFields[i]._tag << " = " << length; + length = 0; + } + PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0, 1); + std::cout << " / total vol = " << voltot << std::endl; + return pv; +} + 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) - { + for (unsigned int i = 0; i < elasticFields.size(); ++i){ SolverField<SVector3> Field(pAssembler, LagSpace); - IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); + IsotropicElasticTerm Eterm(Field, elasticFields[i]._E, elasticFields[i]._nu); BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); - it != elasticFields[i].g->end(); ++it) - { - MElement *e=*it; + it != elasticFields[i].g->end(); ++it){ + MElement *e = *it; double energ; IntPt *GP; - int npts=Integ_Bulk.getIntPoints(e,&GP); - Elastic_Energy_Term.get(e,npts,GP,energ); + int npts = Integ_Bulk.getIntPoints(e, &GP); + Elastic_Energy_Term.get(e, npts, GP, energ); std::vector<double> vec; vec.push_back(energ); - data[(*it)->getNum()]=vec; + data[(*it)->getNum()] = vec; } } PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0); return pv; } - #else PView* elasticitySolver::buildDisplacementView(const std::string postFileName) @@ -759,6 +963,12 @@ PView* elasticitySolver::buildDisplacementView(const std::string postFileName) return 0; } +PView* elasticitySolver::buildStrainView(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"); @@ -782,5 +992,10 @@ PView* elasticitySolver::buildStressesView (const std::string postFileName) Msg::Error("Post-pro module not available"); return 0; } +PView *elasticitySolver::buildVolumeView(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 cfb879139b276126a7fd3ed190af93b807f84b85..423e5ff400dcc5cae0f1cadcadc809004209a991 100644 --- a/Solver/elasticitySolver.h +++ b/Solver/elasticitySolver.h @@ -22,7 +22,7 @@ struct LagrangeMultiplierField { groupOfElements *g; double _tau; SVector3 _d; - simpleFunction<double> _f; + simpleFunction<double> *_f; LagrangeMultiplierField() : _tag(0), g(0){} }; @@ -78,9 +78,12 @@ class elasticitySolver elasticitySolver(GModel *model, int tag); - void addDirichletBC (int dim, int entityId, int component, double value); - void addNeumannBC (int dim, int entityId, const std::vector<double> value); - void addElasticDomain (int tag, double e, double nu); + void addDirichletBC(int dim, int entityId, int component, double value); + void addDirichletBC(int dim, std::string phys, int component, double value); + void addNeumannBC(int dim, int entityId, const std::vector<double> value); + void addNeumannBC(int dim, std::string phys, const std::vector<double> value); + void addElasticDomain(int tag, double e, double nu); + void addElasticDomain(std::string phys, double e, double nu); virtual ~elasticitySolver() { @@ -95,12 +98,15 @@ class elasticitySolver void solve(); void postSolve(); void exportKb(); - void getSolutionOnElement(MElement *el, fullMatrix<double> &sol); + void computeEffectiveStiffness(std::vector<double> stiff); + void computeEffectiveStrain(std::vector<double> strain); virtual PView *buildDisplacementView(const std::string postFileName); + virtual PView *buildStrainView(const std::string postFileName); virtual PView *buildStressesView(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); + virtual PView *buildVolumeView(const std::string postFileName); // std::pair<PView *, PView*> buildErrorEstimateView // (const std::string &errorFileName, double, int); // std::pair<PView *, PView*> buildErrorEstimateView diff --git a/Solver/femTerm.h b/Solver/femTerm.h index 85d8ccd94abd9cee987367a7113746bdc92f312e..584b5be3d7fa6f40b5c9984859d4ba39ca83b861 100644 --- a/Solver/femTerm.h +++ b/Solver/femTerm.h @@ -54,7 +54,7 @@ class femTerm { groupOfElements &C) const { groupOfElements::elementContainer::const_iterator it = L.begin(); - for ( ; it != L.end() ; ++it){ + for ( ; it != L.end(); ++it){ MElement *eL = *it; if (&C == &L || C.find(eL)){ SElement se(eL); @@ -78,7 +78,7 @@ class femTerm { { const int nbR = localMatrix.size1(); const int nbC = localMatrix.size2(); - std::vector<Dof> R,C; // better use default consdtructors and reserve the right amount of space to avoid reallocation + std::vector<Dof> R, C; // better use default consdtructors and reserve the right amount of space to avoid reallocation R.reserve(nbR); C.reserve(nbC); bool sym=true; @@ -90,12 +90,12 @@ class femTerm { Dof c(getLocalDofC(se, j)); R.push_back(r); C.push_back(c); - if (!(r==c)) sym=false; + if (!(r == c)) sym = false; } } else { - sym=false; + sym = false; for (int j = 0; j < nbR; j++) R.push_back(getLocalDofR(se, j)); for (int k = 0; k < nbC; k++) @@ -118,6 +118,31 @@ class femTerm { dm.fixVertex(v[i], comp, field, e(v[i]->x(), v[i]->y(), v[i]->z())); } + void neumannNodalBC(MElement *e, int comp, int field, + const simpleFunction<dataVec> &fct, + dofManager<dataVec> &dm) + { + double jac[3][3]; + double sf[256]; + int integrationOrder = 2 * e->getPolynomialOrder(); + int npts; + IntPt *GP; + e->getIntegrationPoints(integrationOrder, &npts, &GP); + for (int ip = 0; ip < npts; ip++){ + const double u = GP[ip].pt[0]; + const double v = GP[ip].pt[1]; + const double w = GP[ip].pt[2]; + const double weight = GP[ip].weight; + const double detJ = e->getJacobian(u, v, w, jac); + SPoint3 p; e->pnt(u, v, w, p); + e->getShapeFunctions(u, v, w, sf); + const dataVec FCT = fct(p.x(), p.y(), p.z()); + for (int k = 0; k < e->getNumShapeFunctions(); k++){ + dm.assemble(e->getShapeFunctionNode(k), comp, field, detJ * weight * sf[k] * FCT); + } + } + } + void neumannNodalBC(int physical, int dim, int comp, int field, const simpleFunction<dataVec> &fct, dofManager<dataVec> &dm) @@ -127,30 +152,31 @@ class femTerm { m->getPhysicalGroups(groups); std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].find(physical); if (it == groups[dim].end()) return; - double jac[3][3]; - double sf[256]; for (unsigned int i = 0; i < it->second.size(); ++i){ GEntity *ge = it->second[i]; for (unsigned int j = 0; j < ge->getNumMeshElements(); j++){ MElement *e = ge->getMeshElement(j); - int integrationOrder = 2 * e->getPolynomialOrder(); - int nbNodes = e->getNumVertices(); - int npts; - IntPt *GP; - e->getIntegrationPoints(integrationOrder, &npts, &GP); - for (int ip = 0; ip < npts; ip++){ - const double u = GP[ip].pt[0]; - const double v = GP[ip].pt[1]; - const double w = GP[ip].pt[2]; - const double weight = GP[ip].weight; - const double detJ = e->getJacobian(u, v, w, jac); - SPoint3 p; e->pnt(u, v, w, p); - e->getShapeFunctions(u, v, w, sf); - const dataVec FCT = fct(p.x(), p.y(), p.z()); - for (int k = 0; k < nbNodes; k++){ - dm.assemble(e->getVertex(k), comp, field, detJ * weight * sf[k] * FCT); - } - } + neumannNodalBC(e, comp, field, fct, dm); + } + } + } + void neumannNormalNodalBC(int physical, int dim, int field, + const simpleFunction<dataVec> &fct, + dofManager<dataVec> &dm) + { + std::map<int, std::vector<GEntity*> > groups[4]; + GModel *m = _gm; + m->getPhysicalGroups(groups); + std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].find(physical); + if (it == groups[dim].end()) return; + for (unsigned int i = 0; i < it->second.size(); ++i){ + GEntity *ge = it->second[i]; + for (unsigned int j = 0; j < ge->getNumMeshElements(); j++){ + MElement *e = ge->getMeshElement(j); + + neumannNodalBC(e, 0, field, fct, dm); + neumannNodalBC(e, 1, field, fct, dm); + neumannNodalBC(e, 2, field, fct, dm); } } } @@ -182,8 +208,8 @@ class DummyfemTerm : public femTerm<double> private : // i dont want to mess with this anymore virtual int sizeOfC(SElement *se) const {return 0;} virtual int sizeOfR(SElement *se) const {return 0;} - virtual Dof getLocalDofR(SElement *se, int iRow) const {return Dof(0,0);} - virtual Dof getLocalDofC(SElement *se, int iCol) const {return Dof(0,0);} + virtual Dof getLocalDofR(SElement *se, int iRow) const {return Dof(0, 0);} + virtual Dof getLocalDofC(SElement *se, int iCol) const {return Dof(0, 0);} virtual void elementMatrix(SElement *se, fullMatrix<dataMat> &m) const {m.scale(0.);} virtual void elementVector(SElement *se, fullVector<dataVec> &m) const {m.scale(0.);} }; diff --git a/Solver/functionSpace.h b/Solver/functionSpace.h index d890cd09f9dfbdee3524b6b5ccfd8c6664bb76cf..a3f356ae9015e0f08c5f878ffa532d259103c898 100644 --- a/Solver/functionSpace.h +++ b/Solver/functionSpace.h @@ -115,7 +115,8 @@ class ScalarLagrangeFunctionSpaceOfElement : public FunctionSpace<double> virtual void f(MElement *ele, double u, double v, double w, std::vector<ValType> &vals) { if(ele->getParent()) { - if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B || + ele->getTypeForMSH() == MSH_POLYG_B) { //FIXME MPolygonBorders... ele->movePointFromParentSpaceToElementSpace(u, v, w); } } @@ -128,7 +129,8 @@ class ScalarLagrangeFunctionSpaceOfElement : public FunctionSpace<double> virtual void gradf(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) { if(ele->getParent()) { - if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B || + ele->getTypeForMSH() == MSH_POLYG_B) { //FIXME MPolygonBorders... ele->movePointFromParentSpaceToElementSpace(u, v, w); } } @@ -150,7 +152,8 @@ class ScalarLagrangeFunctionSpaceOfElement : public FunctionSpace<double> 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... + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B || + ele->getTypeForMSH() == MSH_POLYG_B) { //FIXME MPolygonBorders... ele->movePointFromParentSpaceToElementSpace(u, v, w); } } @@ -169,7 +172,8 @@ class ScalarLagrangeFunctionSpaceOfElement : public FunctionSpace<double> virtual void gradfuvw(MElement *ele, double u, double v, double w, std::vector<GradType> &grads) { if(ele->getParent()) { - if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B) { //FIXME MPolygonBorders... + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B || + ele->getTypeForMSH() == MSH_POLYG_B) { //FIXME MPolygonBorders... ele->movePointFromParentSpaceToElementSpace(u, v, w); } } diff --git a/Solver/terms.cpp b/Solver/terms.cpp index 97f2bf5fc73f54f8810ed88dcc102e31a434c144..cff7fbb8aa25edf1dcdbcf8ab46ebcab5e7db875 100644 --- a/Solver/terms.cpp +++ b/Solver/terms.cpp @@ -142,31 +142,6 @@ void IsotropicElasticTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<do } } -void LagrangeMultiplierTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const -{ - 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; - } - } - } -} - void LagMultTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const { int nbFF1 = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent diff --git a/Solver/terms.h b/Solver/terms.h index 2e0041137d500f6b5411750a283be7bc45abcc2d..b49c75f54dbbebaa56ebe0ee65e84fad711fe1bd 100644 --- a/Solver/terms.h +++ b/Solver/terms.h @@ -34,8 +34,14 @@ inline double dot(const double &a, const double &b) inline int delta(int i,int j) {if (i==j) return 1; else return 0;} - - +inline void setDirection(double &a, const double &b) +{ + a = b; +} +inline void setDirection(SVector3 &a, const SVector3 &b) +{ + for(int i = 0; i < 3; i++) a(i) = b(i); +} template<class T2=double> class ScalarTermBase { @@ -234,9 +240,9 @@ public : template<class T1> class LoadTerm : public LinearTerm<T1> { protected: - simpleFunction<typename TensorialTraits<T1>::ValType> &Load; + simpleFunction<typename TensorialTraits<T1>::ValType> *Load; public : - LoadTerm(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> &Load_) : + LoadTerm(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> *Load_) : LinearTerm<T1>(space1_), Load(Load_) {} virtual ~LoadTerm() {} virtual LinearTermBase<double>* clone () const { return new LoadTerm<T1>(LinearTerm<T1>::space1,Load);} @@ -244,19 +250,19 @@ public : virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<double> > &vv) const {}; }; -class LagrangeMultiplierTerm : public BilinearTerm<SVector3, double> +template<class T1> class LagrangeMultiplierTerm : public BilinearTerm<T1, double> { - SVector3 _d; + T1 _d; public : - LagrangeMultiplierTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<double>& space2_, const SVector3 &d) : - BilinearTerm<SVector3, double>(space1_, space2_) + LagrangeMultiplierTerm(FunctionSpace<T1>& space1_, FunctionSpace<double>& space2_, const T1 &d) : + BilinearTerm<T1, double>(space1_, space2_) { - for (int i = 0; i < 3; i++) _d(i) = d(i); + setDirection(_d, d); } virtual ~LagrangeMultiplierTerm() {} virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const; virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const{}; - virtual BilinearTermBase* clone () const {return new LagrangeMultiplierTerm(BilinearTerm<SVector3, double>::space1,BilinearTerm<SVector3, double>::space2,_d);} + virtual BilinearTermBase* clone () const {return new LagrangeMultiplierTerm(BilinearTerm<T1, double>::space1, BilinearTerm<T1, double>::space2, _d);} }; class LagMultTerm : public BilinearTerm<SVector3, SVector3> @@ -276,9 +282,9 @@ template<class T1> class LoadTermOnBorder : public LinearTerm<T1> { private : double _eqfac; - simpleFunction<typename TensorialTraits<T1>::ValType> &Load; + simpleFunction<typename TensorialTraits<T1>::ValType> *Load; public : - LoadTermOnBorder(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> &Load_, double eqfac = 1.0) : + LoadTermOnBorder(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> *Load_, double eqfac = 1.0) : LinearTerm<T1>(space1_), _eqfac(eqfac), Load(Load_) {} virtual ~LoadTermOnBorder() {} virtual LinearTermBase<double>* clone () const { return new LoadTermOnBorder<T1>(LinearTerm<T1>::space1,Load,_eqfac);} diff --git a/Solver/terms.hpp b/Solver/terms.hpp index fef362b6eaf5920154b3fded57e8bee4bfab591d..a6b0e3f43affd598b45117ad57886235acf90c4f 100644 --- a/Solver/terms.hpp +++ b/Solver/terms.hpp @@ -7,7 +7,7 @@ // Eric Bechet // -#include "terms.h" +//#include "terms.h" template<class T2> void LinearTermBase<T2>::get(MElement *ele, int npts, IntPt *GP, fullVector<T2> &vec) const { @@ -101,7 +101,7 @@ template<class T1> void LoadTerm<T1>::get(MElement *ele, int npts, IntPt *GP, fu 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()); + 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; @@ -191,25 +191,49 @@ template<class T1> void GradTerm<T1>::get(MElement *ele, int npts, IntPt *GP, st } } - +template<class T1> void LagrangeMultiplierTerm<T1>::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + int nbFF1 = BilinearTerm<T1, double>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent + int nbFF2 = BilinearTerm<T1, 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<typename TensorialTraits<T1>::ValType> Vals; + std::vector<TensorialTraits<double>::ValType> ValsT; + BilinearTerm<T1,double>::space1.f(ele, u, v, w, Vals); + BilinearTerm<T1,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; + } + } + } +} template<class T1> void LoadTermOnBorder<T1>::get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) const { - MElement *elep; - if (ele->getParent()) elep = 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]; + 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<typename TensorialTraits<T1>::ValType> Vals; LinearTerm<T1>::space1.f(ele, u, v, w, Vals); + if(ele->getTypeForMSH() == MSH_LIN_B || ele->getTypeForMSH() == MSH_TRI_B || + ele->getTypeForMSH() == MSH_POLYG_B) + ele->movePointFromParentSpaceToElementSpace(u, v, w); SPoint3 p; ele->pnt(u, v, w, p); - typename TensorialTraits<T1>::ValType load = Load(p.x(), p.y(), p.z()); + typename TensorialTraits<T1>::ValType load = (*Load)(p.x(), p.y(), p.z()); for(int j = 0; j < nbFF ; ++j){ m(j) += _eqfac * dot(Vals[j], load) * weight * detJ; } diff --git a/Solver/thermicSolver.cpp b/Solver/thermicSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3ef7885ff69d36bc04fa13f0311821f29ba871c --- /dev/null +++ b/Solver/thermicSolver.cpp @@ -0,0 +1,318 @@ +// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. + +#include <string.h> +#include "GmshConfig.h" +#include "thermicSolver.h" +#include "linearSystemCSR.h" +#include "linearSystemPETSc.h" +#include "linearSystemGMM.h" +#include "linearSystemFull.h" +#include "Numeric.h" +#include "GModel.h" +#include "functionSpace.h" +#include "terms.h" +#include "solverAlgorithms.h" +#include "quadratureRules.h" +#include "solverField.h" +#include "MPoint.h" +#include "gmshLevelset.h" +#if defined(HAVE_POST) +#include "PView.h" +#include "PViewData.h" +#endif + +void thermicSolver::setMesh(const std::string &meshFileName) +{ + pModel = new GModel(); + pModel->readMSH(meshFileName.c_str()); + _dim = pModel->getNumRegions() ? 3 : 2; + + if (LagSpace) delete LagSpace; + LagSpace = new ScalarLagrangeFunctionSpace(_tag); + + if (LagrangeMultiplierSpace) delete LagrangeMultiplierSpace; + LagrangeMultiplierSpace = new ScalarLagrangeFunctionSpaceOfElement(_tag + 1); +} + +void thermicSolver::solve() +{ + linearSystemFull<double> *lsys = new linearSystemFull<double>; +/*#if defined(HAVE_TAUCS) + linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; +#elif defined(HAVE_PETSC) + linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; +#else + linearSystemGmm<double> *lsys = new linearSystemGmm<double>; + lsys->setNoisy(2); +#endif*/ + assemble(lsys); + lsys->systemSolve(); + printf("-- done solving!\n"); +} + +void thermicSolver::cutMesh(gLevelset *ls) +{ + pModel = pModel->buildCutGModel(ls); + pModel->writeMSH("cutMesh.msh"); +} + +void thermicSolver::setThermicDomain(int phys, double k) +{ + thermicField field; + field._k = k; + field._tag = _tag; + field.g = new groupOfElements (_dim, phys); + thermicFields.push_back(field); +} + +void thermicSolver::setLagrangeMultipliers(int phys, double tau, int tag, simpleFunction<double> *f) +{ + LagrangeMultiplierFieldT field; + field._tau = tau; + field._tag = tag; + field._f = f; + field.g = new groupOfElements (_dim - 1, phys); + LagrangeMultiplierFields.push_back(field); +} + +void thermicSolver::setEdgeTemp(int edge, simpleFunction<double> *f) +{ + dirichletBCT diri; + diri.g = new groupOfElements (1, edge); + diri._f = f; + diri._tag = edge; + diri.onWhat = BoundaryConditionT::ON_EDGE; + allDirichlet.push_back(diri); +} + +void thermicSolver::assemble(linearSystem<double> *lsys) +{ + if (pAssembler) delete pAssembler; + pAssembler = new dofManager<double>(lsys); + + // we first do all fixations. the behavior of the dofManager is to + // give priority to fixations : when a dof is fixed, it cannot be + // numbered afterwards + + // Dirichlet conditions + for (unsigned int i = 0; i < allDirichlet.size(); i++){ + FilterDofTrivial filter; + FixNodalDofs(*LagSpace, allDirichlet[i].g->begin(), allDirichlet[i].g->end(), + *pAssembler, *allDirichlet[i]._f, filter); + } + // LagrangeMultipliers + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i){ + NumberDofs(*LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), + LagrangeMultiplierFields[i].g->end(), *pAssembler); + } + // Thermic Fields + for (unsigned int i = 0; i < thermicFields.size(); ++i){ + NumberDofs(*LagSpace, thermicFields[i].g->begin(), thermicFields[i].g->end(), *pAssembler); + } + // Neumann conditions + GaussQuadrature Integ_Boundary(GaussQuadrature::Val); + for (unsigned int i = 0; i < allNeumann.size(); i++){ + std::cout << "Neumann BC" << std::endl; + LoadTerm<double> 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++){ + printf("Lagrange Mult Lag\n"); + LagrangeMultiplierTerm<double> LagTerm(*LagSpace, *LagrangeMultiplierSpace, 1.); + Assemble(LagTerm, *LagSpace, *LagrangeMultiplierSpace, + LagrangeMultiplierFields[i].g->begin(), LagrangeMultiplierFields[i].g->end(), + Integ_LagrangeMult, *pAssembler); + printf("Lagrange Mult Lap\n"); + LaplaceTerm<double, double> LapTerm(*LagrangeMultiplierSpace, + -LagrangeMultiplierFields[i]._tau); + Assemble(LapTerm, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), + LagrangeMultiplierFields[i].g->end(), Integ_Laplace, *pAssembler); + printf("Lagrange Mult Load\n"); + LoadTermOnBorder<double> Lterm(*LagrangeMultiplierSpace, LagrangeMultiplierFields[i]._f); + Assemble(Lterm, *LagrangeMultiplierSpace, LagrangeMultiplierFields[i].g->begin(), + LagrangeMultiplierFields[i].g->end(), Integ_Boundary, *pAssembler); + } + // Assemble thermic term + GaussQuadrature Integ_Bulk(GaussQuadrature::ValVal); + for (unsigned int i = 0; i < thermicFields.size(); i++){ + printf("Thermic Term\n"); + LaplaceTerm<double, double> Tterm(*LagSpace, thermicFields[i]._k); + Assemble(Tterm, *LagSpace, thermicFields[i].g->begin(), thermicFields[i].g->end(), + Integ_Bulk, *pAssembler); + } + + /*for (int i = 0;i<pAssembler->sizeOfR();i++){ + for (int j = 0;j<pAssembler->sizeOfR();j++){ + double d; lsys->getFromMatrix(i, j, d); + printf("%g ", d); + } + double d; lsys->getFromRightHandSide(i, d); + printf(" | %g\n", d); + }*/ + + printf("nDofs=%d\n", pAssembler->sizeOfR()); + printf("nFixed=%d\n", pAssembler->sizeOfF()); +} + +double thermicSolver::computeL2Norm(simpleFunction<double> *sol) { + double val = 0.0; + SolverField<double> solField(pAssembler, LagSpace); + for (unsigned int i = 0; i < thermicFields.size(); ++i){ + for (groupOfElements::elementContainer::const_iterator it = thermicFields[i].g->begin(); it != thermicFields[i].g->end(); ++it){ + MElement *e = *it; +//printf("element (%g,%g) (%g,%g) (%g,%g)\n",e->getVertex(0)->x(),e->getVertex(0)->y(),e->getVertex(1)->x(),e->getVertex(1)->y(),e->getVertex(2)->x(),e->getVertex(2)->y()); + int npts; + IntPt *GP; + double jac[3][3]; + int integrationOrder = 2 * (e->getPolynomialOrder()+5); + e->getIntegrationPoints(integrationOrder, &npts, &GP); + for (int j = 0; j < npts; j++){ + double u = GP[j].pt[0]; + double v = GP[j].pt[1]; + double w = GP[j].pt[2]; + double weight = GP[j].weight; + double detJ = fabs(e->getJacobian (u, v, w, jac)); + SPoint3 p; + e->pnt(u, v, w, p); + double FEMVALUE; + solField.f(e, u, v, w, FEMVALUE); + double diff = (*sol)(p.x(), p.y(), p.z()) - FEMVALUE; + val += diff * diff * detJ * weight; +//printf("(%g %g) : detJ=%g we=%g FV=%g sol=%g diff=%g\n",p.x(),p.y(),detJ,weight,FEMVALUE,(*sol)(p.x(), p.y(), p.z()),diff); + } + } + } +printf("L2Norm = %g\n",sqrt(val)); + return sqrt(val); +} + +double thermicSolver::computeLagNorm(int tag, simpleFunction<double> *sol) { + double val = 0.0, val2 = 0.0; + SolverField<double> solField(pAssembler, LagrangeMultiplierSpace); + for (unsigned int i = 0; i < LagrangeMultiplierFields.size(); ++i){ + if(tag != LagrangeMultiplierFields[i]._tag) continue; + for(groupOfElements::elementContainer::const_iterator it = LagrangeMultiplierFields[i].g->begin(); + it != LagrangeMultiplierFields[i].g->end(); ++it){ + MElement *e = *it; +printf("element (%g,%g) (%g,%g)\n",e->getVertex(0)->x(),e->getVertex(0)->y(),e->getVertex(1)->x(),e->getVertex(1)->y()); + int npts; + IntPt *GP; + double jac[3][3]; + int integrationOrder = 2 * (e->getPolynomialOrder()+1); + e->getIntegrationPoints(integrationOrder, &npts, &GP); + for (int j = 0; j < npts; j++){ + double u = GP[j].pt[0]; + double v = GP[j].pt[1]; + double w = GP[j].pt[2]; + double weight = GP[j].weight; + double detJ = fabs(e->getJacobian (u, v, w, jac)); + SPoint3 p; + e->getParent()->pnt(u, v, w, p); + double FEMVALUE; + solField.f(e, u, v, w, FEMVALUE); + double diff = (*sol)(p.x(), p.y(), p.z()) - FEMVALUE; + val += diff * diff * detJ * weight; + val2 += (*sol)(p.x(), p.y(), p.z()) * (*sol)(p.x(), p.y(), p.z()) * detJ * weight; +printf("(%g %g) : u,v=(%g,%g) detJ=%g we=%g FV=%g sol=%g diff=%g\n",p.x(),p.y(),u,v,detJ,weight,FEMVALUE,(*sol)(p.x(), p.y(), p.z()),diff); + } + } + } +printf("LagNorm = %g\n",sqrt(val/val2)); + return sqrt(val/val2); +} + +#if defined(HAVE_POST) + +PView* thermicSolver::buildTemperatureView (const std::string postFileName) +{ + std::cout << "build Temperature View"<< std::endl; + std::set<MVertex*> v; + std::map<MVertex*, MElement*> vCut; + for (unsigned int i = 0; i < thermicFields.size(); ++i){ + for (groupOfElements::elementContainer::const_iterator it = thermicFields[i].g->begin(); it != thermicFields[i].g->end(); ++it){ + MElement *e = *it; + 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<double> Field(pAssembler, LagSpace); + for (std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it){ + double val; + MPoint p(*it); + Field.f(&p, 0, 0, 0, val); //printf("valv=%g\n",val); + std::vector<double> vec; vec.push_back(val); + data[(*it)->getNum()] = vec; + } + for (std::map<MVertex*, MElement*>::iterator it = vCut.begin(); it != vCut.end(); ++it){ + double 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); //printf("valvc=%g\n",val); + std::vector<double> vec; vec.push_back(val); + data[it->first->getNum()] = vec; + } + PView *pv = new PView (postFileName, "NodeData", pModel, data, 0.0, 1); + return pv; +} + +PView* thermicSolver::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, 1); + return pv; +} + +#else +PView* thermicSolver::buildTemperatureView(const std::string postFileName) +{ + Msg::Error("Post-pro module not available"); + return 0; +} + +PView* thermicSolver::buildLagrangeMultiplierView (const std::string postFileName) +{ + Msg::Error("Post-pro module not available"); + return 0; +} +#endif + + + + + diff --git a/Solver/thermicSolver.h b/Solver/thermicSolver.h new file mode 100644 index 0000000000000000000000000000000000000000..59c42456f0b5432edeef422b923024771c56d055 --- /dev/null +++ b/Solver/thermicSolver.h @@ -0,0 +1,100 @@ +// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. + +#ifndef _THERMIC_SOLVER_H_ +#define _THERMIC_SOLVER_H_ + +#include <map> +#include <string> +#include "SVector3.h" +#include "dofManager.h" +#include "simpleFunction.h" +#include "functionSpace.h" + +class GModel; +class PView; +class groupOfElements; +class gLevelset; + +struct LagrangeMultiplierFieldT { + int _tag; + groupOfElements *g; + double _tau; + simpleFunction<double> *_f; + LagrangeMultiplierFieldT() : _tag(0), g(0){} +}; + +struct thermicField { + int _tag; // tag for the dofManager + groupOfElements *g; // support for this field + double _k; // diffusivity + thermicField () : _tag(0), g(0){} +}; + +struct BoundaryConditionT +{ + int _tag; // tag for the dofManager + enum location{UNDEF, ON_VERTEX, ON_EDGE, ON_FACE, ON_VOLUME}; + location onWhat; // on vertices or elements + groupOfElements *g; // support for this BC + BoundaryConditionT() : _tag(0), onWhat(UNDEF), g(0) {} +}; + +struct dirichletBCT : public BoundaryConditionT +{ + simpleFunction<double> *_f; + dirichletBCT ():BoundaryConditionT(), _f(0){} +}; + +struct neumannBCT : public BoundaryConditionT +{ + simpleFunction<double> *_f; + neumannBCT () : BoundaryConditionT(), _f(0){} +}; +// a thermic solver ... +class thermicSolver +{ + protected: + GModel *pModel; + int _dim, _tag; + dofManager<double> *pAssembler; + FunctionSpace<double> *LagSpace; + FunctionSpace<double> *LagrangeMultiplierSpace; + + // young modulus and poisson coefficient per physical + std::vector<thermicField> thermicFields; + std::vector<LagrangeMultiplierFieldT> LagrangeMultiplierFields; + // neumann BC + std::vector<neumannBCT> allNeumann; + // dirichlet BC + std::vector<dirichletBCT> allDirichlet; + + public: + thermicSolver(int tag) : _tag(tag), pAssembler(0), LagSpace(0), LagrangeMultiplierSpace(0) {} + + virtual ~thermicSolver() + { + if (LagSpace) delete LagSpace; + if (LagrangeMultiplierSpace) delete LagrangeMultiplierSpace; + if (pAssembler) delete pAssembler; + } + void assemble (linearSystem<double> *lsys); + virtual void setMesh(const std::string &meshFileName); + void cutMesh(gLevelset *ls); + void setThermicDomain(int phys, double k); + void setLagrangeMultipliers(int phys, double tau, int tag, simpleFunction<double> *f); + void setEdgeTemp(int edge, simpleFunction<double> *f); + void solve(); + virtual PView *buildTemperatureView(const std::string postFileName); + virtual PView *buildLagrangeMultiplierView(const std::string posFileName); + double computeL2Norm(simpleFunction<double> *f); + double computeLagNorm(int tag, simpleFunction<double> *f); + // std::pair<PView *, PView*> buildErrorEstimateView + // (const std::string &errorFileName, double, int); + // std::pair<PView *, PView*> buildErrorEstimateView + // (const std::string &errorFileName, const elasticityData &ref, double, int); +}; + +#endif diff --git a/wrappers/gmshpy/gmshPost.i b/wrappers/gmshpy/gmshPost.i index d30cc19dba658416f19e463a0fc9416965cd6aae..6b68a2caa2915b865c5fe2c6d6109a5afdd07c7a 100644 --- a/wrappers/gmshpy/gmshPost.i +++ b/wrappers/gmshpy/gmshPost.i @@ -16,6 +16,7 @@ #include "PViewFactory.h" #include "PViewData.h" #include "PViewAsSimpleFunction.h" + #include "PViewDataGModel.h" #endif %} @@ -34,6 +35,7 @@ namespace std { %include "simpleFunction.h" %template(simpleFunctionDouble) simpleFunction<double>; %include "PViewAsSimpleFunction.h" +%include "PViewDataGModel.h" %include "Plugin.h" %include "PluginManager.h" #endif diff --git a/wrappers/gmshpy/gmshSolver.i b/wrappers/gmshpy/gmshSolver.i index 881d8ad93859331e7ff5367fec2375c36ad83a09..6c22c518dd5088610ba635137cdb65074af16b63 100644 --- a/wrappers/gmshpy/gmshSolver.i +++ b/wrappers/gmshpy/gmshSolver.i @@ -10,6 +10,7 @@ #if defined(HAVE_SOLVER) #include "dofManager.h" #include "elasticitySolver.h" + #include "thermicSolver.h" #include "frameSolver.h" #include "linearSystem.h" #include "linearSystemCSR.h" @@ -24,6 +25,7 @@ %include "dofManager.h" %template(dofManagerDouble) dofManager<double>; %include "elasticitySolver.h" +%include "thermicSolver.h" %include "frameSolver.h" %include "linearSystem.h" %template(linearSystemDouble) linearSystem<double>;