GetFEM  5.5
getfem_torus.cc
1 /*===========================================================================
2 
3  Copyright (C) 2014-2026 Liang Jin Lim
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 #include "getfem/bgeot_torus.h"
22 #include "getfem/getfem_torus.h"
23 
24 namespace getfem
25 {
26 
27  void torus_fem::init(){
28  cvr = poriginal_fem_->ref_convex(0);
29  dim_ = cvr->structure()->dim();
30  is_standard_fem = false;
31  is_equiv = real_element_defined = true;
32  is_pol = poriginal_fem_->is_polynomial();
33  is_polycomp = poriginal_fem_->is_polynomialcomp();
34  is_lag = poriginal_fem_->is_lagrange();
35  es_degree = poriginal_fem_->estimated_degree();
36  ntarget_dim = 3;
37 
38  std::stringstream nm;
39  nm << "FEM_TORUS(" << poriginal_fem_->debug_name() << ")";
40  debug_name_ = nm.str();
41 
42  init_cvs_node();
43  GMM_ASSERT1(poriginal_fem_->target_dim() == 1, "Vectorial fems not supported");
44  size_type nb_dof_origin = poriginal_fem_->nb_dof(0);
45  for (size_type k = 0; k < nb_dof_origin; ++k)
46  {
47  for(size_type j = 0; j < 2; ++j){
48  add_node(xfem_dof(poriginal_fem_->dof_types()[k], j),
49  poriginal_fem_->node_of_dof(0, k));
50  }
51  }
52  }
53 
54  size_type torus_fem::index_of_global_dof
55  (size_type /*cv*/, size_type i) const
56  { return i; }
57 
58  void torus_fem::base_value(const base_node &, base_tensor &) const
59  { GMM_ASSERT1(false, "No base values, real only element."); }
60 
61  void torus_fem::grad_base_value(const base_node &, base_tensor &) const
62  { GMM_ASSERT1(false, "No grad values, real only element."); }
63 
64  void torus_fem::hess_base_value(const base_node &, base_tensor &) const{
65  GMM_ASSERT1(false, "No hess values, real only element.");
66  }
67 
69  base_tensor &t, bool) const{
70 
71  GMM_ASSERT1(!(poriginal_fem_->is_on_real_element()), "Original FEM must not be real.");
72 
73  base_tensor u_orig;
74  poriginal_fem_->base_value(c.xref(), u_orig);
75  if (!(poriginal_fem_->is_equivalent())){
76  base_tensor u_temp = u_orig;
77  u_orig.mat_transp_reduction(u_temp, c.M(), 0);
78  }
79 
80  if(is_scalar_){
81  t = u_orig;
82  return;
83  }
84 
85  //expand original base of [nb_base, 1]
86  //to vectorial form [nb_base * dim_, dim_ + 1]
87  bgeot::multi_index tensor_size(u_orig.sizes());
88  tensor_size[0] *= dim_;
89  tensor_size[1] = ntarget_dim;
90  t.adjust_sizes(tensor_size);
91  for (size_type i = 0; i < u_orig.sizes()[0]; ++i) {
92  for (dim_type j = 0; j < dim_; ++j) {
93  t(i*dim_ + j, j) = u_orig(i, 0);
94  }
95  }
96  }
97 
99  (const getfem::fem_interpolation_context& c, base_tensor &t, bool) const
100  {
101  GMM_ASSERT1(!(poriginal_fem_->is_on_real_element()), "Original FEM must not be real.");
102 
103  bgeot::scalar_type radius = std::abs(c.xreal()[0]);
104  base_tensor u;
105  bgeot::pstored_point_tab ppt = c.pgp()->get_ppoint_tab();
106  getfem::pfem_precomp pfp = getfem::fem_precomp(poriginal_fem_, ppt, 0);
107  base_tensor u_origin = pfp->grad(c.ii());
108  //poriginal_fem_->grad_base_value(c.xref(), u_origin);
109  GMM_ASSERT1(!u_origin.empty(), "Original FEM is unable to provide grad base value!");
110 
111  base_tensor n_origin = pfp->val(c.ii());
112  //poriginal_fem_->base_value(c.xref(), n_origin);
113  GMM_ASSERT1(!n_origin.empty(), "Original FEM is unable to provide base value!");
114 
115  //expand original grad of [nb_base, 1, dim_]
116  //to vectorial form [nb_base * dim_, dim_ + 1, dim_ + 1]
117  const bgeot::multi_index &origin_size = u_origin.sizes();
118  bgeot::multi_index tensor_size(origin_size);
119  dim_type dim_size = is_scalar_ ? 1 : dim_;
120  tensor_size[0] *= dim_size;
121  tensor_size[1] = ntarget_dim;
122  tensor_size[2] = dim_ + 1;
123  u.adjust_sizes(tensor_size);
124  for (size_type i = 0; i < origin_size[0]; ++i) { //dof
125  for (dim_type j = 0; j < dim_size; ++j) {
126  for (dim_type k = 0; k < dim_; ++k) {
127  u(i*dim_size+j, j, k) = u_origin(i, 0, k);
128  }
129  }
130  }
131  t = u;
132  t.mat_transp_reduction(u, c.B(), 2);
133 
134  if(is_scalar_) return;
135 
136  for (size_type i = 0; i < origin_size[0]; ++i) {
137  t(i*dim_size, dim_, dim_) = n_origin[i] / radius;
138  }
139  }
140 
142  (const getfem::fem_interpolation_context & /*c*/, base_tensor & /*t*/, bool) const
143  {
144  GMM_ASSERT1(false, "Hessian not yet implemented in torus fem.");
145  }
146 
147  void torus_fem::set_to_scalar(bool is_scalar){
148  if(is_scalar_ == is_scalar) return;
149 
150  is_scalar_ = is_scalar;
151 
152  if(is_scalar_){
153  ntarget_dim = 1;
154  dof_types_.clear();
155  init_cvs_node();
156  size_type nb_dof_origin = poriginal_fem_->nb_dof(0);
157  for (size_type k = 0; k < nb_dof_origin; ++k){
158  add_node(poriginal_fem_->dof_types()[k], poriginal_fem_->node_of_dof(0, k));
159  }
160  }else{
161  ntarget_dim = 3;
162  dof_types_.clear();
163  init_cvs_node();
164  size_type nb_dof_origin = poriginal_fem_->nb_dof(0);
165  for (size_type k = 0; k < nb_dof_origin; ++k)
166  {
167  for(size_type j = 0; j < 2; ++j){
168  add_node(xfem_dof(poriginal_fem_->dof_types()[k], j),
169  poriginal_fem_->node_of_dof(0, k));
170  }
171  }
172  }
173  }
174 
175  pfem torus_fem::get_original_pfem() const{return poriginal_fem_;}
176 
177  DAL_SIMPLE_KEY(torus_fem_key, bgeot::size_type);
178 
179  getfem::pfem new_torus_fem(getfem::pfem pf) {
180  static bgeot::size_type key_count = 0;
181  ++key_count;
182  getfem::pfem pfem_torus = std::make_shared<torus_fem>(pf);
183  dal::pstatic_stored_object_key
184  pk = std::make_shared<torus_fem_key>(key_count);
185  dal::add_stored_object(pk, pfem_torus, pfem_torus->node_tab(0));
186  return pfem_torus;
187  }
188 
189  void del_torus_fem(getfem::pfem pf){
190  const torus_fem *ptorus_fem = dynamic_cast<const torus_fem*>(pf.get());
191  if (ptorus_fem != 0) dal::del_stored_object(pf);
192  }
193 
194  void torus_mesh_fem::adapt_to_torus_(){
195 
196  for (dal::bv_visitor cv(linked_mesh().convex_index()); !cv.finished(); ++cv){
197  pfem poriginal_fem = fem_of_element(cv);
198  if(poriginal_fem == 0) continue;
199 
200  del_torus_fem(poriginal_fem);
201 
202  pfem pf = new_torus_fem(poriginal_fem);
203  torus_fem *pf_torus = dynamic_cast<torus_fem*>(const_cast<virtual_fem*>(pf.get()));
204  pf_torus->set_to_scalar((Qdim != 3));
205  set_finite_element(cv, pf);
206  }
207  touch();
208  }
209 
211  {
212  const_cast<torus_mesh_fem*>(this)->adapt_to_torus_();
213 
214  for (dal::bv_visitor cv(linked_mesh().convex_index()); !cv.finished(); ++cv){
215  pfem pf = fem_of_element(cv);
216  if(pf == 0) continue;
217  torus_fem *pf_torus = dynamic_cast<torus_fem*>(const_cast<virtual_fem*>(pf.get()));
218  if(pf_torus == 0) continue;
219  pf_torus->set_to_scalar((Qdim != 3));
220  }
221 
223  }
224 
225  torus_mesh::torus_mesh(std::string name) : mesh(std::move(name)){}
226 
228  {
229  base_matrix G;
230  bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
231  G.resize(2, G.ncols());
232  auto pgt_torus = std::dynamic_pointer_cast<const bgeot::torus_geom_trans>(trans_of_convex(ic));
233  GMM_ASSERT2(pgt_torus, "Internal error, convex is not a torus transformation.");
234  return getfem::convex_radius_estimate(pgt_torus->get_original_transformation(), G);
235  }
236 
237  void torus_mesh::adapt(const getfem::mesh &original_mesh){
238  clear();
239  GMM_ASSERT1(original_mesh.dim() == 2, "Adapting torus feature must be a 2d mesh");
240  mesh::copy_from(original_mesh);
241  adapt();
242  }
243 
244  void torus_mesh::adapt(){
245 
246  bgeot::node_tab node_tab_copy(pts);
247  this->pts.clear();
248  for(size_type pt = 0; pt < node_tab_copy.size(); ++pt){
249  node_tab_copy[pt].resize(3);
250  this->pts.add_node(node_tab_copy[pt]);
251  }
252 
253  for(size_type i = 0; i < this->convex_tab.size(); ++i){
254  bgeot::pconvex_structure pstructure
255  = bgeot::torus_structure_descriptor(convex_tab[i].cstruct);
256  convex_tab[i].cstruct = pstructure;
257  }
258 
259  for(size_type i = 0; i < this->gtab.size(); ++i){
260  bgeot::pgeometric_trans pgeom_trans = bgeot::torus_geom_trans_descriptor(gtab[i]);
261  gtab[i] = pgeom_trans;
262  }
263  }
264 }
Provides mesh of torus.
const base_node & xreal() const
coordinates of the current point, in the real convex.
const base_node & xref() const
coordinates of the current point, in the reference convex.
Store a set of points, identifying points that are nearer than a certain very small distance.
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:749
virtual void enumerate_dof() const
Renumber the degrees of freedom.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
void set_finite_element(size_type cv, pfem pf)
Set the finite element method of a convex.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash!...
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
void copy_from(const mesh &m)
Clone a mesh.
Definition: getfem_mesh.cc:486
void clear()
Erase the mesh.
Definition: getfem_mesh.cc:272
Torus fem, the real grad base value is modified to compute radial grad of F/R.
Definition: getfem_torus.h:51
void real_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the value of all components of the base functions at the current point of the fem_interpolation_...
Definition: getfem_torus.cc:68
void hess_base_value(const base_node &, base_tensor &) const
Give the value of all hessians (on ref.
Definition: getfem_torus.cc:64
void real_grad_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the gradient of all components of the base functions at the current point of the fem_interpolati...
Definition: getfem_torus.cc:99
void base_value(const base_node &, base_tensor &) const
Give the value of all components of the base functions at the point x of the reference element.
Definition: getfem_torus.cc:58
void real_hess_base_value(const fem_interpolation_context &, base_tensor &, bool=true) const
Give the hessian of all components of the base functions at the current point of the fem_interpolatio...
void grad_base_value(const base_node &, base_tensor &) const
Give the value of all gradients (on ref.
Definition: getfem_torus.cc:61
Mesh fem object that adapts.
Definition: getfem_torus.h:96
void enumerate_dof(void) const
Renumber the degrees of freedom.
virtual scalar_type convex_radius_estimate(size_type ic) const
Return an estimate of the convex largest dimension.
Base class for finite element description.
Definition: getfem_fem.h:255
Provides mesh and mesh fem of torus.
pdof_description xfem_dof(pdof_description p, size_type ind)
Description of a special dof for Xfem.
Definition: getfem_fem.cc:433
scalar_type APIDECL convex_radius_estimate(bgeot::pgeometric_trans pgt, const base_matrix &pts)
rough estimate of the radius of the convex using the largest eigenvalue of the jacobian of the geomet...
Definition: getfem_mesh.cc:797
void add_node(const pdof_description &d, const base_node &pt, const dal::bit_vector &faces)
internal function adding a node to an element for the creation of a finite element method.
Definition: getfem_fem.cc:648
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:243
const base_matrix & M() const
non tau-equivalent transformation matrix.
Definition: getfem_fem.cc:43
pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt, dal::pstatic_stored_object dep)
Handles precomputations for FEM.
Definition: getfem_fem.cc:4760
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
GEneric Tool for Finite Element Methods.