PView *GMSH_DistancePlugin::execute(PView *v) { int id_pt = (int) DistanceOptions_Number[0].def; int id_line = (int) DistanceOptions_Number[1].def; int id_face = (int) DistanceOptions_Number[2].def; double type = (double) DistanceOptions_Number[3].def; int ortho = (int) DistanceOptions_Number[6].def; PView *view = new PView(); _data = getDataList(view); #if defined(HAVE_SOLVER) #if defined(HAVE_TAUCS) linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> * dofView = new dofManager<double>(lsys); #endif std::vector<GEntity*> _entities; GModel::current()->getEntities(_entities); if (!_entities.size() || !_entities[_entities.size()-1]->getMeshElement(0)) { Msg::Error("This plugin needs a mesh !"); return view; } GEntity* ge = _entities[_entities.size()-1]; int integrationPointTetra[2] = {0,0}; int numnodes = 0; for (unsigned int i = 0; i < _entities.size()-1; i++) numnodes += _entities[i]->mesh_vertices.size(); int totNodes = numnodes + _entities[_entities.size()-1]->mesh_vertices.size(); int order = ge->getMeshElement(0)->getPolynomialOrder(); int totNumNodes = totNodes + ge->getNumMeshElements()*integrationPointTetra[order-1]; std::vector<SPoint3> pts; std::vector<double> distances; std::vector<MVertex* > pt2Vertex; pts.clear(); distances.clear(); pt2Vertex.clear(); pts.reserve(totNumNodes); distances.reserve(totNumNodes); pt2Vertex.reserve(totNumNodes); std::map<MVertex*,double> _distanceE_map; std::map<MVertex*,int> _isInYarn_map; std::vector<int> index; std::vector<double> distancesE; std::vector<double> distances2; std::vector<double> distancesE2; std::vector<int> isInYarn; std::vector<int> isInYarn2; std::vector<SPoint3> closePts; std::vector<SPoint3> closePts2; for (int i=0; i<totNumNodes; i++) { distances.push_back(1.e22); } int k = 0; for (unsigned int i=0; i<_entities.size(); i++){ GEntity* ge = _entities[i]; _maxDim = std::max(_maxDim, ge->dim()); for (unsigned int j=0; j<ge->mesh_vertices.size(); j++) { MVertex *v = ge->mesh_vertices[j]; pts.push_back(SPoint3(v->x(), v->y(), v->z())); _distance_map.insert(std::make_pair(v, 0.0)); /* TO DO (by AM) SPoint3 p_empty(); _closePts_map.insert(std::make_pair(v, p_empty)); */ pt2Vertex[k] = v; k++; } } // Compute geometrical distance to mesh boundaries //------------------------------------------------------ if (type < 0.0 ) { bool existEntity = false; for (unsigned int i=0; i<_entities.size(); i++) { GEntity* g2 = _entities[i]; int gDim = g2->dim(); std::vector<int> phys = g2->getPhysicalEntities(); bool computeForEntity = false; for(unsigned int k = 0; k<phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) computeForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2)) computeForEntity = true; } if (computeForEntity) { existEntity = true; for (unsigned int k = 0; k < g2->getNumMeshElements(); k++) { std::vector<double> iDistances; std::vector<SPoint3> iClosePts; std::vector<double> iDistancesE; std::vector<int> iIsInYarn; MElement *e = g2->getMeshElement(k); MVertex *v1 = e->getVertex(0); MVertex *v2 = e->getVertex(1); SPoint3 p1(v1->x(), v1->y(), v1->z()); SPoint3 p2(v2->x(), v2->y(), v2->z()); if ((e->getNumVertices() == 2 && order == 1) || (e->getNumVertices() == 3 && order == 2)) { signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2); } else if ((e->getNumVertices() == 3 && order == 1) || (e->getNumVertices() == 6 && order == 2)) { MVertex *v3 = e->getVertex(2); SPoint3 p3 (v3->x(),v3->y(),v3->z()); signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2, p3); } for (unsigned int kk=0; kk<pts.size(); kk++) { if (std::abs(iDistances[kk]) < distances[kk]) { distances[kk] = std::abs(iDistances[kk]); MVertex *v = pt2Vertex[kk]; _distance_map[v] = distances[kk]; /* TO DO (by AM) _closePts_map[v] = iClosePts[kk]; */ } } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } printView(_entities, _distance_map); /* TO DO (by AM) printView(_entities, _closePts_map); */ } // Compute PDE for distance function //----------------------------------- else if (type > 0.0) { #if defined(HAVE_SOLVER) bool existEntity = false; SBoundingBox3d bbox; for(unsigned int i = 0; i < _entities.size(); i++){ GEntity* ge = _entities[i]; int gDim = ge->dim(); bool fixForEntity = false; std::vector<int> phys = ge->getPhysicalEntities(); for(unsigned int k = 0; k < phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) fixForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2) ) fixForEntity = true; } if (fixForEntity) { existEntity = true; for (unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); for (int k=0; k<t->getNumVertices(); k++) { MVertex *v = t->getVertex(k); dofView->fixVertex(v, 0, 1, 0.); bbox += SPoint3(v->x(), v->y(), v->z()); } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if(_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for(unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); allElems.push_back(t); for (int k = 0; k < t->getNumVertices(); k++) dofView->numberVertex(t->getVertex(k), 0, 1); } } } double L = norm(SVector3(bbox.max(), bbox.min())); double mu = type*L; simpleFunction<double> DIFF(mu*mu), ONE(1.0); distanceTerm distance(GModel::current(), 1, &DIFF, &ONE); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); distance.addToMatrix(*dofView, &se); } groupOfElements gr(allElems); distance.addToRightHandSide(*dofView, gr); Msg::Info("Distance Computation: Assembly done"); lsys->systemSolve(); Msg::Info("Distance Computation: System solved"); for (std::map<MVertex*,double >::iterator itv = _distance_map.begin(); itv != _distance_map.end() ; ++itv) { MVertex *v = itv->first; double value; dofView->getDofValue(v, 0, 1, value); value = std::min(0.9999, value); double dist = -mu * log(1. - value); itv->second = dist; } printView(_entities, _distance_map); #endif } _data->setName("distance"); _data->Time.push_back(0); _data->setFileName(_fileName.c_str()); _data->finalize(); // compute also orthogonal vector to distance field // A Uortho = -C DIST //------------------------------------------------ if (ortho > 0) { #if defined(HAVE_SOLVER) #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys2 = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys2 = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> myAssembler(lsys2); simpleFunction<double> ONE(1.0); double dMax = 1.0; //EMI TO CHANGE std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if (_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for (unsigned int i=0; i<ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); double vMean = 0.0; for (int k = 0; k < t->getNumVertices(); k++) { std::map<MVertex*, double>::iterator it = _distance_map.find(t->getVertex(k)); vMean += it->second; } vMean /= t->getNumVertices(); if (vMean < dMax) allElems.push_back(ge->getMeshElement(i)); } } } int mid = (int)floor(allElems.size() / 2.); MElement *e = allElems[mid]; MVertex *vFIX = e->getVertex(0); myAssembler.fixVertex(vFIX, 0, 1, 0.0); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *t = *it; for(int k = 0; k < t->getNumVertices(); k++) myAssembler.numberVertex(t->getVertex(k), 0, 1); } orthogonalTerm *ortho; ortho = new orthogonalTerm(GModel::current(), 1, &ONE, &_distance_map); // if (type < 0) // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, view); // else // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, dofView); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); ortho->addToMatrix(myAssembler, &se); } groupOfElements gr(allElems); ortho->addToRightHandSide(myAssembler, gr); Msg::Info("Orthogonal Computation: Assembly done"); lsys2->systemSolve(); Msg::Info("Orthogonal Computation: System solved"); PView *view2 = new PView(); PViewDataList *data2 = getDataList(view2); data2->setName("ortogonal field"); Msg::Info("Writing orthogonal.pos"); FILE * f5 = Fopen("orthogonal.pos","w"); fprintf(f5,"View \"orthogonal\"{\n"); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *e = *it; int numNodes = e->getNumVertices(); if (e->getType() == TYPE_POLYG) numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices(); std::vector<double> x(numNodes), y(numNodes), z(numNodes); std::vector<double> *out2 = data2->incrementList(1, e->getType(), numNodes); std::vector<MVertex*> nods; std::vector<double> orth; if(!e->getNumChildren()) for(int i=0; i<numNodes; i++) nods.push_back(e->getVertex(i)); else for(int i = 0; i < e->getNumChildren(); i++) for(int j = 0; j < e->getChild(i)->getNumVertices(); j++) nods.push_back(e->getChild(i)->getVertex(j)); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->x()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->y()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->z()); if (_maxDim == 2) switch (numNodes) { case 2: fprintf(f5,"SL("); break; case 3: fprintf(f5,"ST("); break; case 4: fprintf(f5,"SQ("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } else if (_maxDim == 3) switch (numNodes) { case 4: fprintf(f5,"SS("); break; case 8: fprintf(f5,"SH("); break; case 6: fprintf(f5,"SI("); break; case 5: fprintf(f5,"SY("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } for (int j=0; j<numNodes; j++) { MVertex *v = nods[j]; if (j) fprintf(f5, ",%g,%g,%g", v->x(), v->y(), v->z()); else fprintf(f5, "%g,%g,%g", v->x(), v->y(), v->z()); double value; myAssembler.getDofValue(v, 0, 1, value); orth.push_back(value); } fprintf(f5,"){"); for (unsigned int i=0; i<orth.size(); i++) { out2->push_back(orth[i]); if (i) fprintf(f5,",%g", orth[i]); else fprintf(f5,"%g", orth[i]); } fprintf(f5,"};\n"); } fprintf(f5,"};\n"); fclose(f5); lsys->clear(); lsys2->clear(); data2->Time.push_back(0); data2->setFileName("orthogonal.pos"); data2->finalize(); #endif } return view; }
void highOrderTools::applySmoothingTo(std::vector<MElement*> &all, GFace *gf) { #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; #endif // compute the straight sided positions of high order nodes that are // on the edges of the face in the UV plane dofManager<double> myAssembler(lsys); elasticityTerm El(0, 1.0, CTX::instance()->mesh.hoPoissonRatio, _tag); std::vector<MElement*> layer, v; double minD; getDistordedElements(all, CTX::instance()->mesh.hoThresholdMin, v, minD); int numBad = v.size(); const int nbLayers = CTX::instance()->mesh.hoNLayers; for (int i = 0; i < nbLayers; i++){ addOneLayer(all, v, layer); v.insert(v.end(), layer.begin(), layer.end()); } if (!v.size()) return; Msg::Info("Smoothing high order mesh : model face %d (%d elements considered in " "the elastic analogy, worst mapping %12.5E, %3d bad elements)", gf->tag(), v.size(),minD,numBad); addOneLayer(all, v, layer); std::set<MVertex*>::iterator it; std::set<MVertex*> verticesToMove; // on the last layer, fix displacement to 0 for (unsigned int i = 0; i < layer.size(); i++){ for (int j = 0; j < layer[i]->getNumVertices(); j++){ MVertex *vert = layer[i]->getVertex(j); myAssembler.fixVertex(vert, 0, _tag, 0); myAssembler.fixVertex(vert, 1, _tag, 0); } } // fix all vertices that cannot move for (unsigned int i = 0; i < v.size(); i++){ moveToStraightSidedLocation(v[i]); for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); if (vert->onWhat()->dim() < 2){ double du = 0, dv = 0; myAssembler.fixVertex(vert, 0, _tag, du); myAssembler.fixVertex(vert, 1, _tag, dv); } } } // number the other DOFs for (unsigned int i = 0; i < v.size(); i++){ for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); myAssembler.numberVertex(vert, 0, _tag); myAssembler.numberVertex(vert, 1, _tag); verticesToMove.insert(vert); } } double dx0 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); double dx = dx0; Msg::Debug(" dx0 = %12.5E", dx0); int iter = 0; while(0){ double dx2 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); Msg::Debug(" dx2 = %12.5E", dx2); if (fabs(dx2 - dx) < 1.e-4 * dx0)break; if (iter++ > 2)break; dx = dx2; } for (it = verticesToMove.begin(); it != verticesToMove.end(); ++it){ SPoint2 param; if ((*it)->onWhat()->dim() == 2){ reparamMeshVertexOnFace(*it, gf, param); GPoint gp = gf->point(param); (*it)->x() = gp.x(); (*it)->y() = gp.y(); (*it)->z() = gp.z(); _targetLocation[*it] = SVector3(gp.x(), gp.y(), gp.z()); } else{ SVector3 p = getTL(*it); (*it)->x() = p.x(); (*it)->y() = p.y(); (*it)->z() = p.z(); } } delete lsys; }
// apply a displacement that does not create elements that are // distorted over a value "thres" double highOrderTools::apply_incremental_displacement(double max_incr, std::vector<MElement*> & v, bool mixed, double thres, char *meshName, std::vector<MElement*> & disto) { #ifdef HAVE_PETSC // assume that the mesh is OK, yet already curved //linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; lsys->setParameter("petscOptions","-pc_type ilu"); lsys->setParameter("petscOptions","-ksp_monitor"); dofManager<double> myAssembler(lsys); elasticityMixedTerm El_mixed (0, 1.0, .333, _tag); elasticityTerm El (0, 1.0, .333, _tag); std::set<MVertex*> _vertices; //+++++++++ Boundary Conditions & Numbering +++++++++++++++++++++++++++++++ // fix all dof that correspond to vertices on the boundary // the value is equal for (unsigned int i = 0; i < v.size(); i++){ for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); _vertices.insert(vert); } } //+++++++++ Fix d tr(eps) = 0 +++++++++++++++++++++++++++++++ if (mixed){ for (unsigned int i = 0; i < disto.size(); i++){ for (int j = 0; j < disto[i]->getNumVertices(); j++){ MVertex *vert = disto[i]->getVertex(j); myAssembler.fixVertex(vert, 4, _tag, 0.0); } } } for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ MVertex *vert = *it; std::map<MVertex*,SVector3>::iterator itt = _targetLocation.find(vert); // impose displacement @ boundary if (itt != _targetLocation.end() && vert->onWhat()->dim() < _dim){ myAssembler.fixVertex(vert, 0, _tag, itt->second.x()-vert->x()); myAssembler.fixVertex(vert, 1, _tag, itt->second.y()-vert->y()); myAssembler.fixVertex(vert, 2, _tag, itt->second.z()-vert->z()); } // ensure we do not touch any vertex that is on the boundary else if (vert->onWhat()->dim() < _dim){ myAssembler.fixVertex(vert, 0, _tag, 0); myAssembler.fixVertex(vert, 1, _tag, 0); myAssembler.fixVertex(vert, 2, _tag, 0); } // } if (_dim == 2)myAssembler.fixVertex(vert, 2, _tag, 0); // number vertices myAssembler.numberVertex(vert, 0, _tag); myAssembler.numberVertex(vert, 1, _tag); myAssembler.numberVertex(vert, 2, _tag); if (mixed){ myAssembler.numberVertex(vert, 3, _tag); myAssembler.numberVertex(vert, 4, _tag); } } if (myAssembler.sizeOfR()){ // assembly of the elasticity term on the for (unsigned int i = 0; i < v.size(); i++){ SElement se(v[i]); if (mixed) El_mixed.addToMatrix(myAssembler, &se); else El.addToMatrix(myAssembler, &se); } // solve the system lsys->systemSolve(); } // Move vertices @ maximum FILE *fd = Fopen ("d.msh","w"); fprintf(fd,"$MeshFormat\n2 0 8\n$EndMeshFormat\n$NodeData\n1\n" "\"tr(sigma)\"\n1\n0.0\n3\n1\n3\n%d\n", (int) _vertices.size()); for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ double ax, ay, az; myAssembler.getDofValue(*it, 0, _tag, ax); myAssembler.getDofValue(*it, 1, _tag, ay); myAssembler.getDofValue(*it, 2, _tag, az); (*it)->x() += max_incr*ax; (*it)->y() += max_incr*ay; (*it)->z() += max_incr*az; fprintf(fd,"%d %g %g %g\n",(*it)->getIndex(), ax,ay,az); } fprintf(fd,"$EndNodeData\n"); fclose(fd); // Check now if elements are ok (*_vertices.begin())->onWhat()->model()->writeMSH(meshName); double percentage = max_incr * 100.; while(1){ std::vector<MElement*> disto; double minD; getDistordedElements(v, 0.5, disto, minD); if (minD < thres){ percentage -= 10.; for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ double ax, ay, az; myAssembler.getDofValue(*it, 0, _tag, ax); myAssembler.getDofValue(*it, 1, _tag, ay); myAssembler.getDofValue(*it, 2, _tag, az); (*it)->x() -= .1*ax; (*it)->y() -= .1*ay; (*it)->z() -= .1*az; } } else break; } delete lsys; return percentage; #endif return 0.0; }
void backgroundMesh2D::propagateValues(DoubleStorageType &dirichlet, simpleFunction<double> &eval_diffusivity, bool in_parametric_plane) { #if defined(HAVE_SOLVER) linearSystem<double> *_lsys = 0; #if defined(HAVE_PETSC) && !defined(HAVE_TAUCS) _lsys = new linearSystemPETSc<double>; #elif defined(HAVE_GMM) && !defined(HAVE_TAUCS) linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>; _lsysb->setGmres(1); _lsys = _lsysb; #elif defined(HAVE_TAUCS) _lsys = new linearSystemCSRTaucs<double>; #else _lsys = new linearSystemFull<double>; #endif dofManager<double> myAssembler(_lsys); // fix boundary conditions DoubleStorageType::iterator itv = dirichlet.begin(); for ( ; itv != dirichlet.end(); ++itv) { myAssembler.fixVertex(itv->first, 0, 1, itv->second); } // Number vertices std::set<MVertex*> vs; GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); delete _lsys; return; } for (unsigned int k = 0; k < face->triangles.size(); k++) for (int j=0; j<3; j++)vs.insert(face->triangles[k]->getVertex(j)); for (unsigned int k = 0; k < face->quadrangles.size(); k++) for (int j=0; j<4; j++)vs.insert(face->quadrangles[k]->getVertex(j)); std::map<MVertex*,SPoint3> theMap; if ( in_parametric_plane) { for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { SPoint2 p; reparamMeshVertexOnFace ( *it, face, p); theMap[*it] = SPoint3((*it)->x(),(*it)->y(),(*it)->z()); (*it)->setXYZ(p.x(),p.y(),0.0); } } for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) myAssembler.numberVertex(*it, 0, 1); // Assemble laplaceTerm l(0, 1, &eval_diffusivity); for (unsigned int k = 0; k < face->triangles.size(); k++) { MTriangle *t = face->triangles[k]; SElement se(t); l.addToMatrix(myAssembler, &se); } // Solve if (myAssembler.sizeOfR()) { _lsys->systemSolve(); } // save solution for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { myAssembler.getDofValue(*it, 0, 1, dirichlet[*it]); } if ( in_parametric_plane) { for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { SPoint3 p = theMap[(*it)]; (*it)->setXYZ(p.x(),p.y(),p.z()); } } delete _lsys; #endif }