getfem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Getfem-commits] (no subject)


From: Yves Renard
Subject: [Getfem-commits] (no subject)
Date: Sat, 9 Jun 2018 10:35:10 -0400 (EDT)

branch: master
commit f1fc36b58da6c236edb014d22b41795bd3c32da9
Author: Yves Renard <address@hidden>
Date:   Sat Jun 9 16:34:02 2018 +0200

    Making 'Normal' refering to the unit vector to a level-set when integrating 
on a level-set
---
 doc/sphinx/source/userdoc/gasm_high.rst            |  8 ++--
 .../getfem_generic_assembly_compile_and_exec.h     |  3 +-
 src/getfem/getfem_mesh_im_level_set.h              |  4 ++
 src/getfem_generic_assembly_compile_and_exec.cc    | 53 ++++++++++++++++++----
 src/getfem_global_function.cc                      | 17 ++++---
 src/getfem_mesh_im_level_set.cc                    | 31 +++++++++++++
 6 files changed, 96 insertions(+), 20 deletions(-)

diff --git a/doc/sphinx/source/userdoc/gasm_high.rst 
b/doc/sphinx/source/userdoc/gasm_high.rst
index 7a74a24..717d993 100644
--- a/doc/sphinx/source/userdoc/gasm_high.rst
+++ b/doc/sphinx/source/userdoc/gasm_high.rst
@@ -54,7 +54,7 @@ A specific language has been developed to describe the weak 
formulation of bound
 
   - ``X`` is the current coordinate on the real element, ``X(i)`` is its i-th 
component.
 
-  - ``Normal`` is the outward unit normal vector to a boundary (for 
integration on a domain boundary).
+  - ``Normal`` is the outward unit normal vector to a boundary, when 
integrating on a domain boundary, or the unit normal vector to a level-set when 
integrating on a level-set with a ``mesh_im_level_set`` method. In the latter 
case, the normal vector is in the direction of the level-set function gradient.
 
   - ``Reshape(t, i, j, ...)``: Reshape a vector/matrix/tensor. Note that all 
tensors in |gf| are stored in the Fortran order.
 
