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: Wed, 31 May 2017 03:06:59 -0400 (EDT)

branch: devel-yves
commit 1ed381c887beb1184fd8cf7e5a9aba9d88f312e9
Author: Yves Renard <address@hidden>
Date:   Tue May 30 11:13:50 2017 +0200

    fully working Lagrange first order pyramidal element with specific 
integration method. Still some problems with second order element
---
 doc/sphinx/source/userdoc/appendixA.rst          |  2 +-
 doc/sphinx/source/userdoc/appendixB.rst          |  7 +++-
 interface/src/gf_mesh.cc                         |  2 +-
 interface/tests/matlab/Makefile.am               |  1 +
 interface/tests/matlab/demo_laplacian_pyramid.m  | 48 +++++++++++++++++-------
 interface/tests/python/demo_laplacian_pyramid.py | 11 +++---
 src/bgeot_geometric_trans.cc                     |  2 +-
 src/bgeot_geotrans_inv.cc                        |  2 -
 src/getfem/bgeot_poly.h                          | 13 ++++++-
 src/getfem_fem.cc                                |  2 +-
 src/getfem_integration.cc                        | 32 ++++++++++------
 11 files changed, 82 insertions(+), 40 deletions(-)

diff --git a/doc/sphinx/source/userdoc/appendixA.rst 
b/doc/sphinx/source/userdoc/appendixA.rst
index 3367648..5d3becd 100644
--- a/doc/sphinx/source/userdoc/appendixA.rst
+++ b/doc/sphinx/source/userdoc/appendixA.rst
@@ -1332,7 +1332,7 @@ Lagrange elements on 3D pyramid
      - Degree 2 pyramidal element with 14 dof
 
 
-The associated geometric transformations are ``"GT_PYRAMID(K)"`` for K = 1 or 
2.
+The associated geometric transformations are ``"GT_PYRAMID(K)"`` for K = 1 or 
2. The associated integration methods ``"IM_PYRAMID(im)"`` where ``im`` is an 
integration method on a hexahedron (or alternatively 
``"IM_PYRAMID_COMPOSITE(im)"`` where ``im`` is an integration method on a 
tetrahedron, but it is theoretically less accurate)
 The shape functions are not polynomial ones but rational fractions. For the 
first degree :
 
 .. math::
diff --git a/doc/sphinx/source/userdoc/appendixB.rst 
b/doc/sphinx/source/userdoc/appendixB.rst
index 2e81cf3..27fbd5a 100644
--- a/doc/sphinx/source/userdoc/appendixB.rst
+++ b/doc/sphinx/source/userdoc/appendixB.rst
@@ -668,6 +668,11 @@ For instance ``"IM_GAUSS_PARALLELEPIPED(2,k)"`` is an 
alias for
 ``"IM_PRODUCT(IM_GAUSS1D(2,k),IM_GAUSS1D(2,k))"`` and can be use instead of the
 ``"IM_QUAD"`` integrations.
 
+Specific integration methods
+----------------------------
+
+For pyramidal elements, ``"IM_PYRAMID(im)"`` provides an integration method 
corresponding to the transformation of an integration ``im`` from a hexahedron 
(for instance ``"IM_GAUSS_PARALLELEPIPED(3,5)"``) onto a pyramid. It is a 
singular integration method specically adapted to rational fraction shape 
functions of the pyramidal elements.
+
 Composite integration methods
 -----------------------------
 
@@ -689,4 +694,4 @@ not defined on the boundary of sub-elements).
 For the HCT element, it is advised to use the ``"IM_HCT_COMPOSITE(im)"`` 
composite
 integration (which split the original triangle into 3 sub-triangles).
 
