GetFEM  5.4.3
getfem_mesh_slice.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2003-2020 Julien Pommier
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_slice.h
33  @author Julien Pommier <Julien.Pommier@insa-toulouse.fr>
34  @date May 2003.
35  @brief Define the class getfem::stored_mesh_slice.
36  */
37 #ifndef GETFEM_MESH_SLICE_H
38 #define GETFEM_MESH_SLICE_H
39 
40 #include "getfem_mesh_slicers.h"
41 
42 namespace getfem {
43  class slicer_build_stored_mesh_slice;
44 
45  /** The output of a getfem::mesh_slicer which has been recorded.
46  @see getfem::slicer_build_stored_mesh_slice */
48  protected:
49  /* nodes lists and simplexes lists for each convex of the original mesh */
50  struct convex_slice {
51  size_type cv_num;
52  dim_type cv_dim;
53  dim_type fcnt, cv_nbfaces; // number of faces of the convex
54  // (fcnt also counts the faces created by
55  // the slicing of the convex)
56  bool discont; // when true, it is assumed that the interpolated data
57  // inside the convex may be discontinuous
58  // (for ex. levelset discont function)
59  mesh_slicer::cs_nodes_ct nodes;
60  mesh_slicer::cs_simplexes_ct simplexes;
61  size_type global_points_count;
62  };
63  typedef std::deque<convex_slice> cvlst_ct;
64 
65  struct merged_node_t {
66  const slice_node *P;
67  unsigned pos; /* [0..nb_points()-1] */
68  };
69  /* these three arrays allow the association of a global point
70  number to a merged point number, and of a merged point to a
71  list of global points */
72  mutable std::vector<merged_node_t> merged_nodes; /* size = points_cnt */
73  mutable std::vector<size_type> merged_nodes_idx; /* size = merged pts + 1*/
74  mutable std::vector<size_type> to_merged_index; /* size = points_cnt */
75  mutable bool merged_nodes_available;
76 
77  /* keep track of the original mesh (hence it should not be destroyed
78  * before the slice) */
79  const mesh *poriginal_mesh;
80  std::vector<size_type> simplex_cnt; // count simplexes of dim 0,1,...,dim
81  size_type points_cnt;
82  cvlst_ct cvlst;
83  size_type dim_;
84  std::vector<size_type> cv2pos; // convex id -> pos in cvlst
85  friend class slicer_build_stored_mesh_slice;
86  friend class mesh_slicer;
87  public:
88  stored_mesh_slice() : poriginal_mesh(0), points_cnt(0), dim_(size_type(-1))
89  { }
90  /** Shortcut constructor to simplexify a mesh with refinement. */
91  explicit stored_mesh_slice(const getfem::mesh& m, size_type nrefine = 1)
92  : poriginal_mesh(0), points_cnt(0), dim_(size_type(-1)) {
93  this->build(m, slicer_none(), nrefine);
94  };
95  virtual ~stored_mesh_slice() {}
96  /** return the number of convexes of the original mesh referenced
97  in the slice */
98  size_type nb_convex() const { return cvlst.size(); }
99  /** return the original convex number of the 'ic'th convex
100  referenced in the slice */
101  size_type convex_num(size_type ic) const { return cvlst[ic].cv_num; }
102  /** return the position ic of the referenced convex in the slice convexes
103  list cvlist, corresponding to the original convex number cv*/
104  size_type convex_pos(size_type cv) const { return cv2pos[cv]; }
105  /** change the slice dimension (append zeros or truncate node coordinates..) */
106  void set_dim(size_type newdim);
107  /** return the slice dimension */
108  size_type dim() const { return dim_; }
109  /** return a pointer to the original mesh */
110  const mesh& linked_mesh() const { return *poriginal_mesh; }
111  /** return the simplex count, in an array.
112  @param c contains the number of simplexes of dimension 0, 1, ... dim().
113  */
114  void nb_simplexes(std::vector<size_type>& c) const { c = simplex_cnt; }
115  /** Return the number of simplexes of dimension sdim */
116  size_type nb_simplexes(size_type sdim) const { return simplex_cnt[sdim]; }
117  /** Return the number of nodes in the slice */
118  size_type nb_points() const { return points_cnt; }
119  /** Return the list of nodes for the 'ic'th convex of the slice. */
120  const mesh_slicer::cs_nodes_ct& nodes(size_type ic) const { return cvlst[ic].nodes; }
121  mesh_slicer::cs_nodes_ct& nodes(size_type ic) { return cvlst[ic].nodes; }
122 
123  /** Return the list of simplexes for the 'ic'th convex of the slice. */
124  const mesh_slicer::cs_simplexes_ct& simplexes(size_type ic) const { return cvlst[ic].simplexes; }
125  size_type memsize() const;
126  void clear() {
127  poriginal_mesh = 0;
128  cvlst.clear();
129  points_cnt = 0;
130  dim_ = size_type(-1);
131  gmm::fill(cv2pos, size_type(-1));
132  simplex_cnt.clear();
133  clear_merged_nodes();
134  }
135  /** @brief merge with another mesh slice. */
136  void merge(const stored_mesh_slice& sl);
137 
138  /** @brief build a list of merged nodes.
139 
140  build a list of merged nodes, i.e. nodes which have the same
141  geometrical location but were extracted from two different
142  convexes will be considered as one same node. Use for
143  exportation purposes, as VTK and OpenDX do not like
144  'discontinuous' meshes
145  */
146  void merge_nodes() const;
147 
148  /** @brief Return the number of merged nodes in slice. */
150  { return merged_nodes_idx.size() - 1; }
151 
152  /** @brief Return the physical position of the merged node.
153  @param i_merged should be 0 <= i_merged < nb_merged_nodes()
154  */
155  const base_node merged_point(size_type i_merged) const
156  { return merged_nodes[merged_nodes_idx[i_merged]].P->pt; }
157 
158  size_type merged_index(size_type ic, size_type ipt) const
159  { return to_merged_index[global_index(ic,ipt)]; }
160  size_type global_index(size_type ic, size_type ipt) const
161  { return cvlst[ic].global_points_count+ipt; }
162 
163  /** @brief Return the number of nodes that were merged
164  to form the merged one.
165  @param i_merged index of the merged node:
166  0 <= i_merged < nb_merged_nodes()
167  */
169  { return merged_nodes_idx[i_merged+1] - merged_nodes_idx[i_merged]; }
170 
171  std::vector<merged_node_t>::const_iterator
172  merged_point_nodes(size_type i_merged) const {
173  return merged_nodes.begin() + merged_nodes_idx[i_merged];
174  }
175 
176  void clear_merged_nodes() const;
177 
178  /** @brief Extract the list of mesh edges.
179 
180  extract the list of mesh edges into 'edges' (size = 2* number
181  of edges). 'slice_edges' indicates which one were created
182  after slicing. The from_merged_nodes flag may be used if you
183  want to use (and merge common edges according to) the merged
184  points
185  */
186  void get_edges(std::vector<size_type> &edges,
187  dal::bit_vector &slice_edges,
188  bool from_merged_nodes) const;
189 
190  void set_convex(size_type cv, bgeot::pconvex_ref cvr,
191  mesh_slicer::cs_nodes_ct cv_nodes,
192  mesh_slicer::cs_simplexes_ct cv_simplexes,
193  dim_type fcnt, const dal::bit_vector& splx_in,
194  bool discont);
195 
196  /** Build the slice, by applying a slicer_action operation. */
197  void build(const getfem::mesh& m, const slicer_action &a,
198  size_type nrefine = 1) { build(m,&a,0,0,nrefine); }
199  /** Build the slice, by applying two slicer_action operations. */
200  void build(const getfem::mesh& m, const slicer_action &a,
201  const slicer_action &b,
202  size_type nrefine = 1) { build(m,&a,&b,0,nrefine); }
203  /** Build the slice, by applying three slicer_action operations. */
204  void build(const getfem::mesh& m, const slicer_action &a,
205  const slicer_action &b, const slicer_action &c,
206  size_type nrefine = 1) { build(m,&a,&b,&c,nrefine); }
207  void build(const getfem::mesh& m, const slicer_action *a,
208  const slicer_action *b, const slicer_action *c,
209  size_type nrefine);
210 
211  /** @brief Apply the listed slicer_action(s) to the slice object.
212  the stored_mesh_slice is not modified. This can be used to build a
213  new stored_mesh_slice from a stored_mesh_slice.
214  */
215  void replay(slicer_action &a) const { replay(&a,0,0); }
216  void replay(slicer_action &a, slicer_action &b) const
217  { replay(&a, &b, 0); }
218  void replay(slicer_action &a, slicer_action &b, slicer_action &c) const
219  { replay(&a, &b, &c); }
220  void replay(slicer_action *a, slicer_action *b, slicer_action *c) const;
221 
222  /** @brief Save a slice content to a text file.
223  */
224  void write_to_file(std::ostream &os) const;
225  void write_to_file(const std::string &fname, bool with_mesh=false) const;
226  /** @brief Read a slice from a file.
227  */
228  void read_from_file(std::istream &ist, const getfem::mesh &m);
229  void read_from_file(const std::string &fname, const getfem::mesh &m);
230 
231 
232  /** @brief Interpolation of a mesh_fem on a slice.
233 
234  The mesh_fem and the slice must share the same mesh, of course.
235 
236  @param mf the mesh_fem
237 
238  @param U a vector whose dimension is a multiple of
239  mf.nb_dof(), the field to be interpolated.
240 
241  @param V on output, a vector corresponding to the interpolated
242  field on the slice (values given on each node of the slice).
243  */
244  template<typename V1, typename V2> void
245  interpolate(const getfem::mesh_fem &mf, const V1& UU, V2& V) const {
246  typedef typename gmm::linalg_traits<V2>::value_type T;
247  std::vector<base_node> refpts;
248  std::vector<std::vector<T> > coeff;
249  base_matrix G;
250  size_type qdim = mf.get_qdim();
251  size_type qqdim = gmm::vect_size(UU) / mf.nb_dof();
252  size_type pos = 0;
253  coeff.resize(qqdim);
254  std::vector<T> U(mf.nb_basic_dof()*qqdim);
255  mf.extend_vector(UU, U);
256 
257  gmm::clear(V);
258  for (size_type i=0; i < nb_convex(); ++i) {
259  size_type cv = convex_num(i);
260  refpts.resize(nodes(i).size());
261  for (size_type j=0; j < refpts.size(); ++j)
262  refpts[j] = nodes(i)[j].pt_ref;
263  if (!mf.convex_index().is_in(cv)) {
264  pos += refpts.size() * qdim * qqdim;
265  continue;
266  }
267 
268  pfem pf = mf.fem_of_element(cv);
269  if (pf->need_G())
270  bgeot::vectors_to_base_matrix(G,
271  mf.linked_mesh().points_of_convex(cv));
272  fem_precomp_pool fppool;
273  pfem_precomp pfp = fppool(pf, store_point_tab(refpts));
274 
275  mesh_fem::ind_dof_ct dof = mf.ind_basic_dof_of_element(cv);
276  for (size_type qq=0; qq < qqdim; ++qq) {
277  coeff[qq].resize(mf.nb_basic_dof_of_element(cv));
278  typename std::vector<T>::iterator cit = coeff[qq].begin();
279  for (mesh_fem::ind_dof_ct::const_iterator it=dof.begin();
280  it != dof.end(); ++it, ++cit)
281  *cit = U[(*it)*qqdim+qq];
282  }
283  fem_interpolation_context ctx(mf.linked_mesh().trans_of_convex(cv),
284  pfp, 0, G, cv, short_type(-1));
285  for (size_type j=0; j < refpts.size(); ++j) {
286  ctx.set_ii(j);
287  for (size_type qq = 0; qq < qqdim; ++qq) {
288  typename gmm::sub_vector_type<V2*,
289  gmm::sub_interval>::vector_type dest =
290  gmm::sub_vector(V,gmm::sub_interval(pos,qdim));
291  pf->interpolation(ctx,coeff[qq],dest,dim_type(qdim));
292  pos += qdim;
293  }
294  }
295  }
296  GMM_ASSERT1(pos == V.size(), "bad dimensions");
297  }
298  };
299 
300  /** @brief a getfem::mesh_slicer whose side effect is to build a
301  stored_mesh_slice object.
302  */
304  stored_mesh_slice &sl;
305  public:
307  GMM_ASSERT1(sl.cvlst.size() == 0,
308  "the stored_mesh_slice already contains data");
309  }
310  void exec(mesh_slicer& ms);
311  };
312 
313  std::ostream& operator<<(std::ostream& o, const stored_mesh_slice& m);
314 }
315 
316 #endif /*GETFEM_MESH_SLICE_H*/
void set_ii(size_type ii__)
change the current point (assuming a geotrans_precomp_ is used)
base class for static stored objects
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:750
handle a pool (i.e.
Definition: getfem_fem.h:717
Describe a finite element method linked to a mesh.
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
virtual dim_type get_qdim() const
Return the Q dimension.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
virtual size_type nb_basic_dof() const
Return the total number of basic degrees of freedom (before the optional reduction).
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.
virtual size_type nb_basic_dof_of_element(size_type cv) const
Return the number of degrees of freedom attached to a given convex.
Apply a serie a slicing operations to a mesh.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:99
void clear()
Erase the mesh.
Definition: getfem_mesh.cc:273
generic slicer class.
a getfem::mesh_slicer whose side effect is to build a stored_mesh_slice object.
This slicer does nothing.
The output of a getfem::mesh_slicer which has been recorded.
size_type convex_pos(size_type cv) const
return the position ic of the referenced convex in the slice convexes list cvlist,...
size_type merged_point_cnt(size_type i_merged) const
Return the number of nodes that were merged to form the merged one.
size_type dim() const
return the slice dimension
void nb_simplexes(std::vector< size_type > &c) const
return the simplex count, in an array.
void replay(slicer_action &a) const
Apply the listed slicer_action(s) to the slice object.
void build(const getfem::mesh &m, const slicer_action &a, const slicer_action &b, const slicer_action &c, size_type nrefine=1)
Build the slice, by applying three slicer_action operations.
const base_node merged_point(size_type i_merged) const
Return the physical position of the merged node.
void set_dim(size_type newdim)
change the slice dimension (append zeros or truncate node coordinates..)
const mesh_slicer::cs_nodes_ct & nodes(size_type ic) const
Return the list of nodes for the 'ic'th convex of the slice.
const mesh_slicer::cs_simplexes_ct & simplexes(size_type ic) const
Return the list of simplexes for the 'ic'th convex of the slice.
void build(const getfem::mesh &m, const slicer_action &a, const slicer_action &b, size_type nrefine=1)
Build the slice, by applying two slicer_action operations.
void merge(const stored_mesh_slice &sl)
merge with another mesh slice.
const mesh & linked_mesh() const
return a pointer to the original mesh
stored_mesh_slice(const getfem::mesh &m, size_type nrefine=1)
Shortcut constructor to simplexify a mesh with refinement.
void write_to_file(std::ostream &os) const
Save a slice content to a text file.
size_type nb_points() const
Return the number of nodes in the slice.
size_type nb_simplexes(size_type sdim) const
Return the number of simplexes of dimension sdim.
size_type nb_convex() const
return the number of convexes of the original mesh referenced in the slice
void read_from_file(std::istream &ist, const getfem::mesh &m)
Read a slice from a file.
void merge_nodes() const
build a list of merged nodes.
void get_edges(std::vector< size_type > &edges, dal::bit_vector &slice_edges, bool from_merged_nodes) const
Extract the list of mesh edges.
void interpolate(const getfem::mesh_fem &mf, const V1 &UU, V2 &V) const
Interpolation of a mesh_fem on a slice.
size_type nb_merged_nodes() const
Return the number of merged nodes in slice.
size_type convex_num(size_type ic) const
return the original convex number of the 'ic'th convex referenced in the slice
void build(const getfem::mesh &m, const slicer_action &a, size_type nrefine=1)
Build the slice, by applying a slicer_action operation.
Define various mesh slicers.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:244
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:73
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
GEneric Tool for Finite Element Methods.