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: Tue, 27 Aug 2019 14:37:03 -0400 (EDT)

branch: master
commit 9edbf0bf58b7ab3329d701c46fc85fefa72368e9
Author: Yves Renard <address@hidden>
Date:   Wed Aug 14 18:12:40 2019 +0200

    adding the possibility to define some hybrid fems
---
 .gitignore                         |   2 +
 src/bgeot_geometric_trans.cc       |  57 ++++++++++++-
 src/bgeot_poly_composite.cc        |  11 +--
 src/getfem/bgeot_geometric_trans.h |   2 +
 src/getfem/bgeot_poly_composite.h  |  67 ++++++++-------
 src/getfem_fem.cc                  | 163 +++++++++++++++++++++++++++++++++++--
 src/getfem_fem_composite.cc        | 162 ++++++++++++++++++++++++++++++++++--
 7 files changed, 412 insertions(+), 52 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7349f73..b7a5bfb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,8 @@ Makefile
 /depcomp
 /install-sh
 /interface/tests/matlab/check_all.sh.trs
+interface/tests/python/results/
+interface/tests/python/results1/
 /ltmain.sh
 /m4/libtool.m4
 /m4/ltoptions.m4
diff --git a/src/bgeot_geometric_trans.cc b/src/bgeot_geometric_trans.cc
index 97a127b..b33a92d 100644
--- a/src/bgeot_geometric_trans.cc
+++ b/src/bgeot_geometric_trans.cc
@@ -1,6 +1,6 @@
 /*===========================================================================
 
- Copyright (C) 2000-2017 Yves Renard
+ Copyright (C) 2000-2019 Yves Renard
 
  This file is a part of GetFEM++
 
@@ -1273,6 +1273,61 @@ namespace bgeot {
     return pgt;
   }
 
+
+  // To be completed
+  pgeometric_trans default_trans_of_cvs(pconvex_structure cvs) {
+
+    dim_type n = cvs->dim();
+    short_type nbf  = cvs->nb_faces();
+    short_type nbpt  = cvs->nb_points();
+
+    // Basic cases
+    if (cvs == simplex_structure(n)) return simplex_geotrans(n, 1);
+    if (cvs == parallelepiped_structure(n))
+      return parallelepiped_geotrans(n, 1);
+    if (cvs == prism_P1_structure(n)) return prism_geotrans(n, 1);
+    
+    // more elaborated ones
+    switch (n) {
+    case 1 : return simplex_geotrans(1, short_type(nbpt-1));
+    case 2 :
+      if (nbf == 3) {
+        short_type k = short_type(round((sqrt(1.+8.*nbpt) - 3. ) / 2.));
+        if (cvs == simplex_structure(2,k)) return simplex_geotrans(2, k);
+      } else if (nbf == 4) {
+        short_type k = short_type(round(sqrt(1.*nbpt)) - 1.);
+        if (cvs == parallelepiped_structure(2, k))
+          return parallelepiped_geotrans(2, k);
+      }
+      break;
+    case 3 :
+      if (nbf == 4) {
+        if (cvs == simplex_structure(3, 2)) return simplex_geotrans(3, 2);
+        if (cvs == simplex_structure(3, 3)) return simplex_geotrans(3, 3);
+        if (cvs == simplex_structure(3, 4)) return simplex_geotrans(3, 4);
+        if (cvs == simplex_structure(3, 5)) return simplex_geotrans(3, 5);
+        if (cvs == simplex_structure(3, 6)) return simplex_geotrans(3, 6);
+      } else if (nbf == 6) {
+        short_type k = short_type(round(pow(1.*nbpt, 1./3.)) - 1.);
+        if (cvs == parallelepiped_structure(3, k))
+          return parallelepiped_geotrans(3, k);
+      } else if (nbf == 5) {
+        if (cvs == pyramid_QK_structure(1)) return pyramid_QK_geotrans(1);
+        if (cvs == pyramid_QK_structure(2)) return pyramid_QK_geotrans(2);
+        if (cvs == pyramid_QK_structure(3)) return pyramid_QK_geotrans(3);
+        if (cvs == pyramid_QK_structure(4)) return pyramid_QK_geotrans(4);
+        if (cvs == pyramid_QK_structure(5)) return pyramid_QK_geotrans(5);
+        if (cvs == pyramid_QK_structure(6)) return pyramid_QK_geotrans(6);
+        if (cvs == pyramid_Q2_incomplete_structure())
+          return pyramid_Q2_incomplete_geotrans();
+      }
+      break;
+    }
+    GMM_ASSERT1(false, "Unrecognized structure");
+  }
+
+  
+
   /* ********************************************************************* */
   /*       Precomputation on geometric transformations.                    */
   /* ********************************************************************* */
