Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
// 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;
}
Exemplo n.º 4
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
}