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: Sun, 28 May 2017 11:22:52 -0400 (EDT)

branch: devel-yves
commit 5a51ad5b1324eee76972234ec3f6b9aa82b2d174
Author: Yves Renard <address@hidden>
Date:   Sun May 28 08:58:33 2017 +0200

    A small optimization for interpolation
---
 interface/src/Makefile.am                       |   1 -
 interface/tests/matlab/demo_laplacian_pyramid.m | 114 ++++++++++++++++++++++++
 interface/tests/python/Makefile.am              |   1 +
 src/bgeot_geometric_trans.cc                    |  56 ++++++++----
 src/getfem/bgeot_poly.h                         |   5 ++
 src/getfem/getfem_fem.h                         |  39 ++++++--
 src/getfem_fem.cc                               |  12 ++-
 7 files changed, 198 insertions(+), 30 deletions(-)

diff --git a/interface/src/Makefile.am b/interface/src/Makefile.am
index bf7dcce..9a858c5 100644
--- a/interface/src/Makefile.am
+++ b/interface/src/Makefile.am
@@ -25,7 +25,6 @@ endif
 
 if BUILDSCILAB
 subdirSCILAB=scilab
-.NOTPARALLEL: scilab
 endif
 
 SUBDIRS = . $(subdirMATLAB) $(subdirPYTHON) $(subdirSCILAB)