-For pyramidal elements, ``"IM_PYRAMID_COMPOSITE(im)"`` provide an integration 
method ase on the decomposition of the pyramid into two tetrahedrons.
+For pyramidal elements, ``"IM_PYRAMID_COMPOSITE(im)"`` provides an integration 
method ase on the decomposition of the pyramid into two tetrahedrons (``im`` 
should be an integration method on a tetrahedron). Note that the integraton 
method ``"IM_PYRAMID(im)"`` where ``im`` is an integration method on an 
hexahedron, should be prefered.
diff --git a/interface/src/gf_mesh.cc b/interface/src/gf_mesh.cc
index 6bc076a..52dbb94 100644
--- a/interface/src/gf_mesh.cc
+++ b/interface/src/gf_mesh.cc
@@ -166,7 +166,7 @@ pyramidal_mesh(getfem::mesh *pmesh, getfemint::mexargs_in 
&in) {
     barycenter /= 8.;
     size_type ib = pmesh->add_point(barycenter);
     pmesh->add_pyramid(iipts[0],iipts[1],iipts[2],iipts[3],ib);
-    pmesh->add_pyramid(iipts[4],iipts[6],iipts[5],iipts[7],ib);
+    pmesh->add_pyramid(iipts[7],iipts[6],iipts[5],iipts[4],ib);
     pmesh->add_pyramid(iipts[0],iipts[4],iipts[1],iipts[5],ib);
     pmesh->add_pyramid(iipts[1],iipts[5],iipts[3],iipts[7],ib);
     pmesh->add_pyramid(iipts[3],iipts[7],iipts[2],iipts[6],ib);
diff --git a/interface/tests/matlab/Makefile.am 
b/interface/tests/matlab/Makefile.am
index b1192aa..442c69a 100644
--- a/interface/tests/matlab/Makefile.am
+++ b/interface/tests/matlab/Makefile.am
@@ -44,6 +44,7 @@ EXTRA_DIST=                                           \
        demo_laplacian_DG.m                             \
        demo_Mindlin_Reissner_plate.m                   \
        demo_laplacian.m                                \
+       demo_laplacian_pyramid.m                        \
        demo_periodic_laplacian.m                       \
        demo_nonlinear_elasticity.m                     \
        demo_nonlinear_elasticity_anim.m                \
diff --git a/interface/tests/matlab/demo_laplacian_pyramid.m 
b/interface/tests/matlab/demo_laplacian_pyramid.m
index 1996abf..60e6d25 100644
--- a/interface/tests/matlab/demo_laplacian_pyramid.m
+++ b/interface/tests/matlab/demo_laplacian_pyramid.m
@@ -24,6 +24,7 @@ gamma0 = 0.001;  % Nitsche's method parameter gamma0 (gamma = 
gamma0*h)
 r = 1e8;         % Penalization parameter
 draw = true;
 draw_mesh = false;
+with_pyramids = true;
 
 K = 2;           % Degree of the finite element method
 
@@ -31,16 +32,26 @@ asize =  size(who('automatic_var654'));
 if (asize(1)) draw = false; end;
 
 % trace on;
-NX = 1;
-m = gf_mesh('pyramidal', [0:1/NX:1], [0:1/NX:1], [0:1/NX:1]);
-
+NX = 10;
+if (with_pyramids)
+  m = gf_mesh('pyramidal', [0:1/NX:1], [0:1/NX:1], [0:1/NX:1]);
+else
+  m = gf_mesh('regular simplices', [0:1/NX:1], [0:1/NX:1], [0:1/NX:1]);
+end
 
 % 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))'));
+if (with_pyramids)
+  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))'));
+  mim = gf_mesh_im(m, gf_integ('IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3,5))'));
+  % mim = gf_mesh_im(m, 
gf_integ('IM_PYRAMID_COMPOSITE(IM_STRUCTURED_COMPOSITE(IM_TETRAHEDRON(5),3))'));
+else
+  gf_mesh_fem_set(mf,'fem',gf_fem(sprintf('FEM_PK(3,%d)', K)));
+  mim = gf_mesh_im(m, gf_integ('IM_TETRAHEDRON(5)'));
+end
 
 
 % Detect the border of the mesh
@@ -56,12 +67,12 @@ 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)' });
-% Uexact = gf_mesh_fem_get(mf, 'eval', { 'sin(x).*sin(y).*sin(z)' });
+% Uexact = gf_mesh_fem_get(mf, 'eval', { 'x.*sin(2*pi*x).*sin(2*pi*y)' });
+Uexact = gf_mesh_fem_get(mf, 'eval', { 'sin(pi*x/2).*sin(pi*y/2).*sin(pi*z/2)' 
});
 % 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)' });
