From 2a81f927ca1c21214e58f481aa3c5cfa5594ca69 Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Fri, 23 Sep 2016 14:18:22 +0000
Subject: [PATCH] When searching reference point from physical point with
 Newton-Raphson: start from the reference coordinate of nearer element node.

---
 Geo/MElement.cpp     | 25 +++++++++++++++++++++++++
 Numeric/nodalBasis.h |  3 +++
 2 files changed, 28 insertions(+)

diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 24cb8009a1..71af67d7f9 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -846,6 +846,31 @@ void MElement::xyz2uvw(double xyz[3], double uvw[3]) const
   // routines are implemented for simplices, where the basis functions
   // are linear)
   uvw[0] = uvw[1] = uvw[2] = 0.;
+
+  // For high order elements, start from the nearer point
+  if (getPolynomialOrder() > 2) {
+    int numNearer = 0;
+    const MVertex *v = getShapeFunctionNode(0);
+    double distNearer = (v->x()-xyz[0])*(v->x()-xyz[0]) +
+                        (v->y()-xyz[1])*(v->y()-xyz[1]) +
+                        (v->z()-xyz[2])*(v->z()-xyz[2]);
+    for (int i = 1; i < getNumShapeFunctions(); i++) {
+      const MVertex *v = getShapeFunctionNode(i);
+      double dist = (v->x()-xyz[0])*(v->x()-xyz[0]) +
+                    (v->y()-xyz[1])*(v->y()-xyz[1]) +
+                    (v->z()-xyz[2])*(v->z()-xyz[2]);
+      if (dist < distNearer) {
+        numNearer = i;
+        distNearer = dist;
+      }
+    }
+    const nodalBasis *nb = getFunctionSpace();
+    fullMatrix<double> refpnts = nb->getReferenceNodes();
+    uvw[0] = refpnts(numNearer, 0);
+    uvw[1] = refpnts(numNearer, 1);
+    uvw[2] = refpnts(numNearer, 2);
+  }
+
   int iter = 1, maxiter = 20;
   double error = 1., tol = 1.e-6;
 
diff --git a/Numeric/nodalBasis.h b/Numeric/nodalBasis.h
index ec61eff8cb..472aed9c16 100644
--- a/Numeric/nodalBasis.h
+++ b/Numeric/nodalBasis.h
@@ -23,6 +23,9 @@ class nodalBasis {
   void getReferenceNodes(fullMatrix<double> &nodes) const {
     nodes = points;
   }
+  const fullMatrix<double>& getReferenceNodes() const {
+    return points;
+  }
   void getReferenceNodesForBezier(fullMatrix<double> &nodes) const;
 
   // Basis functions & gradients evaluation
-- 
GitLab