diff --git a/interface/tests/matlab/demo_laplacian_pyramid.m 
b/interface/tests/matlab/demo_laplacian_pyramid.m
new file mode 100644
index 0000000..d3a6b9c
--- /dev/null
+++ b/interface/tests/matlab/demo_laplacian_pyramid.m
@@ -0,0 +1,114 @@
+% Copyright (C) 2005-2017 Yves Renard, Julien Pommier.
+%
+% This file is a part of GetFEM++
+%
+% GetFEM++  is  free software;  you  can  redistribute  it  and/or modify it
+% under  the  terms  of the  GNU  Lesser General Public License as published
+% by  the  Free Software Foundation;  either version 3 of the License,  or
+% (at your option) any later version along with the GCC Runtime Library
+% Exception either version 3.1 or (at your option) any later version.
+% This program  is  distributed  in  the  hope  that it will be useful,  but
+% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+% or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+% License and GCC Runtime Library Exception for more details.
+% You  should  have received a copy of the GNU Lesser General Public License
+% along  with  this program;  if not, write to the Free Software Foundation,
+% Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+% Options for prescribing the Dirichlet condition
+dirichlet_version = 1; % 0 = simplification, 1 = with multipliers,
+                       % 2 = penalization,  3 = Nitsche's method
+theta = 1;       % Nitsche's method parameter theta
+gamma0 = 0.001;  % Nitsche's method parameter gamma0 (gamma = gamma0*h)
+r = 1e8;         % Penalization parameter
+draw = true;
+draw_mesh = false;
+
+K = 1;           % Degree of the finite element method
+
+asize =  size(who('automatic_var654'));
+if (asize(1)) draw = false; end;
+
+% trace on;
+gf_workspace('clear all');
+NX = 2;
+m = gf_mesh('pyramidal', [0:1/NX:1], [0:1/NX:1], [0:1/NX:1]);
+
+
+% Create a mesh_fem of for a field of dimension 1 (i.e. a scalar field)
+mf = gf_mesh_fem(m,1);
+% Assign the pyramidal fem to all convexes of the mesh_fem, and define an
+% integration method
+gf_mesh_fem_set(mf,'fem',gf_fem(sprintf('FEM_PYRAMID_LAGRANGE(%d)', K)));
+mim = gf_mesh_im(m, gf_integ('IM_PYRAMID_COMPOSITE(IM_TETRAHEDRON(5))'));
+
+
+% Detect the border of the mesh
+border = gf_mesh_get(m, 'outer faces');
+% Mark it as boundary GAMMAD=1
+GAMMAD=1;
+gf_mesh_set(m, 'region', GAMMAD, border);
+if (draw_mesh)
+  figure(1);
+  gf_plot_mesh(m, 'regions', [GAMMAD], 'convexes', 'on'); % the boundary edges 
appear in red
+  pause(1);
+end
+
+% Interpolate the exact solution
+% Uexact = gf_mesh_fem_get(mf, 'eval', { '10*y.*(y-1).*x.*(x-1)+10*x.^5' });
+Uexact = gf_mesh_fem_get(mf, 'eval', { 'x.*sin(2*pi*x).*sin(2*pi*y)' });
+% Opposite of its laplacian
+% F      = gf_mesh_fem_get(mf, 'eval', { 
'-(20*(x.^2+y.^2)-20*x-20*y+200*x.^3)' });
+F      = gf_mesh_fem_get(mf, 'eval', { '4*pi*(2*pi*x.*sin(2*pi*x) - 
cos(2*pi*x)).*sin(2*pi*y)' });
+
+md=gf_model('real');
+gf_model_set(md, 'add fem variable', 'u', mf);
+gf_model_set(md, 'add linear generic assembly brick', mim, 
'Grad_u.Grad_Test_u');
+% gf_model_set(md, 'add Laplacian brick', mim, 'u');
+gf_model_set(md, 'add initialized fem data', 'VolumicData', mf, F);
+gf_model_set(md, 'add source term brick', mim, 'u', 'VolumicData');
+gf_model_set(md, 'add initialized fem data', 'DirichletData', mf, Uexact);
+switch (dirichlet_version)
+  case 0,
+    gf_model_set(md, 'add Dirichlet condition with simplification', 'u', 
GAMMAD, 'DirichletData');   
+  case 1, 
+    gf_model_set(md, 'add Dirichlet condition with multipliers', mim, 'u', mf, 
GAMMAD, 'DirichletData');
+  case 2,
+    gf_model_set(md, 'add Dirichlet condition with penalization', mim, 'u', r, 
GAMMAD, 'DirichletData');
+  case 3,
+    gf_model_set(md, 'add initialized data', 'gamma0', [gamma0]);
+    expr = gf_model_get(md, 'Neumann term', 'u', GAMMAD);
+    gf_model_set(md, 'add Dirichlet condition with Nitsche method', mim, 'u', 
expr, 'gamma0', GAMMAD, theta, 'DirichletData');
+end
+gf_model_get(md, 'solve');
+U = gf_model_get(md, 'variable', 'u');
+Utest = U*0;
+if (draw)
+  figure(2);
+  subplot(2,1,1); gf_plot(mf,U,'mesh','off', 'cvlst', gf_mesh_get(m, 'outer 
faces'), 'refine', 4); 
+  colorbar; title('computed solution');
+
+  subplot(2,1,2); gf_plot(mf,Uexact,'mesh','on', 'cvlst', gf_mesh_get(m, 
'outer faces'), 'refine', 4); 
+  colorbar;title('exact solution');
+end
+
+if(0)
+  for i = 1:size(U,2)
+    Utest(i) = 1;
+    figure(3);
+    gf_plot(mf,Utest,'mesh','on', 'cvlst', gf_mesh_get(m, 'outer faces'), 
'refine', 8); 
+    colorbar;title('shape function');
+    Utest(i) = 0;
+    pause;
+  end
+end
+
+err = gf_compute(mf, Uexact-U, 'H1 norm', mim);
+
+disp(sprintf('H1 norm of error: %g', err));
+
+if (err > 2E-4)
+   error('Laplacian test: error to big');
+end
+
+
diff --git a/interface/tests/python/Makefile.am 
b/interface/tests/python/Makefile.am
index 6caa3c8..f80d0a9 100644
--- a/interface/tests/python/Makefile.am
+++ b/interface/tests/python/Makefile.am
@@ -22,6 +22,7 @@ EXTRA_DIST=                                           \
        demo_crack.py                                   \
        demo_fictitious_domains.py                      \
        demo_laplacian.py                               \
+       demo_laplacian_pyramid.py                       \
        demo_laplacian_DG.py                            \
        demo_laplacian_aposteriori.py                   \
        demo_mortar.py                                  \
diff --git a/src/bgeot_geometric_trans.cc b/src/bgeot_geometric_trans.cc
index 7f1379d..8ff4835 100644
--- a/src/bgeot_geometric_trans.cc
+++ b/src/bgeot_geometric_trans.cc
@@ -483,14 +483,43 @@ namespace bgeot {
   struct igeometric_trans : public geometric_trans {
 
     std::vector<FUNC> trans;
+    mutable std::vector<std::vector<FUNC>> grad_, hess_;
+
+    void compute_grad_() const {
+      size_type R = trans.size();
+      dim_type n = dim();
+      grad_.resize(R);
+      for (size_type i = 0; i < R; ++i) {
+       grad_[i].resize(n);
+       for (dim_type j = 0; j < n; ++j) {
+         grad_[i][j] = trans[i]; grad_[i][j].derivative(j);
+       }
+      }
+    }
 
+    void compute_hess_() const {
+      size_type R = trans.size();
+      dim_type n = dim();
+      hess_.resize(R);
+      for (size_type i = 0; i < R; ++i) {
+       hess_[i].resize(n*n);
+       for (dim_type j = 0; j < n; ++j) {
+         for (dim_type k = 0; k < n; ++k) {
+           hess_[i][j+k*n] = trans[i];
+           hess_[i][j+k*n].derivative(j); hess_[i][j+k*n].derivative(k);
+         }
+       }
+      }
+    }
+    
     virtual void poly_vector_val(const base_node &pt, base_vector &val) const {
       val.resize(nb_points());
       for (size_type k = 0; k < nb_points(); ++k)
         val[k] = to_scalar(trans[k].eval(pt.begin()));
     }
 
-    virtual void poly_vector_val(const base_node &pt, const convex_ind_ct 
&ind_ct,
+    virtual void poly_vector_val(const base_node &pt,
+                                const convex_ind_ct &ind_ct,
                                  base_vector &val) const {
       size_type nb_funcs=ind_ct.size();
       val.resize(nb_funcs);
@@ -499,40 +528,35 @@ namespace bgeot {
     }
 
     virtual void poly_vector_grad(const base_node &pt, base_matrix &pc) const {
+      if (!(grad_.size())) compute_grad_();
       FUNC PP;
       pc.base_resize(nb_points(),dim());
       for (size_type i = 0; i < nb_points(); ++i)
-        for (dim_type n = 0; n < dim(); ++n) {
-          PP = trans[i];
-          PP.derivative(n);
-          pc(i, n) = to_scalar(PP.eval(pt.begin()));
-        }
+        for (dim_type n = 0; n < dim(); ++n)
+          pc(i, n) = to_scalar(grad_[i][n].eval(pt.begin()));
     }
 
     virtual void poly_vector_grad(const base_node &pt,
                                  const convex_ind_ct &ind_ct,
                                   base_matrix &pc) const {
+      if (!(grad_.size())) compute_grad_();
       FUNC PP;
       size_type nb_funcs=ind_ct.size();
       pc.base_resize(nb_funcs,dim());
       for (size_type i = 0; i < nb_funcs; ++i)
-        for (dim_type n = 0; n < dim(); ++n) {
-          PP = trans[ind_ct[i]];
-          PP.derivative(n);
-          pc(i, n) = to_scalar(PP.eval(pt.begin()));
-        }
+        for (dim_type n = 0; n < dim(); ++n)
+          pc(i, n) = to_scalar(grad_[ind_ct[i]][n].eval(pt.begin()));
     }
 
     virtual void poly_vector_hess(const base_node &pt, base_matrix &pc) const {
+      if (!(grad_.size())) compute_grad_();
       FUNC PP, QP;
       pc.base_resize(nb_points(),dim()*dim());
       for (size_type i = 0; i < nb_points(); ++i)
         for (dim_type n = 0; n < dim(); ++n) {
-          QP = trans[i]; QP.derivative(n);
-          for (dim_type m = 0; m <= n; ++m) {
-            PP = QP; PP.derivative(m);
-            pc(i, n*dim()+m) = pc(i, m*dim()+n) = 
to_scalar(PP.eval(pt.begin()));
-          }
+          for (dim_type m = 0; m <= n; ++m)
+            pc(i, n*dim()+m) = pc(i, m*dim()+n) =
+             to_scalar(hess_[i][m*dim()+n].eval(pt.begin()));
         }
     }
 
diff --git a/src/getfem/bgeot_poly.h b/src/getfem/bgeot_poly.h
index 1f8112f..3c4275c 100644
--- a/src/getfem/bgeot_poly.h
+++ b/src/getfem/bgeot_poly.h
@@ -749,6 +749,11 @@ namespace bgeot
     return R;
   }
   
+  template<typename T>  std::ostream &operator <<
+  (std::ostream &o, const rational_fraction<T>& P) {
+    o << "[" << P.numerator() << "]/[" << P.denominator() << "]";
+    return o;
+  }
 
   typedef rational_fraction<opt_long_scalar_type> base_rational_fraction;
 
diff --git a/src/getfem/getfem_fem.h b/src/getfem/getfem_fem.h
index 115b10f..56721a7 100644
--- a/src/getfem/getfem_fem.h
+++ b/src/getfem/getfem_fem.h
@@ -485,7 +485,35 @@ namespace getfem {
   template <class FUNC> class fem : public virtual_fem {
   protected :
     std::vector<FUNC> base_;
+    mutable std::vector<std::vector<FUNC>> grad_, hess_;
 
+    void compute_grad_() const {
+      size_type R = nb_base_components(0);
+      dim_type n = dim();
+      grad_.resize(R);
+      for (size_type i = 0; i < R; ++i) {
+       grad_[i].resize(n);
+       for (dim_type j = 0; j < n; ++j) {
+         grad_[i][j] = base_[i]; grad_[i][j].derivative(j);
+       }
+      }
+    }
+
+    void compute_hess_() const {
+      size_type R = nb_base_components(0);
+      dim_type n = dim();
+      hess_.resize(R);
+      for (size_type i = 0; i < R; ++i) {
+       hess_[i].resize(n*n);
+       for (dim_type j = 0; j < n; ++j) {
+         for (dim_type k = 0; k < n; ++k) {
+           hess_[i][j+k*n] = base_[i];
+           hess_[i][j+k*n].derivative(j); hess_[i][j+k*n].derivative(k);
+         }
+       }
+      }
+    }
+    
   public :
 
     /// Gives the array of basic functions (components).
@@ -506,6 +534,7 @@ namespace getfem {
         reference element directions 0,..,dim-1 and returns the result in
         t(nb_base,target_dim,dim) */
     void grad_base_value(const base_node &x, base_tensor &t) const {
+      if (!(grad_.size())) compute_grad_();
       bgeot::multi_index mi(3);
       dim_type n = dim();
       mi[2] = n; mi[1] = target_dim(); mi[0] = short_type(nb_base(0));
@@ -514,12 +543,13 @@ namespace getfem {
       base_tensor::iterator it = t.begin();
       for (dim_type j = 0; j < n; ++j)
         for (size_type i = 0; i < R; ++i, ++it)
-          { FUNC f = base_[i]; f.derivative(j); *it = 
bgeot::to_scalar(f.eval(x.begin())); }
+         *it = bgeot::to_scalar(grad_[i][j].eval(x.begin()));
     }
     /** Evaluates at point x, the hessian of all base functions w.r.t. the
         reference element directions 0,..,dim-1 and returns the result in
         t(nb_base,target_dim,dim,dim) */
     void hess_base_value(const base_node &x, base_tensor &t) const {
+      if (!(hess_.size())) compute_hess_();
       bgeot::multi_index mi(4);
       dim_type n = dim();
       mi[3] = n; mi[2] = n; mi[1] = target_dim();
@@ -529,11 +559,8 @@ namespace getfem {
       base_tensor::iterator it = t.begin();
       for (dim_type k = 0; k < n; ++k)
         for (dim_type j = 0; j < n; ++j)
-          for (size_type i = 0; i < R; ++i, ++it) {
-            FUNC f = base_[i];
-            f.derivative(j); f.derivative(k);
-            *it = bgeot::to_scalar(f.eval(x.begin()));
-          }
+          for (size_type i = 0; i < R; ++i, ++it)
+           *it = bgeot::to_scalar(hess_[i][j+k*n].eval(x.begin()));
     }
 
   };
diff --git a/src/getfem_fem.cc b/src/getfem_fem.cc
index efcc1c2..888cf7b 100644
--- a/src/getfem_fem.cc
+++ b/src/getfem_fem.cc
@@ -1280,11 +1280,11 @@ namespace getfem {
     } else if (k == 2) {
       p->base().resize(14);
 
-      base_poly xi0 = bgeot::read_base_poly(3, "(1-z-x)*0.5");
-      base_poly xi1 = bgeot::read_base_poly(3, "(1-z-y)*0.5");
-      base_poly xi2 = bgeot::read_base_poly(3, "(1-z+x)*0.5");
-      base_poly xi3 = bgeot::read_base_poly(3, "(1-z+y)*0.5");
-      base_poly z = bgeot::read_base_poly(3, "z");
+      base_poly xi0  = bgeot::read_base_poly(3, "(1-z-x)*0.5");
+      base_poly xi1  = bgeot::read_base_poly(3, "(1-z-y)*0.5");
+      base_poly xi2  = bgeot::read_base_poly(3, "(1-z+x)*0.5");
+      base_poly xi3  = bgeot::read_base_poly(3, "(1-z+y)*0.5");
+      base_poly z    = bgeot::read_base_poly(3, "z");
       base_poly un_z = bgeot::read_base_poly(3, "1-z");
       bgeot::base_rational_fraction Q(bgeot::read_base_poly(3, "1"), un_z);
       
@@ -1318,8 +1318,6 @@ namespace getfem {
       p->add_node(lag_dof, base_small_vector( 0.5,  0.5, 0.5));
       p->add_node(lag_dof, base_small_vector( 0.0,  0.0, 1.0));
 
-      GMM_ASSERT1(false, "to be completed");
-
     } else GMM_ASSERT1(false, "Sorry, pyramidal Lagrange fem "
                       "implemented only for degree 0, 1 or 2");
     



reply via email to

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