diff --git a/src/bgeot_poly_composite.cc b/src/bgeot_poly_composite.cc
index 46ade21..e37b33c 100644
--- a/src/bgeot_poly_composite.cc
+++ b/src/bgeot_poly_composite.cc
@@ -1,6 +1,6 @@
 /*===========================================================================
 
- Copyright (C) 2002-2017 Yves Renard
+ Copyright (C) 2002-2019 Yves Renard
 
  This file is a part of GetFEM++
 
@@ -72,7 +72,7 @@ namespace bgeot {
     orgs.resize(m.nb_convex());
     gtrans.resize(m.nb_convex());
     for (size_type i = 0; i <= m.points().index().last_true(); ++i) {
-      vertexes.add(m.points()[i]);
+      vertices.add(m.points()[i]);
     }
 
     base_node min, max;
@@ -107,9 +107,10 @@ namespace bgeot {
 
   DAL_TRIPLE_KEY(base_poly_key, short_type, short_type, 
std::vector<opt_long_scalar_type>);
 
-  polynomial_composite::polynomial_composite(
-    const mesh_precomposite &m, bool lc)
-    : mp(&m), local_coordinate(lc), default_poly(mp->dim(), 0) {}
+  polynomial_composite::polynomial_composite(const mesh_precomposite &m,
+                                             bool lc, bool ff)
+    : mp(&m), local_coordinate(lc), faces_first(ff),
+      default_poly(mp->dim(), 0) {}
 
   void polynomial_composite::derivative(short_type k) {
     if (local_coordinate) {
diff --git a/src/getfem/bgeot_geometric_trans.h 
b/src/getfem/bgeot_geometric_trans.h
index 0c10fba..c27eb5c 100644
--- a/src/getfem/bgeot_geometric_trans.h
+++ b/src/getfem/bgeot_geometric_trans.h
@@ -230,6 +230,8 @@ namespace bgeot {
   pyramid_geotrans(short_type k) { return pyramid_QK_geotrans(k); }
   pgeometric_trans APIDECL pyramid_Q2_incomplete_geotrans();
 
+  pgeometric_trans APIDECL default_trans_of_cvs(pconvex_structure);
+
   /**
      Get the geometric transformation from its string name.
      @see name_of_geometric_trans
diff --git a/src/getfem/bgeot_poly_composite.h 
b/src/getfem/bgeot_poly_composite.h
index c86bd4f..e704282 100644
--- a/src/getfem/bgeot_poly_composite.h
+++ b/src/getfem/bgeot_poly_composite.h
@@ -1,7 +1,7 @@
 /* -*- c++ -*- (enables emacs c++ mode) */
 /*===========================================================================
 
- Copyright (C) 2002-2017 Yves Renard
+ Copyright (C) 2002-2019 Yves Renard
 
  This file is a part of GetFEM++
 
@@ -74,7 +74,7 @@ namespace bgeot {
     typedef dal::dynamic_tree_sorted<base_node, imbricated_box_less> PTAB;
 
     const basic_mesh *msh;
-    PTAB vertexes;
+    PTAB vertices;
     rtree box_tree;
     std::map<size_type, std::vector<size_type>> box_to_convexes_map;
     std::vector<base_matrix> gtrans;
@@ -99,20 +99,25 @@ namespace bgeot {
   protected :
     const mesh_precomposite *mp;
     std::map<size_type, dal::pstatic_stored_object_key> polytab;
-    bool local_coordinate;  // are the polynomials described on the local
-                            // coordinates of each sub-element or on global 
coordinates.
+    bool local_coordinate;  // Local coordinates on each sub-element for
+                            // polynomials or global coordinates ?
+    bool faces_first; // If true try to evaluate on faces before on the
+                      // interior, usefull for HHO elements.
     base_poly default_poly;
 
   public :
 
-    template <class ITER> scalar_type eval(const ITER &it, size_type l = -1) 
const;
+    template <class ITER> scalar_type eval(const ITER &it,
+                                           size_type l = -1) const;
     void derivative(short_type k);
     void set_poly_of_subelt(size_type l, const base_poly &poly);
     const base_poly &poly_of_subelt(size_type l) const;
     size_type nb_subelt() const { return polytab.size(); }
 
-    polynomial_composite(bool lc = true) : local_coordinate(lc) {}
-    polynomial_composite(const mesh_precomposite &m, bool lc = true);
+    polynomial_composite(bool lc = true, bool ff = false)
+      : local_coordinate(lc), faces_first(ff) {}
+    polynomial_composite(const mesh_precomposite &m, bool lc = true,
+                         bool ff = false);
 
   };
 
@@ -132,7 +137,8 @@ namespace bgeot {
     for (dim_type d = 0; d < p2.size(); ++d) {
       p2[d] = 0;
       auto col = mat_col(M, d);
-      for (dim_type i = 0; i < p1.size(); ++i) p2[d] += col[i] * (*(it + i) - 
p1[i]);
+      for (dim_type i = 0; i < p1.size(); ++i)
+        p2[d] += col[i] * (*(it + i) - p1[i]);
     }
   }
 
@@ -148,50 +154,51 @@ namespace bgeot {
     }
 
     auto dim = mp->dim();
-    base_node p0(dim);
+    base_node p0(dim), p0_stored;
+    size_type cv_stored(-1);
     std::copy(it, it + mp->dim(), p0.begin());
 
     auto &box_tree = mp->box_tree;
     rtree::pbox_set box_list;
     box_tree.find_boxes_at_point(p0, box_list);
-    while (box_list.size())
-    {
+    
+    while (box_list.size()) {
       auto pmax_box = *box_list.begin();
-
-      if (box_list.size() > 1)
-      {
+      
+      if (box_list.size() > 1) {
         auto max_rate = -1.0;
-        for (auto &&pbox : box_list)
-        {
+        for (auto &&pbox : box_list) {
           auto box_rate = 1.0;
-          for (size_type i = 0; i < dim; ++i)
-          {
+          for (size_type i = 0; i < dim; ++i) {
             auto h = pbox->max->at(i) - pbox->min->at(i);
-            if (h > 0)
-            {
-              auto rate = std::min(pbox->max->at(i) - p0[i], p0[i] - 
pbox->min->at(i)) / h;
+            if (h > 0) {
+              auto rate = std::min(pbox->max->at(i) - p0[i],
+                                   p0[i] - pbox->min->at(i)) / h;
               box_rate = std::min(rate, box_rate);
             }
           }
-          if (box_rate > max_rate)
-          {
-            pmax_box = pbox;
-            max_rate = box_rate;
-          }
+          if (box_rate > max_rate) { pmax_box = pbox; max_rate = box_rate; }
         }
       }
-
+      
       for (auto cv : mp->box_to_convexes_map.at(pmax_box->id)) {
         mult_diff_transposed(mp->gtrans[cv], it, mp->orgs[cv], p0);
         if (mp->trans_of_convex(cv)->convex_ref()->is_in(p0) < 1E-10) {
-          return to_scalar(poly_of_subelt(cv).eval(local_coordinate ? 
p0.begin() : it));
+          if (!faces_first || mp->trans_of_convex(cv)->structure()->dim() < 
dim)
+            return to_scalar(poly_of_subelt(cv).eval(local_coordinate
+                                                     ? p0.begin() : it));
+          p0_stored = p0; cv_stored = cv;
         }
       }
+        
       if (box_list.size() == 1) break;
       box_list.erase(pmax_box);
     }
-    GMM_ASSERT1(
-      false, "Element not found in composite polynomial: " << base_node(*it, 
*it + mp->dim()));
+    if (cv_stored != size_type(-1))
+      return to_scalar(poly_of_subelt(cv_stored).eval(local_coordinate
+                                                      ? p0_stored.begin(): 
it));
+    GMM_ASSERT1(false, "Element not found in composite polynomial: "
+                << base_node(*it, *it + mp->dim()));
   }
 
   void structured_mesh_for_convex(pconvex_ref cvr, short_type k,
diff --git a/src/getfem_fem.cc b/src/getfem_fem.cc
index f0c0e9e..c432a66 100644
--- a/src/getfem_fem.cc
+++ b/src/getfem_fem.cc
@@ -1,6 +1,6 @@
 /*===========================================================================
 
- Copyright (C) 1999-2017 Yves Renard
+ Copyright (C) 1999-2019 Yves Renard
 
  This file is a part of GetFEM++
 
@@ -324,22 +324,27 @@ namespace getfem {
 
   enum ddl_type { LAGRANGE, NORMAL_DERIVATIVE, DERIVATIVE, MEAN_VALUE,
                   BUBBLE1, LAGRANGE_NONCONFORMING, GLOBAL_DOF,
-                  SECOND_DERIVATIVE, NORMAL_COMPONENT, EDGE_COMPONENT};
+                  SECOND_DERIVATIVE, NORMAL_COMPONENT, EDGE_COMPONENT,
+                  IPK_CENTER};
 
   struct ddl_elem {
     ddl_type t;
     gmm::int16_type hier_degree;
     short_type hier_raff;
+    size_type spec;
     bool operator < (const ddl_elem &l) const {
       if (t < l.t) return true;
       if (t > l.t) return false;
       if (hier_degree < l.hier_degree) return true;
       if (hier_degree > l.hier_degree) return false;
       if (hier_raff < l.hier_raff) return true;
+      if (hier_raff > l.hier_raff) return false;
+      if (spec < l.spec) return true;
       return false;
     }
-    ddl_elem(ddl_type s = LAGRANGE, gmm::int16_type k = -1, short_type l = 0)
-      : t(s), hier_degree(k), hier_raff(l) {}
+    ddl_elem(ddl_type s = LAGRANGE, gmm::int16_type k = -1, short_type l = 0,
+             size_type spec_ = 0)
+      : t(s), hier_degree(k), hier_raff(l), spec(spec_) {}
   };
 
   struct dof_description {
@@ -431,6 +436,22 @@ namespace getfem {
     return &(tab[tab.add_norepeat(l)]);
   }
 
+  pdof_description ipk_center_dof(dim_type n, size_type k_ind) {
+    THREAD_SAFE_STATIC dim_type n_old = dim_type(-2);
+    THREAD_SAFE_STATIC pdof_description p_old = nullptr;
+    if (n != n_old) {
+      dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
+      dof_description l;
+      l.ddl_desc.resize(n);
+      std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),
+                ddl_elem(IPK_CENTER, -1, 0, k_ind));
+      p_old = &(tab[tab.add_norepeat(l)]);
+      n_old = n;
+    }
+    return p_old;
+  }
+  
+
 
   pdof_description to_coord_dof(pdof_description p, dim_type ct) {
     dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
@@ -1055,7 +1076,7 @@ namespace getfem {
                              std::vector<dal::pstatic_stored_object> &) {
     GMM_ASSERT1(params.size() == 2 || params.size() == 3,
                 "Bad number of parameters : "
-                << params.size() << " should be 2.");
+                << params.size() << " should be 2 or 3.");
     GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
                 (params.size() != 3 || params[2].type() == 0),
                 "Bad type of parameters");
@@ -1640,6 +1661,126 @@ namespace getfem {
   }
 
   /* ******************************************************************** */
