23 #if defined(HAVE_SOLVER) 
   32 static const int NBANN = 2;
 
   44     Msg::Error(
"Maximum number of threads (%d) exceeded in background mesh",
 
   77   : _octree(
nullptr), uv_kdtree(
nullptr), nodes(
nullptr), angle_nodes(
nullptr),
 
   82     Msg::Debug(
"Building cross field using closest distance");
 
   83     propagateCrossFieldByDistance(_gf);
 
   91   std::set<SPoint2> myBCNodes;
 
   92   for(std::size_t i = 0; i < _gf->
triangles.size(); i++) {
 
   95     for(
int j = 0; j < 3; j++) {
 
   97       auto it = _3Dto2D.find(v);
 
   99       if(it == _3Dto2D.end()) {
 
  103         _vertices.push_back(newv);
 
  106         if(v->
onWhat()->
dim() < 2) myBCNodes.insert(p);
 
  113     _triangles.push_back(T2D);
 
  116 #if defined(HAVE_ANN) 
  117   index = 
new ANNidx[2];
 
  118   dist = 
new ANNdist[2];
 
  119   nodes = annAllocPts(myBCNodes.size(), 3);
 
  120   auto itp = myBCNodes.begin();
 
  122   while(itp != myBCNodes.end()) {
 
  124     nodes[ind][0] = pt.
x();
 
  125     nodes[ind][1] = pt.
y();
 
  130   uv_kdtree = 
new ANNkd_tree(nodes, myBCNodes.size(), 3);
 
  137   if(
CTX::instance()->mesh.lcFromPoints) { propagate1dMesh(_gf); }
 
  139     auto itv2 = _2Dto3D.begin();
 
  140     for(; itv2 != _2Dto3D.end(); ++itv2) {
 
  148   propagateCrossField(_gf);
 
  159 #if defined(HAVE_ANN) 
  160   if(uv_kdtree) 
delete uv_kdtree;
 
  161   if(angle_kdtree) 
delete angle_kdtree;
 
  162   if(nodes) annDeallocPts(nodes);
 
  163   if(angle_nodes) annDeallocPts(angle_nodes);
 
  170                                   std::map<MVertex *, double> &dirichlet,
 
  172                                   bool in_parametric_plane = 
false)
 
  174 #if defined(HAVE_SOLVER) 
  175 #if defined(HAVE_PETSC) 
  177 #elif defined(HAVE_GMM) 
  186   auto itv = dirichlet.begin();
 
  187   for(; itv != dirichlet.end(); ++itv) {
 
  188     myAssembler.
fixVertex(itv->first, 0, 1, itv->second);
 
  192   std::set<MVertex *> vs;
 
  193   for(std::size_t k = 0; k < _gf->
triangles.size(); k++)
 
  194     for(
int j = 0; j < 3; j++) vs.insert(_gf->
triangles[k]->getVertex(j));
 
  195   for(std::size_t k = 0; k < _gf->
quadrangles.size(); k++)
 
  196     for(
int j = 0; j < 4; j++) vs.insert(_gf->
quadrangles[k]->getVertex(j));
 
  198   std::map<MVertex *, SPoint3> theMap;
 
  199   if(in_parametric_plane) {
 
  200     for(
auto it = vs.begin(); it != vs.end(); ++it) {
 
  203       theMap[*it] = 
SPoint3((*it)->x(), (*it)->y(), (*it)->z());
 
  204       (*it)->setXYZ(p.
x(), p.
y(), 0.0);
 
  208   for(
auto it = vs.begin(); it != vs.end(); ++it)
 
  213   for(std::size_t k = 0; k < _gf->
triangles.size(); k++) {
 
  223   for(
auto it = vs.begin(); it != vs.end(); ++it) {
 
  224     myAssembler.
getDofValue(*it, 0, 1, dirichlet[*it]);
 
  227   if(in_parametric_plane) {
 
  228     for(
auto it = vs.begin(); it != vs.end(); ++it) {
 
  230       (*it)->setXYZ(p.
x(), p.
y(), p.
z());
 
  239   std::vector<GEdge *> 
const &e = _gf->
edges();
 
  241   std::map<MVertex *, double> sizes;
 
  243   for(; it != e.end(); ++it) {
 
  244     if(!(*it)->isSeam(_gf)) {
 
  245       for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
 
  246         MVertex *v1 = (*it)->lines[i]->getVertex(0);
 
  247         MVertex *v2 = (*it)->lines[i]->getVertex(1);
 
  249           double d = sqrt((v1->
x() - v2->
x()) * (v1->
x() - v2->
x()) +
 
  250                           (v1->
y() - v2->
y()) * (v1->
y() - v2->
y()) +
 
  251                           (v1->
z() - v2->
z()) * (v1->
z() - v2->
z()));
 
  252           for(
int k = 0; k < 2; k++) {
 
  253             MVertex *v = (*it)->lines[i]->getVertex(k);
 
  254             auto itv = sizes.find(v);
 
  255             if(itv == sizes.end())
 
  258               itv->second = 0.5 * (itv->second + log(d));
 
  269   for(; itv2 != 
_2Dto3D.end(); ++itv2) {
 
  272     _sizes[v_2D] = exp(sizes[v_3D]);
 
  281     Msg::Warning(
"cannot reparametrize a point in crossField");
 
  293   std::vector<GEdge *> 
const &e = _gf->
edges();
 
  295   std::map<MVertex *, double> _cosines4, _sines4;
 
  296   std::map<MVertex *, SPoint2> _param;
 
  298   for(; it != e.end(); ++it) {
 
  299     if(!(*it)->isSeam(_gf)) {
 
  300       for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
 
  302         v[0] = (*it)->lines[i]->getVertex(0);
 
  303         v[1] = (*it)->lines[i]->getVertex(1);
 
  309         SVector3 t2(v[1]->x() - v[0]->x(), v[1]->y() - v[0]->y(),
 
  310                     v[1]->
z() - v[0]->
z());
 
  313         double _angle = 
angle(t1, t2);
 
  316         for(
int i = 0; i < 2; i++) {
 
  317           auto itc = _cosines4.find(v[i]);
 
  318           auto its = _sines4.find(v[i]);
 
  319           if(itc != _cosines4.end()) {
 
  320             itc->second = 0.5 * (itc->second + cos(4 * _angle));
 
  321             its->second = 0.5 * (its->second + sin(4 * _angle));
 
  324             _param[v[i]] = (i == 0) ? p1 : p2;
 
  325             _cosines4[v[i]] = cos(4 * _angle);
 
  326             _sines4[v[i]] = sin(4 * _angle);
 
  333 #if defined(HAVE_ANN) 
  334   index = 
new ANNidx[NBANN];
 
  335   dist = 
new ANNdist[NBANN];
 
  336   angle_nodes = annAllocPts(_cosines4.size(), 3);
 
  337   auto itp = _cosines4.begin();
 
  341   while(itp != _cosines4.end()) {
 
  343     double c = itp->second;
 
  345     double s = _sines4[v];
 
  346     angle_nodes[ind][0] = pt.
x();
 
  347     angle_nodes[ind][1] = pt.
y();
 
  348     angle_nodes[ind][2] = 0.0;
 
  354   angle_kdtree = 
new ANNkd_tree(angle_nodes, _cosines4.size(), 3);
 
  360   double cosTheta = 
dot(a, b);
 
  362   return atan2(sinTheta, cosTheta);
 
  378   double a[3] = {cos(4 * i0->second), cos(4 * i1->second), cos(4 * i2->second)};
 
  379   double b[3] = {sin(4 * i0->second), sin(4 * i1->second), sin(4 * i2->second)};
 
  382   const double gradcos = sqrt(
f[0] * 
f[0] + 
f[1] * 
f[1] + 
f[2] * 
f[2]);
 
  386   return (gradcos ) * h;
 
  400   double a[3] = {cos(4 * i0->second), cos(4 * i1->second), cos(4 * i2->second)};
 
  401   double b[3] = {sin(4 * i0->second), sin(4 * i1->second), sin(4 * i2->second)};
 
  404   const double gradcos = sqrt(
f[0] * 
f[0] + 
f[1] * 
f[1] + 
f[2] * 
f[2]);
 
  408   return (gradcos ) * h;
 
  420     for(std::size_t i = 0; i < _gf->
triangles.size(); i++) {
 
  422       double val = smoothness < .5 ? 1.0 : 1.e-3; 
 
  430     if(++ITER > 0) 
break;
 
  435   sprintf(name, 
"cross-%d-%d.pos", _gf->
tag(), ITER);
 
  437   sprintf(name, 
"smooth-%d-%d.pos", _gf->
tag(), ITER);
 
  451   std::map<MVertex *, double> _cosines4, _sines4;
 
  452   std::vector<GEdge *> 
const &e = _gf->
edges();
 
  454   for(; it != e.end(); ++it) {
 
  455     if(!(*it)->isSeam(_gf)) {
 
  456       for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
 
  458         v[0] = (*it)->lines[i]->getVertex(0);
 
  459         v[1] = (*it)->lines[i]->getVertex(1);
 
  467         SVector3 d1(v[1]->x() - v[0]->x(), v[1]->y() - v[0]->y(),
 
  468                     v[1]->
z() - v[0]->
z());
 
  471         double _angle = 
myAngle(t1, d1, n);
 
  473         for(
int i = 0; i < 2; i++) {
 
  474           auto itc = _cosines4.find(v[i]);
 
  475           auto its = _sines4.find(v[i]);
 
  476           if(itc != _cosines4.end()) {
 
  477             itc->second = 0.5 * (itc->second + cos(4 * _angle));
 
  478             its->second = 0.5 * (its->second + sin(4 * _angle));
 
  481             _cosines4[v[i]] = cos(4 * _angle);
 
  482             _sines4[v[i]] = sin(4 * _angle);
 
  496   for(; itv2 != 
_2Dto3D.end(); ++itv2) {
 
  499     double angle = atan2(_sines4[v_3D], _cosines4[v_3D]) / 4.0;
 
  507   auto itv = 
_sizes.begin();
 
  508   for(; itv != 
_sizes.end(); ++itv) {
 
  524     itv->second = std::min(lc, itv->second);
 
  531   std::set<MEdge, MEdgeLessThan> 
edges;
 
  532   for(std::size_t i = 0; i < 
_triangles.size(); i++) {
 
  533     for(
int j = 0; j < 
_triangles[i]->getNumEdges(); j++) {
 
  537   const double _beta = 1.3;
 
  538   for(
int i = 0; i < 3; i++) {
 
  539     auto it = 
edges.begin();
 
  540     for(; it != 
edges.end(); ++it) {
 
  541       MVertex *v0 = it->getVertex(0);
 
  542       MVertex *v1 = it->getVertex(1);
 
  545       auto s0 = 
_sizes.find(V0);
 
  546       auto s1 = 
_sizes.find(V1);
 
  554       if(s0->second < s1->second)
 
  555         s1->second = std::min(s1->second, _beta * s0->second);
 
  557         s0->second = std::min(s0->second, _beta * s1->second);
 
  574   double uv[3] = {u, v, w};
 
  578 #if defined(HAVE_ANN) 
  579     if(uv_kdtree->nPoints() < 2) 
return -1000.;
 
  580     double pt[3] = {u, v, 0.0};
 
  581 #pragma omp critical // just to avoid crash (still incorrect) - should use nanoflann 
  582     uv_kdtree->annkSearch(pt, 2, index, dist);
 
  583     SPoint3 p1(nodes[index[0]][0], nodes[index[0]][1], nodes[index[0]][2]);
 
  584     SPoint3 p2(nodes[index[1]][0], nodes[index[1]][1], nodes[index[1]][2]);
 
  591       Msg::Error(
"BGM octree: cannot find UVW=%g %g %g", u, v, w);
 
  599   return itv1->second * (1 - uv2[0] - uv2[1]) + itv2->second * uv2[0] +
 
  600          itv3->second * uv2[1];
 
  608 #if defined(HAVE_ANN) 
  610     if(angle_kdtree->nPoints() >= NBANN) {
 
  611       double pt[3] = {u, v, 0.0};
 
  612 #pragma omp critical // just to avoid crash (still incorrect) - should use nanoflann 
  613       angle_kdtree->annkSearch(pt, NBANN, index, dist);
 
  614       double SINE = 0.0, COSINE = 0.0;
 
  615       for(
int i = 0; i < NBANN; i++) {
 
  616         SINE += _sin[index[i]];
 
  617         COSINE += _cos[index[i]];
 
  619       angle = atan2(SINE, COSINE) / 4.0;
 
  636   double uv[3] = {u, v, w};
 
  640 #if defined(HAVE_ANN) 
  641     if(uv_kdtree->nPoints() < 2) 
return -1000.0;
 
  642     double pt[3] = {u, v, 0.0};
 
  643 #pragma omp critical // just to avoid crash (still incorrect) - should use nanoflann 
  644     uv_kdtree->annkSearch(pt, 2, index, dist);
 
  645     SPoint3 p1(nodes[index[0]][0], nodes[index[0]][1], nodes[index[0]][2]);
 
  646     SPoint3 p2(nodes[index[1]][0], nodes[index[1]][1], nodes[index[1]][2]);
 
  653       Msg::Error(
"BGM octree angle: cannot find UVW=%g %g %g", u, v, w);
 
  662   double cos4 = cos(4 * itv1->second) * (1 - uv2[0] - uv2[1]) +
 
  663                 cos(4 * itv2->second) * uv2[0] + cos(4 * itv3->second) * uv2[1];
 
  664   double sin4 = sin(4 * itv1->second) * (1 - uv2[0] - uv2[1]) +
 
  665                 sin(4 * itv2->second) * uv2[0] + sin(4 * itv3->second) * uv2[1];
 
  666   double angle = atan2(sin4, cos4) / 4.0;
 
  673                            const std::map<MVertex *, double> &_whatToPrint,
 
  676   FILE *
f = 
Fopen(filename.c_str(), 
"w");
 
  678     Msg::Error(
"Could not open file '%s'", filename.c_str());
 
  681   fprintf(
f, 
"View \"Background Mesh\"{\n");
 
  683     for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
 
  688       fprintf(
f, 
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n", v1->
x(),
 
  689               v1->
y(), v1->
z(), v2->
x(), v2->
y(), v2->
z(), v3->
x(), v3->
y(),
 
  694     for(std::size_t i = 0; i < 
_triangles.size(); i++) {
 
  698       auto itv1 = _whatToPrint.find(v1);
 
  699       auto itv2 = _whatToPrint.find(v2);
 
  700       auto itv3 = _whatToPrint.find(v3);
 
  702         fprintf(
f, 
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n", v1->
x(),
 
  703                 v1->
y(), v1->
z(), v2->
x(), v2->
y(), v2->
z(), v3->
x(), v3->
y(),
 
  704                 v3->
z(), itv1->second, itv2->second, itv3->second);
 
  710         fprintf(
f, 
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n", p1.
x(),
 
  711                 p1.
y(), p1.
z(), p2.
x(), p2.
y(), p2.
z(), p3.
x(), p3.
y(), p3.
z(),
 
  712                 itv1->second, itv2->second, itv3->second);
 
  724     Msg::Debug(
"Rebuilding BackgroundMesh element octree");
 
  753   Msg::Debug(
"GlobalBackgroundMesh destructor call");
 
  765                                              bool overwriteExisting)
 
  767   Msg::Debug(
"GlobalBackgroundMesh: import GModel mesh ...");
 
  771     Msg::Debug(
"- delete existing mesh (for overwrite)");
 
  783   std::unordered_map<MVertex *, MVertex *> old2new;
 
  785   std::set<GVertex *, GEntityPtrLessThan> vertices = 
gm->
getVertices();
 
  788     for(
GVertex *e : gf->embeddedVertices()) vertices.insert(e);
 
  789     for(
GEdge *e : gf->embeddedEdges()) 
edges.insert(e);
 
  795     for(
size_t i = 0; i < gv->mesh_vertices.size(); ++i) {
 
  796       MVertex *v = gv->mesh_vertices[i];
 
  797       auto it = old2new.find(v);
 
  798       if(it == old2new.end()) {
 
  811     for(
size_t i = 0; i < ge->mesh_vertices.size(); ++i) {
 
  812       MVertex *v = ge->mesh_vertices[i];
 
  815       auto it = old2new.find(v);
 
  816       if(it == old2new.end()) {
 
  821     bm.
lines.reserve(ge->lines.size());
 
  822     for(
size_t i = 0; i < ge->lines.size(); ++i) {
 
  826       if(v0 == NULL || v1 == NULL) {
 
  827         Msg::Error(
"GlobalBackgroundMesh: failed to import mesh (1)");
 
  843     for(
size_t i = 0; i < gf->mesh_vertices.size(); ++i) {
 
  844       MVertex *v = gf->mesh_vertices[i];
 
  845       auto it = old2new.find(v);
 
  846       if(it == old2new.end()) {
 
  857     bm.
triangles.reserve(gf->triangles.size() + 2 * gf->quadrangles.size());
 
  859     for(
size_t i = 0; i < gf->triangles.size(); ++i) {
 
  864       if(v0 == NULL || v1 == NULL || v2 == NULL) {
 
  865         Msg::Error(
"GlobalBackgroundMesh: failed to import mesh (2)");
 
  874     if(gf->quadrangles.size() > 0) {
 
  875       for(
size_t i = 0; i < gf->quadrangles.size(); ++i) {
 
  881         if(v0 == NULL || v1 == NULL || v2 == NULL || v3 == NULL) {
 
  882           Msg::Error(
"GlobalBackgroundMesh: failed to import mesh (3)");
 
  893   Msg::Debug(
"- imported: %li vertices, %li lines, %li triangles",
 
  894              old2new.size(), nlines, ntris);