GetFEM  5.5
getfem_convect.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2009-2026 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, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /**@file getfem_convect.h
32  @author Yves Renard <Yves.Renard@insa-lyon.fr>,
33  @date October 27, 2009.
34  @brief Compute the convection of a quantity with respect to a vector field.
35 */
36 #ifndef GETFEM_CONVECT_H__
37 #define GETFEM_CONVECT_H__
38 
39 #include "getfem_mesh_fem.h"
40 #include "getfem_interpolation.h"
41 #include "gmm/gmm_dense_qr.h"
42 
43 namespace getfem {
44 
45  enum convect_boundary_option { CONVECT_EXTRAPOLATION, CONVECT_UNCHANGED, CONVECT_PERIODICITY };
46 
47  /** Compute the convection of a quantity on a getfem::mesh_fem with respect
48  to a velocity field
49  @param mf the source mesh_fem. Should be of Lagrange type.
50  @param U the source field.
51  @param mf_v the mesh_fem on which the vector field is described
52  @param V contains the vector field described on mf_v.
53  @param nt number of time integration step.
54  @param option concerns the entrant boundary.
55  @param per_min, per_max : the periodicity box for the PERIODICITY option
56  */
57  template<class VECT1, class VECT2>
58  void convect(const mesh_fem &mf, VECT1 &U, const mesh_fem &mf_v,
59  const VECT2 &V, scalar_type dt, size_type nt,
60  convect_boundary_option option = CONVECT_EXTRAPOLATION,
61  const base_node &per_min = base_node(),
62  const base_node &per_max = base_node()) {
63  // Should be robustified on the boundaries -> control of the nodes going
64  // out the mesh.
65  // Should control that the point do not move to fast ( < h/2 for instance).
66  // Could be extended to non-lagragian fem with a projection (moving the
67  // gauss points).
68  // Can take into account a source term by integration on the
69  // characteristics.
70 
71  typedef typename gmm::linalg_traits<VECT1>::value_type T;
72  int extra = (option == CONVECT_EXTRAPOLATION) ? 2 : 0;
73 
74  if (nt == 0) return;
75 
76  GMM_ASSERT1(!(mf.is_reduced()),
77  "This convection algorithm work only on pure Lagrange fems");
78  /* test if mf is really of Lagrange type. */
79  for (dal::bv_visitor cv(mf.convex_index()); !cv.finished();++cv) {
80  pfem pf_t = mf.fem_of_element(cv);
81  GMM_ASSERT1(pf_t->target_dim() == 1 && pf_t->is_lagrange(),
82  "This convection algorithm work only on pure Lagrange fems");
83  }
84 
85  // Get the nodes of mf
86  const mesh &msh(mf.linked_mesh());
87  size_type N = msh.dim();
88  if (option == CONVECT_PERIODICITY)
89  GMM_ASSERT1(per_min.size() == N && per_max.size() == N,
90  "Wrong size of box extremity for PERIODICITY option");
91 
92  getfem::mesh_trans_inv mti(msh, 1E-10);
93  size_type qdim = mf.get_qdim();
94  size_type nbpts = mf.nb_basic_dof() / qdim;
95  std::vector<base_node> nodes(nbpts);
96  for (size_type i = 0; i < nbpts; ++i)
97  nodes[i] = mf.point_of_basic_dof(i * qdim);
98 
99  // Obtain the first interpolation of v (same mesh)
100  size_type qqdimt = (gmm::vect_size(V) / mf_v.nb_dof()) * mf_v.get_qdim();
101  GMM_ASSERT1(qqdimt == N, "The velocity field should be a vector field "
102  "of the same dimension as the mesh");
103  std::vector<T> VI(nbpts*N);
104  getfem::interpolation(mf_v, mf, V, VI);
105 
106  // Convect the nodes with respect to v
107  scalar_type ddt = dt / scalar_type(nt);
108  for (size_type i = 0; i < nt; ++i) {
109  if (i > 0) {
110  mti.clear();
111  mti.add_points(nodes);
112  gmm::clear(VI);
113  dal::bit_vector dof_untouched;
114  interpolation(mf_v, mti, V, VI, extra, &dof_untouched);
115  for (dal::bv_visitor j(dof_untouched); !j.finished();++j)
116  VI[j] = V[j];
117  }
118 
119  for (size_type j = 0; j < nbpts; ++j) {
120  gmm::add(gmm::scaled(gmm::sub_vector(VI, gmm::sub_interval(N*j, N)),
121  -ddt), nodes[j]);
122  if (option == CONVECT_PERIODICITY) {
123  for (size_type k = 0; k < N; ++k)
124  if (per_max[k] > per_min[k]) {
125  while (nodes[j][k] > per_max[k]) nodes[j][k] -= per_max[k];
126  while (nodes[j][k] < per_min[k]) nodes[j][k] += per_max[k];
127  }
128  }
129  }
130  }
131 
132  // 3 final interpolation
133  std::vector<T> UI(nbpts*qdim);
134  mti.clear();
135  mti.add_points(nodes);
136  dal::bit_vector dof_untouched;
137  interpolation(mf, mti, U, UI, extra, &dof_untouched);
138  for (dal::bv_visitor i(dof_untouched); !i.finished();++i)
139  UI[i] = U[i];
140  gmm::copy(UI, U);
141  }
142 
143 
144 }
145 
146 
147 #endif
Describe a finite element method linked to a mesh.
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 base_node point_of_basic_dof(size_type cv, size_type i) const
Return the geometrical location of a degree of freedom.
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.
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
Interpolation of fields from a mesh_fem onto another.
Define the getfem::mesh_fem class.
Dense QR factorization.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:243
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
GEneric Tool for Finite Element Methods.
void convect(const mesh_fem &mf, VECT1 &U, const mesh_fem &mf_v, const VECT2 &V, scalar_type dt, size_type nt, convect_boundary_option option=CONVECT_EXTRAPOLATION, const base_node &per_min=base_node(), const base_node &per_max=base_node())
Compute the convection of a quantity on a getfem::mesh_fem with respect to a velocity field.
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.