@@ -895,7 +895,7 @@ For |gf| 5.1. When using a fem cut by a level-set (using 
fem_level_set or mesh_f
   Xfem_minus(Test_Div_u)
   Xfem_minus(Test_Hess_u)
   
-which are only available when the evaluation (integration) is made on the 
curve/surface separating two zones of continuity, i.e. on the zero level-set of 
a considered level-set function (using a mesh_im_level_set object). For 
instance, a jump in the variable ``u`` will be given by::
+which are only available when the evaluation (integration) is made on the 
curve/surface separating two zones of continuity, i.e. on the zero level-set of 
a considered level-set function (using a ``mesh_im_level_set`` object). For 
instance, a jump in the variable ``u`` will be given by::
 
   Xfem_plus(u)-Xfem_minus(u)
 
@@ -903,7 +903,9 @@ and the average by::
 
   (Xfem_plus(u)+Xfem_minus(u))/2
 
-The value ``Xfem_plus(u)`` is the value of ``u`` on the side where the 
corresponding level-set function is positive and ``Xfem_minus(u)`` the value of 
``u`` on the side where the level-set function is negative.
+  The value ``Xfem_plus(u)`` is the value of ``u`` on the side where the 
corresponding level-set function is positive and ``Xfem_minus(u)`` the value of 
``u`` on the side where the level-set function is negative.
+
+  Additionally, note that, when integrating on a level-set with a 
``mesh_im_level_set`` object, ``Normal`` stands for the normal unit vector to 
the level-set in the direction of the gradient of the level-set function.
   
 Storage of sub-expressions in a getfem::im_data object during assembly
 ----------------------------------------------------------------------
diff --git a/src/getfem/getfem_generic_assembly_compile_and_exec.h 
b/src/getfem/getfem_generic_assembly_compile_and_exec.h
index 0f7766d..3802ca2 100644
--- a/src/getfem/getfem_generic_assembly_compile_and_exec.h
+++ b/src/getfem/getfem_generic_assembly_compile_and_exec.h
@@ -144,6 +144,7 @@ namespace getfem {
     struct region_mim_instructions {
 
       const mesh *m;
+      const mesh_im *im;
       ga_if_hierarchy current_hierarchy;
       std::map<std::string, base_vector> local_dofs;
       std::map<const mesh_fem *, pfem_precomp> pfps;
@@ -176,7 +177,7 @@ namespace getfem {
       ga_instruction_list instructions;
       std::map<scalar_type, std::list<pga_tree_node> > node_list;
 
-      region_mim_instructions(): m(0) {}
+    region_mim_instructions(): m(0), im(0) {}
     };
 
     std::list<ga_tree> trees; // The trees are stored mainly because they
diff --git a/src/getfem/getfem_mesh_im_level_set.h 
b/src/getfem/getfem_mesh_im_level_set.h
index 5ae02ef..623d267 100644
--- a/src/getfem/getfem_mesh_im_level_set.h
+++ b/src/getfem/getfem_mesh_im_level_set.h
@@ -111,6 +111,8 @@ namespace getfem {
       regular_simplex_pim = reg;
       base_singular_pim = sing;
     }
+
+    int location(void) const { return integrate_where; }
     
     size_type memsize() const {
       return mesh_im::memsize(); // + ... ;
@@ -171,6 +173,8 @@ namespace getfem {
     void set_level_set_boolean_operations(const std::string description) {
       ls_csg_description = description;
     }
+    void compute_normal_vector(const fem_interpolation_context &ctx,
+                              base_small_vector &vec) const;
   };
 
 
diff --git a/src/getfem_generic_assembly_compile_and_exec.cc 
b/src/getfem_generic_assembly_compile_and_exec.cc
index 6afb52d..f54d6bd 100644
--- a/src/getfem_generic_assembly_compile_and_exec.cc
+++ b/src/getfem_generic_assembly_compile_and_exec.cc
@@ -19,6 +19,7 @@
 
 ===========================================================================*/
 
+#include "getfem/getfem_mesh_im_level_set.h"
 #include "getfem/getfem_generic_assembly_tree.h"
 #include "getfem/getfem_generic_assembly_semantic.h"
 #include "getfem/getfem_generic_assembly_compile_and_exec.h"
@@ -271,7 +272,7 @@ namespace getfem {
   struct ga_instruction_copy_Normal : public ga_instruction_copy_small_vect {
 
     virtual int exec() {
-      GA_DEBUG_INFO("Instruction: Normal");
+      GA_DEBUG_INFO("Instruction: unit normal vector");
       GMM_ASSERT1(t.size() == vec.size(), "Invalid outward unit normal "
                   "vector. Possible reasons: not on boundary or "
                   "transformation failed.");
@@ -283,6 +284,27 @@ namespace getfem {
       : ga_instruction_copy_small_vect(t_, Normal_)  {}
   };
 
+  struct ga_instruction_level_set_normal_vector : public ga_instruction {
+    base_tensor &t;
+    const mesh_im_level_set *mimls;
+    const fem_interpolation_context &ctx;
+    base_small_vector vec;
+    
+    virtual int exec() {
+      GA_DEBUG_INFO("Instruction: unit normal vector to a level-set");
+      mimls->compute_normal_vector(ctx, vec);
+      GMM_ASSERT1(t.size() == vec.size(), "Invalid outward unit normal "
+                  "vector. Possible reasons: not on boundary or "
+                  "transformation failed.");
+      gmm::copy(vec, t.as_vector());
+      return 0;
+    }
+    ga_instruction_level_set_normal_vector
+    (base_tensor &t_, const mesh_im_level_set *mimls_,
+     const fem_interpolation_context &ctx_)
+      : t(t_), mimls(mimls_), ctx(ctx_), vec(t.size())  {}
+  };
+
   struct ga_instruction_element_size : public ga_instruction {
     base_tensor &t;
     scalar_type &es;
@@ -4932,13 +4954,24 @@ namespace getfem {
       break;
 
     case GA_NODE_NORMAL:
-      GMM_ASSERT1(!function_case,
-                  "No use of Normal is allowed in functions");
-      if (pnode->tensor().size() != m.dim())
-        pnode->init_vector_tensor(m.dim());
-      pgai = std::make_shared<ga_instruction_copy_Normal>
-             (pnode->tensor(), gis.Normal);
-      rmi.instructions.push_back(std::move(pgai));
+      {
+       GMM_ASSERT1(!function_case,
+                   "No use of Normal is allowed in functions");
+       if (pnode->tensor().size() != m.dim())
+         pnode->init_vector_tensor(m.dim());
+       const mesh_im_level_set *mimls
+         = dynamic_cast<const mesh_im_level_set *>(rmi.im);
+       if (mimls && mimls->location()==mesh_im_level_set::INTEGRATE_BOUNDARY) {
+         // Appel avec ctx (pt de Gauss)
+         pgai = std::make_shared<ga_instruction_level_set_normal_vector>
+           (pnode->tensor(), mimls, gis.ctx);
+         rmi.instructions.push_back(std::move(pgai));
+       } else {
+         pgai = std::make_shared<ga_instruction_copy_Normal>
+           (pnode->tensor(), gis.Normal);
+         rmi.instructions.push_back(std::move(pgai));
+       }
+      }
       break;
 
     case GA_NODE_INTERPOLATE_X:
@@ -6349,7 +6382,7 @@ namespace getfem {
           ga_instruction_set::region_mim rm(td.mim, td.rg);
           ga_instruction_set::region_mim_instructions &rmi
             = gis.whole_instructions[rm];
-          rmi.m = td.m;
+          rmi.m = td.m; rmi.im = td.mim;
           // rmi.interpolate_infos.clear();
           ga_compile_interpolate_trans(root, workspace, gis, rmi, *(td.m));
           ga_compile_node(root, workspace, gis,rmi, *(td.m), false,
@@ -6399,7 +6432,7 @@ namespace getfem {
             ga_instruction_set::region_mim rm(td.mim, td.rg);
             ga_instruction_set::region_mim_instructions &rmi
               = gis.whole_instructions[rm];
-            rmi.m = td.m;
+            rmi.m = td.m; rmi.im = td.mim;
             // rmi.interpolate_infos.clear();
             ga_compile_interpolate_trans(root, workspace, gis, rmi, *(td.m));
             ga_compile_node(root, workspace, gis, rmi, *(td.m), false,
diff --git a/src/getfem_global_function.cc b/src/getfem_global_function.cc
index d443a25..fcdda89 100644
--- a/src/getfem_global_function.cc
+++ b/src/getfem_global_function.cc
@@ -31,24 +31,24 @@ namespace getfem {
   scalar_type global_function_simple::val
   (const fem_interpolation_context &c) const {
     base_node pt = c.xreal();
-    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") 
" <<
-                                   "passed to a global function of dim = "<< 
dim_ <<".");
+    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
+               << "passed to a global function of dim = "<< dim_ <<".");
     return this->val(pt);
   }
 
   void global_function_simple::grad
   (const fem_interpolation_context &c, base_small_vector &g) const {
     base_node pt = c.xreal();
-    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") 
" <<
-                                   "passed to a global function of dim = "<< 
dim_ <<".");
+    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
+               << "passed to a global function of dim = "<< dim_ <<".");
     this->grad(pt, g);
   }
 
   void global_function_simple::hess
   (const fem_interpolation_context &c, base_matrix &h) const {
     base_node pt = c.xreal();
-    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") 
" <<
-                                   "passed to a global function of dim = "<< 
dim_ <<".");
+    GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
+               << "passed to a global function of dim = "<< dim_ <<".");
     this->hess(pt, h);
   }
 
@@ -744,6 +744,11 @@ namespace getfem {
       scalar_type y = (*mls_y)(c.xref());
       if (c.xfem_side() > 0 && y <= 0) y = 1E-13;
       if (c.xfem_side() < 0 && y >= 0) y = -1E-13;
+      // if (c.xfem_side()) {
+      //       cout << "point : " << c.xref() << " side : " << c.xfem_side() 
<< endl;
+      //       cout << "side -1 : " << fn->val(x,-1E-13) << " : " << 
fn->val(x,-1E-16) << endl;
+      //       cout << "side  1 : " << fn->val(x, 1E-13) << " : " << 
fn->val(x, 1E-16) << endl;
+      // }
 
       return fn->val(x,y);
     }
diff --git a/src/getfem_mesh_im_level_set.cc b/src/getfem_mesh_im_level_set.cc
index a030c0a..6fd7afd 100644
--- a/src/getfem_mesh_im_level_set.cc
+++ b/src/getfem_mesh_im_level_set.cc
@@ -441,6 +441,35 @@ namespace getfem {
     // cout << "Number of built methods : " << build_methods.size() << endl;
   }
 
+  void mesh_im_level_set::compute_normal_vector
+  (const fem_interpolation_context &ctx, base_small_vector &vec) const {
+    size_type nb_ls = mls->nb_level_sets(), j = 0;
+    std::vector<pmesher_signed_distance> mesherls0(nb_ls);
+    if (vec.size() != linked_mesh().dim()) vec.resize(linked_mesh().dim());
+    base_small_vector un(ctx.pgt()->dim());
+                        
+    if (nb_ls == 0) {
+      gmm::clear(vec); return; 
+    } else if (nb_ls == 1) {
+      mesherls0[0]
+       = mls->get_level_set(0)->mls_of_convex(ctx.convex_num(), 0, false);
+    } else {
+      scalar_type d_min(0);
+      for (unsigned i = 0; i < nb_ls; ++i) {
+       mesherls0[i]
+         = mls->get_level_set(i)->mls_of_convex(ctx.convex_num(), 0, false);
+       scalar_type d = gmm::abs((*(mesherls0[i]))(ctx.xref()));
+       if (i == 0 || d < d_min) { d_min = d; j = i; }
+      }
+    }
+    mesherls0[j]->grad(ctx.xref(), un);
+    gmm::mult(ctx.B(), un, vec);
+    scalar_type no = gmm::vect_norm2(vec);
+    if (no != scalar_type(0))
+      gmm::scale(vec, scalar_type(1) / gmm::vect_norm2(vec));
+  }
+
+
 
   void mesh_im_cross_level_set::update_from_context(void) const
   { is_adapted = false; }
@@ -713,6 +742,8 @@ namespace getfem {
     is_adapted = true; touch();
   }
 
+
+
   
 }  /* end of namespace getfem.                                             */
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]