Loading [MathJax]/extensions/tex2jax.js
Fluid structure interaction suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
boundary_conditions.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2022 by Luca Heltai
4 //
5 // This file is part of the FSI-suite platform, based on the deal.II library.
6 //
7 // The FSI-suite platform is free software; you can use it, redistribute it,
8 // and/or modify it under the terms of the GNU Lesser General Public License as
9 // published by the Free Software Foundation; either version 3.0 of the License,
10 // or (at your option) any later version. The full text of the license can be
11 // found in the file LICENSE at the top level of the FSI-suite platform
12 // distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef parsed_tools_boundary_conditions_h
17 #define parsed_tools_boundary_conditions_h
18 
21 
23 
24 #include <deal.II/fe/mapping.h>
25 
27 
29 
30 #ifdef DEAL_II_WITH_SYMENGINE
31 
32 # include "parsed_tools/components.h"
33 # include "parsed_tools/enum.h"
34 # include "parsed_tools/grid_info.h"
36 
37 namespace ParsedTools
38 {
43  {
44  dirichlet = 0, //< Dirichlet boundary condition
45  neumann = 1, //< Neumann boundary condition
46  first_dof = 2, //< First dof of first active cell on first processor is
47  // fixed to a given value
48  // robin = 2,
49  // dirichlet_nitsche = 3,
50  // neumann_nitsche = 4,
51  // robin_nitsche = 5,
52  // normal_dirichlet = 6,
53  };
54 
62  template <int spacedim>
63  class BoundaryConditions : public dealii::ParameterAcceptor
64  {
65  public:
70  const std::string &section_name = "",
71  const std::string &component_names = "u",
72  const std::vector<std::set<dealii::types::boundary_id>> &ids =
73  {{dealii::numbers::internal_face_boundary_id}},
74  const std::vector<std::string> &selected_components = {"u"},
75  const std::vector<BoundaryConditionType> &bc_type =
77  const std::vector<std::string> &expressions = {"0"});
78 
86  void
88  const dealii::Differentiation::SD::types::substitution_map
89  &substitution_map);
90 
99  void
101  const dealii::Differentiation::SD::types::substitution_map &arguments);
102 
107  void
108  set_time(const double &time);
109 
114  template <typename Tria>
115  void
116  check_consistency(const Tria &tria) const
117  {
118  grid_info.build_info(tria);
120  }
121 
126  void
127  check_consistency() const;
128 
133  template <int dim>
134  void
136  const dealii::DoFHandler<dim, spacedim> &dof_handler,
137  dealii::AffineConstraints<double> &constraints) const;
138 
143  template <int dim>
144  void
146  const dealii::Mapping<dim, spacedim> &mapping,
147  const dealii::DoFHandler<dim, spacedim> &dof_handler,
148  dealii::AffineConstraints<double> &constraints) const;
149 
161  template <int dim, typename MatrixType, typename VectorType>
162  void
164  const dealii::DoFHandler<dim, spacedim> &dof_handler,
165  const dealii::AffineConstraints<double> &constraints,
166  MatrixType &matrix,
167  VectorType &rhs) const;
168 
179  template <int dim, typename MatrixType, typename VectorType>
180  void
182  const dealii::Mapping<dim, spacedim> &mapping,
183  const dealii::DoFHandler<dim, spacedim> &dof_handler,
184  const dealii::AffineConstraints<double> &constraints,
185  MatrixType &matrix,
186  VectorType &rhs) const;
187 
193  std::set<dealii::types::boundary_id>
195 
201  std::set<dealii::types::boundary_id>
202  get_natural_boundary_ids() const;
203 
204  private:
208  const std::string component_names;
209 
213  const unsigned int n_components;
214 
218  mutable unsigned int n_boundary_conditions;
219 
223  std::vector<std::set<dealii::types::boundary_id>> ids;
224 
228  std::vector<std::string> selected_components;
229 
233  std::vector<BoundaryConditionType> bc_type;
234 
238  std::vector<std::string> expressions;
239 
243  std::vector<std::unique_ptr<dealii::Functions::SymbolicFunction<spacedim>>>
245 
249  std::vector<dealii::ComponentMask> masks;
250 
254  std::vector<Components::Type> types;
255 
256 
261  };
262 
263 
264 
265 # ifndef DOXYGEN
266  // Template implementations
267  template <int spacedim>
268  template <int dim, typename MatrixType, typename VectorType>
269  void
271  const dealii::Mapping<dim, spacedim> &mapping,
272  const dealii::DoFHandler<dim, spacedim> &dof_handler,
273  const dealii::AffineConstraints<double> &constraints,
274  MatrixType &matrix,
275  VectorType &rhs) const
276  {
277  for (unsigned int i = 0; i < n_boundary_conditions; ++i)
278  if (bc_type[i] == BoundaryConditionType::neumann)
279  {
280  const auto &neumann_ids = ids[i];
281  const auto &function = functions[i];
282  const auto &mask = masks[i];
283  const auto &type = types[i];
284  const auto &fe = dof_handler.get_fe();
285 
288  AssertThrow(false,
290  "Neumann boundary conditions for normal and "
291  "tangential components are not implemented yet."));
292 
293  const auto face_quadrature_formula =
294  Components::get_face_quadrature(dof_handler.get_triangulation(),
295  fe.tensor_degree() + 1);
296 
297  dealii::FEFaceValues<dim, spacedim> fe_face_values(
298  mapping,
299  fe,
300  face_quadrature_formula,
303 
304  const unsigned int dofs_per_cell = fe.n_dofs_per_cell();
305  dealii::FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
306 
307  dealii::Vector<double> cell_rhs(dofs_per_cell);
308 
309  std::vector<dealii::types::global_dof_index> local_dof_indices(
310  dofs_per_cell);
311  for (const auto &cell : dof_handler.active_cell_iterators())
312  if (cell->at_boundary() && cell->is_locally_owned())
313  {
314  cell_rhs = 0;
315  // for(const auto face: cell->face_indices())
316  for (const unsigned int f : cell->face_indices())
317  if (neumann_ids.find(cell->face(f)->boundary_id()) !=
318  neumann_ids.end())
319  {
320  fe_face_values.reinit(cell, f);
321  for (const unsigned int i : fe_face_values.dof_indices())
322  {
323  const auto comp_i =
324  fe.system_to_component_index(i).first;
325  if (mask[comp_i])
326  for (const unsigned int q_index :
327  fe_face_values.quadrature_point_indices())
328  cell_rhs(i) +=
329  fe_face_values.shape_value(i, q_index) *
330  function->value(fe_face_values.quadrature_point(
331  q_index),
332  comp_i) *
333  fe_face_values.JxW(q_index);
334  }
335  }
336  cell->get_dof_indices(local_dof_indices);
337  constraints.distribute_local_to_global(cell_rhs,
338  local_dof_indices,
339  rhs);
340  }
341  }
342  rhs.compress(dealii::VectorOperation::add);
343  (void)matrix;
344  }
345 
346 
347 
348  template <int spacedim>
349  template <int dim, typename MatrixType, typename VectorType>
350  void
352  const dealii::DoFHandler<dim, spacedim> &dof_handler,
353  const dealii::AffineConstraints<double> &constraints,
354  MatrixType &matrix,
355  VectorType &rhs) const
356  {
357  const auto &mapping =
358  get_default_linear_mapping(dof_handler.get_triangulation());
359  apply_natural_boundary_conditions(
360  mapping, dof_handler, constraints, matrix, rhs);
361  }
362 
363 
364 
365  template <int spacedim>
366  template <int dim>
367  void
369  const dealii::DoFHandler<dim, spacedim> &dof_handler,
370  dealii::AffineConstraints<double> &constraints) const
371  {
372  const auto &mapping =
373  get_default_linear_mapping(dof_handler.get_triangulation());
374  apply_essential_boundary_conditions(mapping, dof_handler, constraints);
375  }
376 
377 
378 
379  template <int spacedim>
380  template <int dim>
381  void
383  const dealii::Mapping<dim, spacedim> &mapping,
384  const dealii::DoFHandler<dim, spacedim> &dof_handler,
385  dealii::AffineConstraints<double> &constraints) const
386  {
387  // Take care of boundary conditions that don't need anything else than
388  // the constraints.
389  for (unsigned int i = 0; i < n_boundary_conditions; ++i)
390  {
391  const auto &boundary_ids = ids[i];
392  const auto &bc = bc_type[i];
393  const auto &function = functions[i];
394  const auto &mask = masks[i];
395  const auto &type = types[i];
396  std::map<dealii::types::boundary_id, const dealii::Function<spacedim> *>
397  fmap;
398 
399  if (boundary_ids.find(dealii::numbers::internal_face_boundary_id) !=
400  boundary_ids.end())
401  {
402  const auto all_ids =
403  dof_handler.get_triangulation().get_boundary_ids();
404  for (const auto &id : all_ids)
405  fmap[id] = function.get();
406  }
407  else
408  for (const auto &id : boundary_ids)
409  fmap[id] = function.get();
410 
411  // In this function, we only do Dirichlet boundary conditions.
412  switch (bc)
413  {
415  switch (type)
416  {
418  if constexpr (dim == spacedim && dim > 1)
421  dof_handler,
422  mask.first_selected_component(),
423  boundary_ids,
424  fmap,
425  constraints,
426  mapping);
427  else
428  AssertThrow(false,
430  "Cannot use normal "
431  "flux boundary conditions "
432  "for this dim and spacedim"));
433  break;
434  case Components::Type::tangential:
435  if constexpr (dim == spacedim && dim > 1)
438  dof_handler,
439  mask.first_selected_component(),
440  boundary_ids,
441  fmap,
442  constraints,
443  mapping);
444  else
445  AssertThrow(false,
447  "Cannot use tangential "
448  "flux boundary conditions "
449  "for this dim and spacedim"));
450  break;
451  default:
453  mapping, dof_handler, fmap, constraints, mask);
454  break;
455  }
456  break;
457  default:
458  // Nothing to do in this function call
459  break;
460  }
461  }
462  }
463 # endif
464 } // namespace ParsedTools
465 #endif
466 #endif
const std::string section_name
A wrapper for boundary conditions.
void set_time(const double &time)
Update time in each Functions::SymbolicFunction defined in this object.
std::vector< std::string > selected_components
Component on which to apply the boundary condition.
std::vector< BoundaryConditionType > bc_type
Type of boundary conditions.
const unsigned int n_components
Number of components of the problem.
GridInfo grid_info
Information about the grid this BC applies to.
void apply_natural_boundary_conditions(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, const AffineConstraints< double > &constraints, MatrixType &matrix, VectorType &rhs) const
Same as above for non standard mapping.
const std::string component_names
Component names of the boundary conditions.
void check_consistency() const
Make sure the specified boundary conditions make sense.
std::vector< Components::Type > types
Component types.
std::vector< std::string > expressions
Expressions for the boundary conditions.
std::vector< std::set< types::boundary_id > > ids
Ids on which this object applies boundary conditions.
void apply_essential_boundary_conditions(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< double > &constraints) const
Add essential boundary conditions computed with this object to the specified constraints.
BoundaryConditions(const std::string &section_name="", const std::string &component_names="u", const std::vector< std::set< types::boundary_id >> &ids={{numbers::internal_face_boundary_id}}, const std::vector< std::string > &selected_components={"u"}, const std::vector< BoundaryConditionType > &bc_type={BoundaryConditionType::dirichlet}, const std::vector< std::string > &expressions={"0"})
Constructor.
void apply_natural_boundary_conditions(const DoFHandler< dim, spacedim > &dof_handler, const AffineConstraints< double > &constraints, MatrixType &matrix, VectorType &rhs) const
Add natural boundary conditions computed with this object to the specified constraints,...
std::vector< std::unique_ptr< Functions::SymbolicFunction< spacedim > > > functions
The actual functions.
std::set< types::boundary_id > get_essential_boundary_ids() const
Get all ids where we impose essential boundary conditions.
void set_additional_function_arguments(const Differentiation::SD::types::substitution_map &arguments)
Call Functions::SymbolicFunction::set_additional_function_arguments() for every function defined in t...
unsigned int n_boundary_conditions
Number of boundary conditions.
void apply_essential_boundary_conditions(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< double > &constraints) const
Add the boundary conditions computed with this object to the specified constraints for non standard m...
std::vector< ComponentMask > masks
Component on which to apply the boundary condition.
std::set< types::boundary_id > get_natural_boundary_ids() const
Get all ids where we impose natural boundary conditions.
void update_user_substitution_map(const Differentiation::SD::types::substitution_map &substitution_map)
Update the substitition map of every Functions::SymbolicFunction defined in this object.
void check_consistency(const Tria &tria) const
Check that the grid is compatible with this boundary condition object, and that the boundary conditio...
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void interpolate_boundary_values(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const std::map< types::boundary_id, const Function< spacedim, number > * > &function_map, AffineConstraints< number > &constraints, const ComponentMask &component_mask={})
void compute_nonzero_normal_flux_constraints(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int first_vector_component, const std::set< types::boundary_id > &boundary_ids, const std::map< types::boundary_id, const Function< spacedim, double > * > &function_map, AffineConstraints< double > &constraints, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< dim, spacedim >()))
void compute_nonzero_tangential_flux_constraints(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int first_vector_component, const std::set< types::boundary_id > &boundary_ids, const std::map< types::boundary_id, const Function< spacedim, double > * > &function_map, AffineConstraints< double > &constraints, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< dim, spacedim >()))
update_values
update_JxW_values
update_quadrature_points
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Quadrature< dim - 1 > get_face_quadrature(const Triangulation< dim, spacedim > &tria, const unsigned int degree)
Return a Quadrature object that can be used on the given Triangulation faces.
Type
Enumerator used to identify patterns of components and their size in the a block system.
Definition: components.h:44
@ tangential
Tangential component of a vector.
@ normal
Normal component of a vector.
Type type(const std::string &component_name, const std::string &selected_component)
Return the component type for the given selected component.
Definition: components.cc:186
ComponentMask mask(const std::string &component_names, const std::string &selected_component)
Return a component mask corresponding to a given selected component, from a list of comma separated c...
Definition: components.cc:226
We collect in this namespace some wrappers around commonly used deal.II classes, derived from the Par...
BoundaryConditionType
Implemented boundary ids.
int(&) functions(const void *v1, const void *v2)
Gather information about a Triangulation.
Definition: grid_info.h:149
void build_info(const Triangulation< dim, spacedim > &tria)
Actually build the information about the Triangulation.
Definition: grid_info.h:183