+  /*    Element Pk on a square with internal nodes (with possible node    */
+  /*  correspondance for surface in 3D (build for HHO elements).          */
+  /* ******************************************************************** */
+  // Not tested. To be tested
+
+  struct IPK_SQUARE_ : public fem<base_poly> {
+    dim_type k;   // 
+    mutable base_matrix K;
+    base_small_vector norient;
+    mutable bgeot::pgeotrans_precomp pgp;
+    mutable bgeot::pgeometric_trans pgt_stored;
+    // mutable pfem_precomp pfp;
+
+    bgeot::pstored_point_tab pC;
+
+    virtual void mat_trans(base_matrix &M, const base_matrix &G,
+                           bgeot::pgeometric_trans pgt) const;
+    IPK_SQUARE_(dim_type nc_);
+  };
+
+  void IPK_SQUARE_::mat_trans(base_matrix &M,
+                              const base_matrix &G,
+                              bgeot::pgeometric_trans pgt) const {
+    // All the dof of this element are concentrated at the center of the 
element
+    // This is a PK element on a square. The base functions are the monomials
+    // The trans_mat is here to eliminate a potential rotation of angle k PI/2
+    // The idea is to compute the gradient at the center and to sort and
+    // orientate the derivative in the two directions, and exchange the base
+    // functions accordingly.
+    dim_type N = dim_type(G.nrows());
+    gmm::copy(gmm::identity_matrix(), M);
+    if (pgt != pgt_stored) {
+      pgt_stored = pgt;
+      pgp = bgeot::geotrans_precomp(pgt, pC, 0);
+    }
+    gmm::resize(K, N, 2);
+    gmm::mult(G, pgp->grad(0), K);
+    scalar_type s0(0), m0(M_PI);
+    for (size_type i = 0; i < N; ++i, m0*=M_PI) s0 += m0 * K(i, 0);
+    scalar_type s1(0), m1(M_PI);
+    for (size_type i = 0; i < N; ++i, m1*=M_PI) s1 += m1 * K(i, 1);
+    scalar_type a0 = gmm::sgn(s0), a1 = gmm::sgn(s1);
+
+    bool inv = false;
+    for (size_type i = 0; i < N; ++i) {
+      if (K(i, 0) * a0 < K(i, 1) * a1 - 1e-6) break;
+      if (K(i, 0) * a0 > K(i, 1) * a1 + 1e-6) { inv = true; break; }
+    }
+
+    if (a0 < 0.) {
+      for (size_type i = 1, l = 1; i < k; ++i)
+        for (size_type j = 0; j <= i; ++j, ++l)
+          { if (((i-j) % 2) == 1) M(l, l) = -1.0; } // X^(i-j) Y^j
+    }
+
+    if (a1 < 0.) {
+      for (size_type i = 1, l = 1; i < k; ++i)
+        for (size_type j = 0; j <= i; ++j, ++l)
+          { if ((j % 2) == 1) M(l, l) = -1.0; } // X^(i-j) Y^j
+    }
+
+    if (inv) {
+      // std::swap(a0, a1);
+      for (size_type i = 1, l = 1; i < k; ++i)
+        for (size_type j = 0; j <= i; ++j, ++l)
+          { M(l, l) = 0.0; M(l, l+i-2*j) = 1.0; }
+    }
+  }
+
+  IPK_SQUARE_::IPK_SQUARE_(dim_type k_) {
+    k = k_;
+    pgt_stored = 0;
+
+    cvr = bgeot::parallelepiped_of_reference(2);
+    dim_ = cvr->structure()->dim();
+    init_cvs_node();
+    es_degree = k;
+    is_pol = true;
+    is_standard_fem = is_lag = is_equiv = false;
+    base_.resize((k+1)*(k+2)/2);
+
+    std::vector<base_node> C(1);
+    C[0] = base_node(0.5, 0.5);
+    pC = bgeot::store_point_tab(C);
+
+    base_poly X, Y;
+    read_poly(X, 2, "x-0.5"); read_poly(Y, 2, "y-0.5");
+
+    base_[0] = bgeot::one_poly(2);
+    add_node(ipk_center_dof(2,0), C[0]);
+
+    for (size_type i = 1, l = 1; i < k; ++i)
+      for (size_type j = 0; j <= i; ++j, ++l) { // X^(i-j) Y^j
+        base_[l] = base_[0];
+        for (size_type n = 0; n < i-j; ++n) base_[l] *= X;
+        for (size_type n = 0; n < j; ++n) base_[l] *= Y;
+        
+        add_node(ipk_center_dof(2,l), C[0]);
+      }
+  }
+
+  static pfem IPK_SQUARE(fem_param_list &params,
+        std::vector<dal::pstatic_stored_object> &dependencies) {
+    GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
+                << params.size() << " should be 1.");
+    GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
+    int k = int(::floor(params[0].num() + 0.01));
+    GMM_ASSERT1(k >= 0 && k < 50 && double(k) == params[0].num(),
+                "Bad parameter");
+    pfem p = std::make_shared<IPK_SQUARE_>(dim_type(k));
+    dependencies.push_back(p->ref_convex(0));
+    dependencies.push_back(p->node_tab(0));
+    return p;
+  }
+
+
+
+  
+
+  /* ******************************************************************** */
   /*    Element RT0 on the simplexes.                                     */
   /* ******************************************************************** */
 