-% F = gf_mesh_fem_get(mf, 'eval', { '-3*sin(x).*sin(y).*sin(z)' });
+% F      = gf_mesh_fem_get(mf, 'eval', { '4*pi*(2*pi*x.*sin(2*pi*x) - 
cos(2*pi*x)).*sin(2*pi*y)' });
+F = gf_mesh_fem_get(mf, 'eval', { 
'3*pi*pi*sin(pi*x/2).*sin(pi*y/2).*sin(pi*z/2)/4' });
 
 md=gf_model('real');
 gf_model_set(md, 'add fem variable', 'u', mf);
@@ -103,15 +114,24 @@ K = gf_asm('laplacian', mim, mf, mf, ones(1, 
gf_mesh_fem_get(mf, 'nbdof')));
 if (0) % Drawing the shape functions on the reference element
   m2 = gf_mesh('empty', 3);
   gf_mesh_set(m2, 'add convex', gf_geotrans('GT_PYRAMID(1)'), [-1 -1 0;  1, 
-1, 0; -1,  1, 0;  1,  1, 0;  0,  0, 1]');
+  % gf_mesh_set(m2, 'add convex', gf_geotrans('GT_PYRAMID(1)'), [-1 -1 2;  1, 
-1, 2; -1,  1, 2;  1,  1, 2;  0,  0, 1]');
+  % gf_mesh_set(m2, 'add convex', gf_geotrans('GT_PYRAMID(1)'), [ 1 -1 0; 1,  
1, 0;   1, -1, 2;  1,  1, 2;  0,  0, 1]');
   mf2 = gf_mesh_fem(m2,1);
-  gf_mesh_fem_set(mf2,'fem',gf_fem('FEM_PYRAMID_LAGRANGE(1)'));
+  gf_mesh_fem_set(mf2,'fem',gf_fem('FEM_PYRAMID_LAGRANGE(2)'));
   Utest = zeros(1,gf_mesh_fem_get(mf2, 'nbdof'));
-  gf_mesh_fem_get(mf2, 'basic dof nodes')
+  % gf_mesh_fem_get(mf2, 'basic dof nodes')
+  %mim2 = gf_mesh_im(m2, gf_integ('IM_PYRAMID_COMPOSITE(IM_TETRAHEDRON(5))'));
+  mim2 = gf_mesh_im(m2, gf_integ('IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3,9))'));
+  % mim2 = gf_mesh_im(m2, 
gf_integ('IM_PYRAMID_COMPOSITE(IM_STRUCTURED_COMPOSITE(IM_TETRAHEDRON(5),10))'));
+  format long
+  M2 = gf_asm('mass matrix', mim2, mf2)
+  K2 = gf_asm('laplacian', mim2, mf2, mf2, ones(1, gf_mesh_fem_get(mf2, 
'nbdof')))
+
   for i = 1:size(Utest,2)
     Utest(i) = 1;
     figure(3);
     gf_plot(mf2,Utest,'mesh','on', 'cvlst', gf_mesh_get(m2, 'outer faces'), 
'refine', 8); 
-    colorbar;title('shape function');
+    colorbar; title('shape function');
     pause;
     Utest(i) = 0;
   end
@@ -123,13 +143,13 @@ if (0) % Drawing the shape functions on the whole mesh
     Utest(i) = 1;
     figure(3);
     gf_plot(mf,Utest,'mesh','on', 'cvlst', gf_mesh_get(m, 'outer faces'), 
'refine', 8); 
-    colorbar;title('shape function');
+    colorbar; title('shape function');
     Utest(i) = 0;
     pause;
   end
 end
 
-if (err > 2E-4)
+if (err > 0.033)
    error('Laplacian test: error to big');
 end
 
diff --git a/interface/tests/python/demo_laplacian_pyramid.py 
b/interface/tests/python/demo_laplacian_pyramid.py
index 9423a39..f4e89a6 100644
--- a/interface/tests/python/demo_laplacian_pyramid.py
+++ b/interface/tests/python/demo_laplacian_pyramid.py
@@ -37,7 +37,7 @@ import numpy as np
 export_mesh = True;
 
 ## Parameters
-NX = 2                             # Mesh parameter.
+NX = 10                            # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
                                    # or penalization
 dirichlet_coefficient = 1e10       # Penalization coefficient
@@ -52,8 +52,8 @@ m = gf.Mesh('pyramidal', np.arange(0,1+1./NX,1./NX),
 mfu   = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # assign the Lagrange linear fem to all pyramids of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(1)'))
-mfrhs.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(1)'))
+mfu.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(2)'))
+mfrhs.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(2)'))
 # mfu.set_fem(gf.Fem('FEM_PK(3,1)'))
 # mfrhs.set_fem(gf.Fem('FEM_PK(3,1)'))
 
@@ -64,7 +64,8 @@ if (export_mesh):
 
 
 #  Integration method used
-mim = gf.MeshIm(m, gf.Integ('IM_PYRAMID_COMPOSITE(IM_TETRAHEDRON(5))'))
+# mim = gf.MeshIm(m, gf.Integ('IM_PYRAMID_COMPOSITE(IM_TETRAHEDRON(6))'))
+mim = gf.MeshIm(m, gf.Integ('IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3,3))'))
 # mim = gf.MeshIm(m, gf.Integ('IM_TETRAHEDRON(5)'))
 
 # Boundary selection
@@ -159,6 +160,6 @@ print ('\nYou can view the solution for instance with');
 print ('mayavi2 -d laplacian.vtk -m Surface \n');
 
 
-if (H1error > 1e-2):
+if (H1error > 0.09):
     print 'Error too large !'
     exit(1)
diff --git a/src/bgeot_geometric_trans.cc b/src/bgeot_geometric_trans.cc
index 8ff4835..fdc16f8 100644
--- a/src/bgeot_geometric_trans.cc
+++ b/src/bgeot_geometric_trans.cc
@@ -549,7 +549,7 @@ namespace bgeot {
     }
 
     virtual void poly_vector_hess(const base_node &pt, base_matrix &pc) const {
-      if (!(grad_.size())) compute_grad_();
+      if (!(hess_.size())) compute_hess_();
       FUNC PP, QP;
       pc.base_resize(nb_points(),dim()*dim());
       for (size_type i = 0; i < nb_points(); ++i)
diff --git a/src/bgeot_geotrans_inv.cc b/src/bgeot_geotrans_inv.cc
index 4d59b64..67dacd5 100644
--- a/src/bgeot_geotrans_inv.cc
+++ b/src/bgeot_geotrans_inv.cc
@@ -108,7 +108,6 @@ namespace bgeot
 
     //    for (size_type j = 0; j < pgt->nb_points(); ++j) 
     //       cout << "point " << j << " : " << cvpts[j] << endl;
-
     converged = true;
     base_node xn(P), y, z,x0;
     /* find an initial guess */
@@ -123,7 +122,6 @@ namespace bgeot
 
     base_node vres(P);
     base_node rn(xreal); rn -= y; 
-
     pgt->poly_vector_grad(x, pc);
     update_B();
     
diff --git a/src/getfem/bgeot_poly.h b/src/getfem/bgeot_poly.h
index c441448..53a7deb 100644
--- a/src/getfem/bgeot_poly.h
+++ b/src/getfem/bgeot_poly.h
@@ -713,8 +713,17 @@ namespace bgeot
     void one() { numerator_.one(); denominator_.one(); }
     void clear() { numerator_.clear(); denominator_.one(); }
     template <typename ITER> T eval(const ITER &it) const {
-      T a = numerator_.eval(it);
-      if (a != T(0)) a /= denominator_.eval(it);
+      typedef typename gmm::number_traits<T>::magnitude_type R;
+      T a = numerator_.eval(it), b = denominator_.eval(it);
+      if (b == T(0)) { // The better should be to evaluate the derivatives ...
+       std::vector<T> p(it, it+dim()), q(dim(), T(1));
+       R no = gmm::vect_norm2(p);
+       if (no == R(0)) no = R(1E-35); else no*=gmm::default_tol(R())*R(100000);
+       gmm::add(gmm::scaled(q, T(no)), p);
+       a = numerator_.eval(p.begin());
+       b = denominator_.eval(p.begin());
+      }
+      if (a != T(0)) a /= b;
       return a;
     }
     /// Constructor.
diff --git a/src/getfem_fem.cc b/src/getfem_fem.cc
index ecc9a80..734f777 100644
--- a/src/getfem_fem.cc
+++ b/src/getfem_fem.cc
@@ -1347,7 +1347,7 @@ namespace getfem {
       GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
       k = dim_type(::floor(params[0].num() + 0.01));
     }
-    pfem p = build_pyramidal_pk_fem(k, false);
+    pfem p = build_pyramidal_pk_fem(k, true);
     dependencies.push_back(p->ref_convex(0));
     dependencies.push_back(p->node_tab(0));
     return p;
diff --git a/src/getfem_integration.cc b/src/getfem_integration.cc
index 3ee290b..047fc3f 100644
--- a/src/getfem_integration.cc
+++ b/src/getfem_integration.cc
@@ -913,9 +913,6 @@ namespace getfem {
          other_nodes.pop_back();
        }
 
-      cout << "nodes1 = " << vref(nodes1) << endl;
-      cout << "nodes2 = " << vref(nodes2) << endl;
-
       base_matrix G1, G2, G3; 
       base_matrix K(N, N), grad(N, N), K3(N, N), K4(N, N);
       base_node normal1(N), normal2(N);
@@ -936,7 +933,6 @@ namespace getfem {
        }
 
        for (size_type i=0; i <  base_im->nb_points(); ++i) {
-         cout << "proceeding with point " << i << endl;
 
          gmm::copy(gmm::identity_matrix(), K4); J4 = J1 = scalar_type(1);
 
@@ -949,10 +945,8 @@ namespace getfem {
            }
            normal1 =  base_im->ref_convex()->normals()[fp];
          }
-         cout << "face number : " << int(fp) << endl;
 
          base_node P = base_im->point(i);
-         cout << "coords P : " << P << endl;
          if (what == TETRA_CYL) { 
            P = pgt3->transform(P, nodes3);
            scalar_type x = P[0], y = P[1], one_minus_z = 1.0 - P[2];
@@ -972,7 +966,6 @@ namespace getfem {
          }
 
          base_node P1 = pgt1->transform(P, nodes1), P2(N);
-         cout << "coords P1 : " << P1 << endl;
          pgt1->poly_vector_grad(P, grad);
          gmm::mult(gmm::transposed(grad), gmm::transposed(G1), K);
          J1 = gmm::abs(gmm::lu_det(K)) * J3 * J4;
@@ -990,19 +983,14 @@ namespace getfem {
            J1 *= gmm::vect_norm2(normal2);
            normal2 /= gmm::vect_norm2(normal2);
          }
-         cout << "here 1" << endl;
-         
          gic.invert(P1, P2);
-         cout << "coords P2 : " << P2 << endl;
          GMM_ASSERT1(pgt2->convex_ref()->is_in(P2) < 1E-8,
                      "Point not in the convex ref : " << P2);
          
-         cout << "here 2" << endl;
          pgt2->poly_vector_grad(P2, grad);
          gmm::mult(gmm::transposed(grad), gmm::transposed(G2), K);
          J2 = gmm::abs(gmm::lu_det(K)); /* = 1 */
          
-         cout << "here 3" << endl;
          if (i <  base_im->nb_points_on_convex())
            add_point(P2, base_im->coeff(i)*J1/J2, short_type(-1));
          else if (J1 > 1E-10) {
@@ -1059,6 +1047,25 @@ namespace getfem {
     return p;
   }
 
+  static pintegration_method pyramid(im_param_list &params,
+       std::vector<dal::pstatic_stored_object> &dependencies) {
+    GMM_ASSERT1(params.size() == 1 && params[0].type() == 1,
+               "Bad parameters for pyramid integration: the first "
+               "parameter should be an integration method");
+    pintegration_method a = params[0].method();
+    GMM_ASSERT1(a->type()==IM_APPROX,"need an approximate integration method");
+    int N = a->approx_method()->dim();
+    GMM_ASSERT1(N == 3, "Bad parameters");
+
+    papprox_integration
+      pai = std::make_shared<quasi_polar_integration>(a->approx_method(), 0, 
0);
+    pintegration_method p = std::make_shared<integration_method>(pai);
+    dependencies.push_back(p->approx_method()->ref_convex());
+    dependencies.push_back(p->approx_method()->pintegration_points());
+    return p;
+  }
+
+
 
   /* ******************************************************************** */
   /*    Naming system                                                     */
@@ -1088,6 +1095,7 @@ namespace getfem {
       add_suffix("NC_PRISM", Newton_Cotes_prism);
       add_suffix("GAUSS_PARALLELEPIPED", Gauss_paramul);
       add_suffix("QUASI_POLAR", quasi_polar);
+      add_suffix("PYRAMID", pyramid);
       add_suffix("STRUCTURED_COMPOSITE",
                  structured_composite_int_method);
       add_suffix("HCT_COMPOSITE",



reply via email to

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