GetFEM++  5.3
getfem_mesh_fem.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 1999-2017 Yves Renard
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**@file getfem_mesh_fem.h
33  @author Yves Renard <Yves.Renard@insa-lyon.fr>
34  @date December 21, 1999.
35  @brief Define the getfem::mesh_fem class
36 */
37 
38 #ifndef GETFEM_MESH_FEM_H__
39 #define GETFEM_MESH_FEM_H__
40 
41 #include "getfem_mesh.h"
42 #include "getfem_fem.h"
43 
44 
45 namespace getfem {
46 
47  template <class CONT> struct tab_scal_to_vect_iterator {
48 
49  typedef typename CONT::const_iterator ITER;
50  typedef typename std::iterator_traits<ITER>::value_type value_type;
51  typedef typename std::iterator_traits<ITER>::pointer pointer;
52  typedef typename std::iterator_traits<ITER>::reference reference;
53  typedef typename std::iterator_traits<ITER>::difference_type
54  difference_type;
55  typedef typename std::iterator_traits<ITER>::iterator_category
56  iterator_category;
57  typedef size_t size_type;
58  typedef tab_scal_to_vect_iterator<CONT> iterator;
59 
60  ITER it;
61  dim_type N;
62  dim_type ii;
63 
64  iterator &operator ++()
65  { ++ii; if (ii == N) { ii = 0; ++it; } return *this; }
66  iterator &operator --()
67  { if (ii == 0) { ii = N-1; --it; } else --ii; return *this; }
68  iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
69  iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
70 
71  iterator &operator +=(difference_type i)
72  { it += (i+ii)/N; ii = dim_type((ii + i) % N); return *this; }
73  iterator &operator -=(difference_type i)
74  { it -= (i+N-ii-1)/N; ii = (ii - i + N * i) % N; return *this; }
75  iterator operator +(difference_type i) const
76  { iterator itt = *this; return (itt += i); }
77  iterator operator -(difference_type i) const
78  { iterator itt = *this; return (itt -= i); }
79  difference_type operator -(const iterator &i) const
80  { return (it - i.it) * N + ii - i.ii; }
81 
82  value_type operator *() const { return (*it) + ii; }
83  value_type operator [](int i) { return *(this + i); }
84 
85  bool operator ==(const iterator &i) const
86  { return (it == i.it) && (ii == i.ii); }
87  bool operator !=(const iterator &i) const { return !(i == *this); }
88  bool operator < (const iterator &i) const
89  { return (it < i.it) && (ii < i.ii); }
90 
91  tab_scal_to_vect_iterator() {}
92  tab_scal_to_vect_iterator(const ITER &iter, dim_type n, dim_type i)
93  : it(iter), N(n), ii(i) { }
94 
95  };
96 
97  /** @internal @brief structure for iteration over the dofs when Qdim
98  != 1 and target_dim == 1
99  */
100  template <class CONT> class tab_scal_to_vect {
101  public :
102  typedef typename CONT::const_iterator ITER;
103  typedef typename std::iterator_traits<ITER>::value_type value_type;
104  typedef typename std::iterator_traits<ITER>::pointer pointer;
105  typedef typename std::iterator_traits<ITER>::pointer const_pointer;
106  typedef typename std::iterator_traits<ITER>::reference reference;
107  typedef typename std::iterator_traits<ITER>::reference const_reference;
108  typedef typename std::iterator_traits<ITER>::difference_type
109  difference_type;
110  typedef size_t size_type;
111  typedef tab_scal_to_vect_iterator<CONT> iterator;
112  typedef iterator const_iterator;
113  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
114  typedef std::reverse_iterator<iterator> reverse_iterator;
115 
116 
117  protected :
118  ITER it, ite;
119  dim_type N;
120 
121  public :
122 
123  bool empty() const { return it == ite; }
124  size_type size() const { return (ite - it) * N; }
125 
126  const_iterator begin() const { return iterator(it, N, 0); }
127  const_iterator end() const { return iterator(ite, N, 0); }
128  const_reverse_iterator rbegin() const
129  { return const_reverse_iterator(end()); }
130  const_reverse_iterator rend() const
131  { return const_reverse_iterator(begin()); }
132 
133  value_type front() const { return *begin(); }
134  value_type back() const { return *(--(end())); }
135 
136  tab_scal_to_vect() : N(0) {}
137  tab_scal_to_vect(const CONT &cc, dim_type n)
138  : it(cc.begin()), ite(cc.end()), N(n) {}
139 
140  value_type operator [](size_type ii) const { return *(begin() + ii);}
141  };
142 
143  /** Describe a finite element method linked to a mesh.
144  *
145  * @see mesh
146  * @see mesh_im
147  */
148  class mesh_fem : public context_dependencies, virtual public dal::static_stored_object {
149  protected :
150  typedef gmm::csc_matrix<scalar_type> REDUCTION_MATRIX;
151  typedef gmm::csr_matrix<scalar_type> EXTENSION_MATRIX;
152 
153  void copy_from(const mesh_fem &mf); /* Remember to change copy_from if
154  adding components to mesh_fem */
155 
156  std::vector<pfem> f_elems;
157  dal::bit_vector fe_convex;
158  const mesh *linked_mesh_;
159  REDUCTION_MATRIX R_;
160  EXTENSION_MATRIX E_;
161  mutable bgeot::mesh_structure dof_structure;
162  mutable bool dof_enumeration_made;
163  mutable bool is_uniform_, is_uniformly_vectorized_;
164  mutable size_type nb_total_dof;
165  pfem auto_add_elt_pf; /* fem for automatic addition */
166  /* of element option. (0 = no automatic addition) */
167  dim_type auto_add_elt_K; /* Degree of the fem for automatic addition */
168  /* of element option. (-1 = no automatic addition) */
169  bool auto_add_elt_disc, auto_add_elt_complete;
170  scalar_type auto_add_elt_alpha;
171  dim_type Qdim; /* this is the "total" target_dim. */
172  bgeot::multi_index mi; /* multi dimensions for matrix/tensor field. */
173  // dim_type QdimM, QdimN; /* for matrix field with QdimM lines and QdimN */
174  // /* columnsQdimM * QdimN = Qdim. */
175  std::vector<size_type> dof_partition;
176  mutable gmm::uint64_type v_num_update, v_num;
177  bool use_reduction; /* A reduction matrix is applied or not. */
178 
179  public :
180  typedef base_node point_type;
181  typedef tab_scal_to_vect<mesh::ind_cv_ct> ind_dof_ct;
182  typedef tab_scal_to_vect<mesh::ind_pt_face_ct> ind_dof_face_ct;
183 
184  void update_from_context() const;
185 
186  gmm::uint64_type version_number() const
187  { context_check(); return v_num; }
188 
189  /** Get the set of convexes where a finite element has been assigned.
190  */
191  inline const dal::bit_vector &convex_index() const
192  { context_check(); return fe_convex; }
193 
194  /// Return true if a reduction matrix is applied to the dofs.
195  bool is_reduced() const { return use_reduction; }
196 
197  /// Return the reduction matrix applied to the dofs.
198  const REDUCTION_MATRIX &reduction_matrix() const { return R_; }
199 
200  /// Return the extension matrix corresponding to reduction applied (RE=I).
201  const EXTENSION_MATRIX &extension_matrix() const { return E_; }
202 
203  /** Allows to set the reduction and the extension matrices.
204  * Should satify (RR*EE=I). */
205  template <typename MATR, typename MATE>
206  void set_reduction_matrices(const MATR &RR, const MATE &EE) {
207  context_check();
208  GMM_ASSERT1(gmm::mat_ncols(RR) == nb_basic_dof() &&
209  gmm::mat_nrows(EE) == nb_basic_dof() &&
210  gmm::mat_nrows(RR) == gmm::mat_ncols(EE),
211  "Wrong dimension of reduction and/or extension matrices");
212  R_ = REDUCTION_MATRIX(gmm::mat_nrows(RR), gmm::mat_ncols(RR));
213  E_ = EXTENSION_MATRIX(gmm::mat_nrows(EE), gmm::mat_ncols(EE));
214  gmm::copy(RR, R_);
215  gmm::copy(EE, E_);
216  use_reduction = true;
217  touch(); v_num = act_counter();
218  }
219 
220  /** Allows to set the reduction and the extension matrices in order
221  * to keep only a certain number of dof. */
222  void reduce_to_basic_dof(const dal::bit_vector &kept_basic_dof);
223  void reduce_to_basic_dof(const std::set<size_type> &kept_basic_dof);
224 
225  /// Validate or invalidate the reduction (keeping the reduction matrices).
226  void set_reduction(bool r) {
227  if (r != use_reduction) {
228  use_reduction = r;
229  if (use_reduction) {
230  context_check();
231  GMM_ASSERT1(gmm::mat_ncols(R_) == nb_basic_dof() &&
232  gmm::mat_nrows(E_) == nb_basic_dof() &&
233  gmm::mat_nrows(R_) == gmm::mat_ncols(E_),
234  "Wrong dimension of reduction and/or extension matrices");
235  }
236  touch(); v_num = act_counter();
237  }
238  }
239 
240  template<typename VECT1, typename VECT2>
241  void reduce_vector(const VECT1 &V1, const VECT2 &V2) const {
242  if (is_reduced()) {
243  size_type qqdim = gmm::vect_size(V1) / nb_basic_dof();
244  if (qqdim == 1)
245  gmm::mult(reduction_matrix(), V1, const_cast<VECT2 &>(V2));
246  else
247  for (size_type k = 0; k < qqdim; ++k)
248  gmm::mult(reduction_matrix(),
249  gmm::sub_vector(V1, gmm::sub_slice(k, nb_basic_dof(),
250  qqdim)),
251  gmm::sub_vector(const_cast<VECT2 &>(V2),
252  gmm::sub_slice(k, nb_dof(),
253  qqdim)));
254  }
255  else gmm::copy(V1, const_cast<VECT2 &>(V2));
256  }
257 
258  template<typename VECT1, typename VECT2>
259  void extend_vector(const VECT1 &V1, const VECT2 &V2) const {
260  if (is_reduced()) {
261  size_type qqdim = gmm::vect_size(V1) / nb_dof();
262  if (qqdim == 1)
263  gmm::mult(extension_matrix(), V1, const_cast<VECT2 &>(V2));
264  else
265  for (size_type k = 0; k < qqdim; ++k)
266  gmm::mult(extension_matrix(),
267  gmm::sub_vector(V1, gmm::sub_slice(k, nb_dof(),
268  qqdim)),
269  gmm::sub_vector(const_cast<VECT2 &>(V2),
270  gmm::sub_slice(k, nb_basic_dof(),
271  qqdim)));
272  }
273  else gmm::copy(V1, const_cast<VECT2 &>(V2));
274  }
275 
276 
277  /// Return a reference to the underlying mesh.
278  const mesh &linked_mesh() const { return *linked_mesh_; }
279 
280  virtual bool is_uniform() const;
281  virtual bool is_uniformly_vectorized() const;
282 
283  /** Set the degree of the fem for automatic addition
284  * of element option. K=-1 disables the automatic addition.
285  */
286  void set_auto_add(dim_type K, bool disc = false,
287  scalar_type alpha = scalar_type(0),
288  bool complete=false) {
289  auto_add_elt_K = K;
290  auto_add_elt_disc = disc;
291  auto_add_elt_alpha = alpha;
292  auto_add_elt_complete = complete;
293  auto_add_elt_pf = 0;
294  }
295 
296  /** Set the fem for automatic addition
297  * of element option. pf=0 disables the automatic addition.
298  */
299  void set_auto_add(pfem pf) {
300  auto_add_elt_pf = pf;
301  auto_add_elt_K = dim_type(-1);
302  auto_add_elt_disc = false;
303  auto_add_elt_alpha = scalar_type(0);
304  auto_add_elt_complete = false;
305  }
306 
307  /** Return the Q dimension. A mesh_fem used for scalar fields has
308  Q=1, for vector fields, Q is typically equal to
309  linked_mesh().dim().
310  */
311  virtual dim_type get_qdim() const { return Qdim; }
312  virtual const bgeot::multi_index &get_qdims() const { return mi; }
313 
314  /** Change the Q dimension */
315  virtual void set_qdim(dim_type q) {
316  if (q != Qdim || mi.size() != 1) {
317  mi.resize(1); mi[0] = q; Qdim = q;
318  dof_enumeration_made = false; touch(); v_num = act_counter();
319  }
320  }
321 
322  /** Set the dimension for a matrix field. */
323  virtual void set_qdim(dim_type M, dim_type N) {
324  if (mi.size() != 2 || mi[0] != M || mi[1] != N) {
325  mi.resize(2); mi[0] = M; mi[1] = N; Qdim = dim_type(M*N);
326  dof_enumeration_made = false; touch(); v_num = act_counter();
327  }
328  }
329 
330  /** Set the dimension for a fourth order tensor field. */
331  virtual void set_qdim(dim_type M, dim_type N, dim_type O, dim_type P) {
332  if (mi.size() != 4 || mi[0] != M || mi[1] != N || mi[2] != O
333  || mi[3] != P) {
334  mi.resize(4); mi[0] = M; mi[1] = N; mi[2] = O; mi[3] = P;
335  Qdim = dim_type(M*N*O*P);
336  dof_enumeration_made = false; touch(); v_num = act_counter();
337  }
338  }
339 
340  /** Set the dimension for an arbitrary order tensor field. */
341  virtual void set_qdim(const bgeot::multi_index &mii) {
342  GMM_ASSERT1(mii.size() < 7,
343  "Tensor field are taken into account up to order 6.");
344  GMM_ASSERT1(mi.size(), "Wrong sizes");
345  if (!(mi.is_equal(mii))) {
346  mi = mii;
347  Qdim = dim_type(1);
348  for (size_type i = 0; i < mi.size(); ++i)
349  Qdim = dim_type(Qdim*mi[i]);
350  GMM_ASSERT1(Qdim, "Wrong sizes");
351  dof_enumeration_made = false; touch(); v_num = act_counter();
352  }
353  }
354 
355 
356  void set_qdim_mn(dim_type M, dim_type N) IS_DEPRECATED
357  { set_qdim(M,N); }
358 
359  /** for matrix fields, return the number of rows. */
360  dim_type get_qdim_m() const IS_DEPRECATED { return dim_type(mi[0]); }
361  /** for matrix fields, return the number of columns. */
362  dim_type get_qdim_n() const IS_DEPRECATED { return dim_type(mi[1]); }
363 
364 
365  /** Set the finite element method of a convex.
366  @param cv the convex number.
367  @param pf the finite element.
368  */
369  void set_finite_element(size_type cv, pfem pf);
370  /** Set the finite element on a set of convexes.
371  @param cvs the set of convex indexes, as a dal::bit_vector.
372  @param pf the finite element, typically obtained with
373  @code getfem::fem_descriptor("FEM_SOMETHING(..)")
374  @endcode
375  */
376  void set_finite_element(const dal::bit_vector &cvs, pfem pf);
377  /** shortcut for set_finite_element(linked_mesh().convex_index(),pf);
378  and set_auto_add(pf). */
379  void set_finite_element(pfem pf);
380  /** Set a classical (i.e. lagrange polynomial) finite element on
381  a convex.
382  @param cv is the convex number.
383  @param fem_degree the polynomial degree of the finite element.
384  @param complete is a flag for excluding incomplete element
385  irrespective of the element geometric transformation.
386  */
387  void set_classical_finite_element(size_type cv, dim_type fem_degree,
388  bool complete=false);
389  /** Set a classical (i.e. lagrange polynomial) finite element on
390  a set of convexes.
391  @param cvs the set of convexes, as a dal::bit_vector.
392  @param fem_degree the polynomial degree of the finite element.
393  */
394  void set_classical_finite_element(const dal::bit_vector &cvs,
395  dim_type fem_degree,
396  bool complete=false);
397  /** Similar to set_classical_finite_element, but uses
398  discontinuous lagrange elements.
399 
400  @param cv the convex index.
401  @param fem_degree the polynomial degree of the finite element.
402  @param alpha the node inset, 0 <= alpha < 1, where 0 implies
403  usual dof nodes, greater values move the nodes toward the
404  center of gravity, and 1 means that all degrees of freedom
405  collapse on the center of gravity.
406  */
407  void set_classical_discontinuous_finite_element(size_type cv,
408  dim_type fem_degree,
409  scalar_type alpha=0,
410  bool complete=false);
411  /** Similar to set_classical_finite_element, but uses
412  discontinuous lagrange elements.
413 
414  @param cvs the set of convexes, as a dal::bit_vector.
415  @param fem_degree the polynomial degree of the finite element.
416  @param alpha the node inset, 0 <= alpha < 1, where 0 implies
417  usual dof nodes, greater values move the nodes toward the
418  center of gravity, and 1 means that all degrees of freedom
419  collapse on the center of gravity.
420  */
421  void set_classical_discontinuous_finite_element(const dal::bit_vector &cvs,
422  dim_type fem_degree,
423  scalar_type alpha=0,
424  bool complete=false);
425  /** Shortcut for
426  * set_classical_finite_element(linked_mesh().convex_index(),...)
427  */
428  void set_classical_finite_element(dim_type fem_degree,
429  bool complete=false);
430  /** Shortcut for
431  * set_classical_discontinuous_finite_element(linked_mesh().convex_index()
432  * ,...)
433  */
434  void set_classical_discontinuous_finite_element(dim_type fem_degree,
435  scalar_type alpha=0,
436  bool complete=false);
437  /** Return the basic fem associated with an element (if no fem is
438  * associated, the function will crash! use the convex_index() of
439  * the mesh_fem to check that a fem is associated to a given
440  * convex). This fem does not take into account the optional
441  * vectorization due to qdim nor the optional reduction.
442  */
443  virtual pfem fem_of_element(size_type cv) const
444  { return ((cv < f_elems.size()) ? f_elems[cv] : 0); }
445  /** Give an array of the dof numbers a of convex.
446  * @param cv the convex number.
447  * @return a pseudo-container of the dof number.
448  */
449  virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const {
450  context_check(); if (!dof_enumeration_made) enumerate_dof();
451  return ind_dof_ct(dof_structure.ind_points_of_convex(cv),
452  dim_type(Qdim/fem_of_element(cv)->target_dim()));
453  }
454  ind_dof_ct ind_dof_of_element(size_type cv) const IS_DEPRECATED
455  { return ind_basic_dof_of_element(cv); }
456  virtual const bgeot::mesh_structure::ind_cv_ct &
457  ind_scalar_basic_dof_of_element(size_type cv) const
458  { return dof_structure.ind_points_of_convex(cv); }
459  /** Give an array of the dof numbers lying of a convex face (all
460  degrees of freedom whose associated base function is non-zero
461  on the convex face).
462  @param cv the convex number.
463  @param f the face number.
464  @return a pseudo-container of the dof number.
465  */
466  virtual ind_dof_face_ct
468  context_check(); if (!dof_enumeration_made) enumerate_dof();
469  return ind_dof_face_ct
470  (dof_structure.ind_points_of_face_of_convex(cv, f),
471  dim_type(Qdim/fem_of_element(cv)->target_dim()));
472  }
473  ind_dof_face_ct
474  ind_dof_of_face_of_element(size_type cv,short_type f) const IS_DEPRECATED
475  { return ind_basic_dof_of_face_of_element(cv, f); }
476  /** Return the number of dof lying on the given convex face.
477  @param cv the convex number.
478  @param f the face number.
479  */
480  virtual size_type nb_basic_dof_of_face_of_element(size_type cv,
481  short_type f) const {
482  context_check(); if (!dof_enumeration_made) enumerate_dof();
483  pfem pf = f_elems[cv];
484  return dof_structure.structure_of_convex(cv)->nb_points_of_face(f)
485  * Qdim / pf->target_dim();
486  }
487  size_type nb_dof_of_face_of_element(size_type cv,
488  short_type f) const IS_DEPRECATED
489  { return nb_basic_dof_of_face_of_element(cv, f); }
490  /** Return the number of degrees of freedom attached to a given convex.
491  @param cv the convex number.
492  */
493  virtual size_type nb_basic_dof_of_element(size_type cv) const {
494  context_check(); if (!dof_enumeration_made) enumerate_dof();
495  pfem pf = f_elems[cv]; return pf->nb_dof(cv) * Qdim / pf->target_dim();
496  }
497  size_type nb_dof_of_element(size_type cv) const IS_DEPRECATED
498  { return nb_basic_dof_of_element(cv); }
499 
500  /* Return the geometrical location of a degree of freedom in the
501  reference convex.
502  @param cv the convex number.
503  @param i the local dof number.
504  const base_node &reference_point_of_dof(size_type cv,size_type i) const {
505  pfem pf = f_elems[cv];
506  return pf->node_of_dof(cv, i * pf->target_dim() / Qdim);
507  }
508  */
509  /** Return the geometrical location of a degree of freedom.
510  @param cv the convex number.
511  @param i the local dof number.
512  */
513  virtual base_node point_of_basic_dof(size_type cv, size_type i) const;
514  base_node point_of_dof(size_type cv, size_type i) const IS_DEPRECATED
515  { return point_of_basic_dof(cv, i); }
516  /** Return the geometrical location of a degree of freedom.
517  @param d the global dof number.
518  */
519  virtual base_node point_of_basic_dof(size_type d) const;
520  base_node point_of_dof(size_type d) const IS_DEPRECATED
521  { return point_of_basic_dof(d); }
522  /** Return the dof component number (0<= x <Qdim) */
523  virtual dim_type basic_dof_qdim(size_type d) const;
524  dim_type dof_qdim(size_type d) const IS_DEPRECATED
525  { return basic_dof_qdim(d); }
526  /** Shortcut for convex_to_dof(d)[0]
527  @param d the global dof number.
528  */
529  virtual size_type first_convex_of_basic_dof(size_type d) const;
530  size_type first_convex_of_dof(size_type d) const IS_DEPRECATED
531  { return first_convex_of_basic_dof(d); }
532  /** Return the list of convexes attached to the specified dof
533  @param d the global dof number.
534  @return an array of convex numbers.
535  */
536  virtual const mesh::ind_cv_ct &convex_to_basic_dof(size_type d) const;
537  const mesh::ind_cv_ct &convex_to_dof(size_type d) const IS_DEPRECATED
538  { return convex_to_basic_dof(d); }
539 
540  /** Give an array that contains the global dof indices corresponding
541  * to the mesh_fem dofs or size_type(-1) if a dof is not global.
542  * @param ind the returned global dof indices array.
543  */
544  virtual void get_global_dof_index(std::vector<size_type> &ind) const;
545  /** Renumber the degrees of freedom. You should not have
546  * to call this function, as it is done automatically */
547  virtual void enumerate_dof() const;
548 
549 #if GETFEM_PARA_LEVEL > 1
550  void enumerate_dof_para()const;
551 #endif
552 
553  /** Return the total number of basic degrees of freedom (before the
554  * optional reduction). */
555  virtual size_type nb_basic_dof() const {
556  context_check(); if (!dof_enumeration_made) enumerate_dof();
557  return nb_total_dof;
558  }
559  /// Return the total number of degrees of freedom.
560  virtual size_type nb_dof() const {
561  context_check(); if (!dof_enumeration_made) enumerate_dof();
562  return use_reduction ? gmm::mat_nrows(R_) : nb_total_dof;
563  }
564  /** Get a list of basic dof lying on a given mesh_region.
565  @param b the mesh_region.
566  @return the list in a dal::bit_vector.
567  */
568  virtual dal::bit_vector basic_dof_on_region(const mesh_region &b) const;
569  /** Get a list of dof lying on a given mesh_region. For a reduced mesh_fem
570  a dof is lying on a region if its potential corresponding shape
571  function is nonzero on this region. The extension matrix is used
572  to make the correspondance between basic and reduced dofs.
573  @param b the mesh_region.
574  @return the list in a dal::bit_vector.
575  */
576  dal::bit_vector dof_on_region(const mesh_region &b) const;
577  dal::bit_vector dof_on_set(const mesh_region &b) const IS_DEPRECATED
578  { return dof_on_region(b); }
579 
580  void set_dof_partition(size_type cv, unsigned partition_num) {
581  if (dof_partition.empty() && partition_num == 0) return;
582  if (dof_partition.size() < linked_mesh().nb_allocated_convex())
583  dof_partition.resize(linked_mesh().nb_allocated_convex());
584  if (dof_partition.at(cv) != partition_num) {
585  dof_partition[cv] = partition_num;
586  dof_enumeration_made = false;
587  }
588  }
589  unsigned get_dof_partition(size_type cv) const {
590  return (cv < dof_partition.size() ? unsigned(dof_partition[cv]) : 0);
591  }
592  void clear_dof_partition() { dof_partition.clear(); }
593 
594  size_type memsize() const {
595  return dof_structure.memsize() +
596  sizeof(mesh_fem) - sizeof(bgeot::mesh_structure) +
597  f_elems.size() * sizeof(pfem) + fe_convex.memsize();
598  }
599  void init_with_mesh(const mesh &me, dim_type Q = 1);
600  /** Build a new mesh_fem. A mesh object must be supplied.
601  @param me the linked mesh.
602  @param Q the Q dimension (see mesh_fem::get_qdim).
603  */
604  explicit mesh_fem(const mesh &me, dim_type Q = 1);
605  mesh_fem();
606  mesh_fem(const mesh_fem &mf);
607  mesh_fem &operator=(const mesh_fem &mf);
608 
609  virtual ~mesh_fem();
610  virtual void clear();
611  /** Read the mesh_fem from a stream.
612  @param ist the stream.
613  */
614  virtual void read_from_file(std::istream &ist);
615  /** Read the mesh_fem from a file.
616  @param name the file name. */
617  void read_from_file(const std::string &name);
618  /* internal usage. */
619  void write_basic_to_file(std::ostream &ost) const;
620  /* internal usage. */
621  void write_reduction_matrices_to_file(std::ostream &ost) const;
622  /** Write the mesh_fem to a stream. */
623  virtual void write_to_file(std::ostream &ost) const;
624  /** Write the mesh_fem to a file.
625 
626  @param name the file name
627 
628  @param with_mesh if set, then the linked_mesh() will also be
629  saved to the file.
630  */
631  void write_to_file(const std::string &name, bool with_mesh=false) const;
632  };
633 
634  /** Gives the descriptor of a classical finite element method of degree K
635  on mesh.
636 
637  The mesh_fem won't be destroyed until its linked_mesh is
638  destroyed. All the mesh_fem built by this function are stored
639  in a cache, which means that calling this function twice with
640  the same arguments will return the same mesh_fem object. A
641  consequence is that you should NEVER modify this mesh_fem!
642  */
643  const mesh_fem &classical_mesh_fem(const mesh &mesh, dim_type degree,
644  dim_type qdim=1, bool complete=false);
645 
646  /** Dummy mesh_fem for default parameter of functions. */
647  const mesh_fem &dummy_mesh_fem();
648 
649 
650  /** Given a mesh_fem @param mf and a vector @param vec of size equal to
651  * mf.nb_basic_dof(), the output vector @param coeff will contain the
652  * values of @param vec corresponding to the basic dofs of element
653  * @param cv. The size of @param coeff is adjusted if necessary.
654  */
655  template <typename VEC1, typename VEC2>
657  const VEC1 &vec,
658  size_type cv, VEC2 &coeff,
659  size_type qmult1 = size_type(-1),
660  size_type qmult2 = size_type(-1)) {
661  if (qmult1 == size_type(-1)) {
662  size_type nbdof = mf.nb_basic_dof();
663  qmult1 = gmm::vect_size(vec) / nbdof;
664  GMM_ASSERT1(gmm::vect_size(vec) == qmult1 * nbdof, "Bad dof vector size");
665  }
666  if (qmult2 == size_type(-1)) {
667  qmult2 = mf.get_qdim();
668  if (qmult2 > 1) qmult2 /= mf.fem_of_element(cv)->target_dim();
669  }
670  size_type qmultot = qmult1*qmult2;
671  auto &ct = mf.ind_scalar_basic_dof_of_element(cv);
672  gmm::resize(coeff, ct.size()*qmultot);
673 
674  auto it = ct.begin();
675  auto itc = coeff.begin();
676  if (qmultot == 1) {
677  for (; it != ct.end(); ++it) *itc++ = vec[*it];
678  } else {
679  for (; it != ct.end(); ++it) {
680  auto itv = vec.begin()+(*it)*qmult1;
681  for (size_type m = 0; m < qmultot; ++m) *itc++ = *itv++;
682  }
683  }
684  }
685 
686  void vectorize_base_tensor(const base_tensor &t, base_matrix &vt,
687  size_type ndof, size_type qdim, size_type N);
688 
689  void vectorize_grad_base_tensor(const base_tensor &t, base_tensor &vt,
690  size_type ndof, size_type qdim, size_type N);
691 
692 
693 } /* end of namespace getfem. */
694 
695 
696 #endif /* GETFEM_MESH_FEM_H__ */
virtual size_type nb_basic_dof_of_element(size_type cv) const
Return the number of degrees of freedom attached to a given convex.
dim_type get_qdim_n() const IS_DEPRECATED
for matrix fields, return the number of columns.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
structure used to hold a set of convexes and/or convex faces.
void slice_vector_on_basic_dof_of_element(const mesh_fem &mf, const VEC1 &vec, size_type cv, VEC2 &coeff, size_type qmult1=size_type(-1), size_type qmult2=size_type(-1))
Given a mesh_fem.
Define a getfem::getfem_mesh object.
base class for static stored objects
const mesh_fem & dummy_mesh_fem()
Dummy mesh_fem for default parameter of functions.
virtual void set_qdim(dim_type M, dim_type N, dim_type O, dim_type P)
Set the dimension for a fourth order tensor field.
void set_reduction_matrices(const MATR &RR, const MATE &EE)
Allows to set the reduction and the extension matrices.
ind_pt_face_ct ind_points_of_face_of_convex(size_type ic, short_type f) const
Return a container of the (global) point number for face f or convex ic.
virtual void set_qdim(const bgeot::multi_index &mii)
Set the dimension for an arbitrary order tensor field.
dim_type get_qdim_m() const IS_DEPRECATED
for matrix fields, return the number of rows.
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! us...
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:95
rational_fraction< T > operator+(const polynomial< T > &P, const rational_fraction< T > &Q)
Add Q to P.
Definition: bgeot_poly.h:750
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
const REDUCTION_MATRIX & reduction_matrix() const
Return the reduction matrix applied to the dofs.
rational_fraction< T > operator-(const polynomial< T > &P, const rational_fraction< T > &Q)
Subtract Q from P.
Definition: bgeot_poly.h:757
const EXTENSION_MATRIX & extension_matrix() const
Return the extension matrix corresponding to reduction applied (RE=I).
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
virtual size_type nb_basic_dof() const
Return the total number of basic degrees of freedom (before the optional reduction).
virtual size_type nb_basic_dof_of_face_of_element(size_type cv, short_type f) const
Return the number of dof lying on the given convex face.
virtual dim_type get_qdim() const
Return the Q dimension.
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
Deal with interdependencies of objects.
GEneric Tool for Finite Element Methods.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
Describe a finite element method linked to a mesh.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
void set_auto_add(pfem pf)
Set the fem for automatic addition of element option.
Mesh structure definition.
Definition of the finite element methods.
virtual ind_dof_face_ct ind_basic_dof_of_face_of_element(size_type cv, short_type f) const
Give an array of the dof numbers lying of a convex face (all degrees of freedom whose associated base...
virtual void set_qdim(dim_type M, dim_type N)
Set the dimension for a matrix field.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const ind_cv_ct & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
void set_reduction(bool r)
Validate or invalidate the reduction (keeping the reduction matrices).
virtual void set_qdim(dim_type q)
Change the Q dimension.
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
const mesh_fem & classical_mesh_fem(const mesh &mesh, dim_type degree, dim_type qdim=1, bool complete=false)
Gives the descriptor of a classical finite element method of degree K on mesh.
void set_auto_add(dim_type K, bool disc=false, scalar_type alpha=scalar_type(0), bool complete=false)
Set the degree of the fem for automatic addition of element option.