@@ -3681,8 +3822,10 @@ namespace getfem {
 
     PK_discont_(dim_type nc, short_type k, scalar_type alpha=scalar_type(0))
       : PK_fem_(nc, k) {
-      std::fill(dof_types_.begin(), dof_types_.end(),
-                lagrange_nonconforming_dof(nc));
+
+      if (alpha < 1e-4) // In order to glue dof of two faces in 3D,
+        std::fill(dof_types_.begin(), // for alpha > 1e-4. Important.
+                  dof_types_.end(), lagrange_nonconforming_dof(nc));
 
       if (alpha != scalar_type(0)) {
         base_node G =
@@ -3894,7 +4037,9 @@ namespace getfem {
         std::vector<dal::pstatic_stored_object> &dependencies);
   pfem P1bubbletriangle_fem(fem_param_list &params,
         std::vector<dal::pstatic_stored_object> &dependencies);
-
+  pfem hho_method(fem_param_list &params,
+        std::vector<dal::pstatic_stored_object> &dependencies);
+  
   struct fem_naming_system : public dal::naming_system<virtual_fem> {
     fem_naming_system() : dal::naming_system<virtual_fem>("FEM") {
       add_suffix("HERMITE", Hermite_fem);
@@ -3924,12 +4069,14 @@ namespace getfem {
       add_suffix("PK_FULL_HIERARCHICAL_COMPOSITE",
                  PK_composite_full_hierarch_fem);
       add_suffix("PK_GAUSSLOBATTO1D", PK_GL_fem);
+      add_suffix("IPK_QUAD", IPK_SQUARE);
       add_suffix("Q2_INCOMPLETE", Q2_incomplete_fem);
       add_suffix("Q2_INCOMPLETE_DISCONTINUOUS", 
Q2_incomplete_discontinuous_fem);
       add_suffix("HCT_TRIANGLE", HCT_triangle_fem);
       add_suffix("REDUCED_HCT_TRIANGLE", reduced_HCT_triangle_fem);
       add_suffix("QUADC1_COMPOSITE", quadc1p3_fem);
       add_suffix("REDUCED_QUADC1_COMPOSITE", reduced_quadc1p3_fem);
+      add_suffix("HHO", hho_method);
       add_suffix("RT0", P1_RT0);
       add_suffix("RT0Q", P1_RT0Q);
       add_suffix("NEDELEC", P1_nedelec);
diff --git a/src/getfem_fem_composite.cc b/src/getfem_fem_composite.cc
index 8236347..628b33f 100644
--- a/src/getfem_fem_composite.cc
+++ b/src/getfem_fem_composite.cc
@@ -29,12 +29,85 @@ namespace getfem {
  
   typedef const fem<bgeot::polynomial_composite> * ppolycompfem;
 
-  static pfem composite_fe_method(const bgeot::mesh_precomposite &mp, 
-                                 const mesh_fem &mf, bgeot::pconvex_ref cr) {
+  struct polynomial_composite_fem : public fem<bgeot::polynomial_composite> {
+    mesh m;
+    mutable bgeot::mesh_precomposite mp;
+    mesh_fem mf;
+    mutable bgeot::pgeotrans_precomp pgp;
+    mutable bgeot::pgeometric_trans pgt_stored;
+    bgeot::pstored_point_tab pspt;
+
+    
+    virtual void mat_trans(base_matrix &M, const base_matrix &G,
+                           bgeot::pgeometric_trans pgt) const;
+
+    
+    polynomial_composite_fem(const mesh &m_, const mesh_fem &mf_)
+      : m(m_), mp(m), mf(m), pgp(0), pgt_stored(0) {
+      for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv)
+        mf.set_finite_element(cv, mf_.fem_of_element(cv));
+      mf.nb_dof();
+      pspt = store_point_tab(m.points());
+      // verification for the non-equivalent fems
+      for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
+        pfem pf1 = mf.fem_of_element(cv);
+        if (!(pf1->is_equivalent())) {
+          dal::bit_vector unshareable;
+          for (const auto &i : mf.ind_basic_dof_of_element(cv))
+            unshareable.add(i);
+       
+          for (dal::bv_visitor cv2(mf.convex_index()); !cv2.finished(); ++cv2) 
{
+            if (cv2 != cv)
+              for (const auto &i : mf.ind_basic_dof_of_element(cv2))
+                GMM_ASSERT1(!(unshareable.is_in(i)), "Non equivalent elements "
+                            "are allowed only if they do not share their 
dofs");
+          }
+        }
+      }
+    }
+  };
+
+  void polynomial_composite_fem::mat_trans(base_matrix &M, const base_matrix 
&G,
+                                           bgeot::pgeometric_trans pgt) const {
+    dim_type N = dim_type(G.nrows());
+    gmm::copy(gmm::identity_matrix(), M);
+    base_matrix G1, M1;
+
+    if (pgt != pgt_stored) {
+      pgt_stored = pgt;
+      pgp = bgeot::geotrans_precomp(pgt, pspt, 0);
+    }
+    
+    for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
+      pfem pf1 = mf.fem_of_element(cv);
+      if (!(pf1->is_equivalent())) {
+        size_type npt=m.nb_points_of_convex(cv);
+        size_type ndof=mf.nb_basic_dof_of_element(cv);
+        GMM_ASSERT1(ndof == pf1->nb_base(0) && ndof == pf1->nb_dof(0),
+                    "Sorry, limited implementation for the moment");
+        // Compute the local G
+        G1.resize(npt, N);
+        M1.resize(ndof, ndof); 
+        for (size_type i = 0; i < npt; ++i)
+          gmm::copy(pgp->transform(m.ind_points_of_convex(cv)[i], G),
+                    gmm::mat_col(G1, i));
+        // Call for the local M
+        pf1->mat_trans(M1, G1, m.trans_of_convex(cv));
+        gmm::sub_index I(mf.ind_basic_dof_of_element(cv));
+        // I is in fact an interval ...
+        gmm::copy(M1, gmm::sub_matrix(M, I, I));
+      }
+    }
+  }
+
+  static pfem composite_fe_method(const getfem::mesh &m, 
+                                 const mesh_fem &mf, bgeot::pconvex_ref cr,
+                                  bool ff = false) {
     
     GMM_ASSERT1(!mf.is_reduced(),
                "Sorry, does not work for reduced mesh_fems");
-    auto p = std::make_shared<fem<bgeot::polynomial_composite>>();
+    auto p = std::make_shared<polynomial_composite_fem>(m, mf);
+    
     p->mref_convex() = cr;
     p->dim() = cr->structure()->dim();
     p->is_polynomialcomp() = p->is_equivalent() = p->is_standard() = true;
@@ -44,15 +117,16 @@ namespace getfem {
     p->init_cvs_node();
 
     std::vector<bgeot::polynomial_composite> base(mf.nb_basic_dof());
-    std::fill(base.begin(), base.end(), bgeot::polynomial_composite(mp));
+    std::fill(base.begin(), base.end(),
+              bgeot::polynomial_composite(p->mp, true, ff));
     std::vector<pdof_description> dofd(mf.nb_basic_dof());
     
     for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
       pfem pf1 = mf.fem_of_element(cv);
       if (!pf1->is_lagrange()) p->is_lagrange() = false;
-      if (!(pf1->is_equivalent() && pf1->is_polynomial())) {
-       GMM_ASSERT1(false, "Only for polynomial and equivalent fem.");
-      }
+      if (!(pf1->is_equivalent())) p->is_equivalent() = false;
+      
+      GMM_ASSERT1(pf1->is_polynomial(), "Only for polynomial fems.");
       ppolyfem pf = ppolyfem(pf1.get());
       p->estimated_degree() = std::max(p->estimated_degree(),
                                       pf->estimated_degree());
@@ -91,7 +165,7 @@ namespace getfem {
     mesh m(*pm);
     mesh_fem mf(m);
     mf.set_finite_element(pm->convex_index(), pf);
-    pfem p = composite_fe_method(*pmp, mf, pf->ref_convex(0));
+    pfem p = composite_fe_method(m, mf, pf->ref_convex(0));
     dependencies.push_back(p->ref_convex(0));
     dependencies.push_back(p->node_tab(0));
     return p;
@@ -724,4 +798,76 @@ namespace getfem {
   }
 
 
+  /* ******************************************************************** */
+  /*    HHO methods: First method for the interior of the elements and    */
+  /*            a method for each face (or a single method for all faces) */
+  /* ******************************************************************** */
+
+  pfem hho_method(fem_param_list &params,
+       std::vector<dal::pstatic_stored_object> &dependencies) {
+    GMM_ASSERT1(params.size() >= 2, "Bad number of parameters : "
+               << params.size() << " should be at least 2.");
+    GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
+               "Bad type of parameters");
+    pfem pf = params[0].method();
+
+    size_type nbf = pf->ref_convex(0)->structure()->nb_faces();
+    GMM_ASSERT1(pf->is_polynomial(), "Only for polynomial elements");
+
+    std::vector<pfem> pff(nbf);
+    if (params.size() == 2)
+      std::fill(pff.begin(), pff.end(), params[1].method());
+    else {
+      GMM_ASSERT1(params.size() == nbf+1, "Bad number of parameters : "
+                  << params.size() << " a single method for all the faces or "
+                  " a method for each face.");
+      for (size_type i = 0; i < nbf; ++i) {
+        GMM_ASSERT1(params[i+1].type() == 1, "Bad type of parameters");
+        GMM_ASSERT1(params[i+1].method()->is_polynomial(),
+                    "Only for polynomial elements");
+        pff[i] = params[i+1].method();
+      }
+    }
+
+    // Obtain the reference element
+    bgeot::pbasic_mesh pm;
+    bgeot::pmesh_precomposite pmp;
+    structured_mesh_for_convex(pf->ref_convex(0), 1, pm, pmp);
+
+    // Addition of faces
+    bgeot::basic_mesh m0(*pm);
+    for  (short_type i = 0; i < nbf; ++i) {
+      bgeot::mesh_structure::ind_pt_face_ct
+        ipts=m0.ind_points_of_face_of_convex(0,i);
+      bgeot::pconvex_structure cvs
+        = m0.structure_of_convex(0)->faces_structure()[i];
+      m0.add_convex(bgeot::default_trans_of_cvs(cvs), ipts.begin());
+    }
+
+    // Build the mesh_fem
+    mesh m1(m0);
+    bgeot::mesh_precomposite mp; mp.initialise(m1);
+    mesh_fem mf(m1);
+    mf.set_finite_element(0, pf);
+    for  (size_type i = 0; i < nbf; ++i)
+      mf.set_finite_element(i+1, pff[i]);
+    
+    pfem p = composite_fe_method(m1, mf, pf->ref_convex(0), true);
+    dependencies.push_back(p->ref_convex(0));
+    dependencies.push_back(p->node_tab(0));
+    return p;
+  }
+
+
+
+
+
+
+
+
+
+
+  
+
+
 }  /* end of namespace getfem.                                            */



reply via email to

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