Fluid structure interaction suite
linear_problem.cc
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 
17 #include "pdes/linear_problem.h"
18 
21 
23 
24 #include <deal.II/fe/fe_tools.h>
25 
27 
28 #include "lac.h"
29 #include "lac_initializer.h"
30 
31 using namespace dealii;
32 
34 
35 namespace PDEs
36 {
37  template <int dim, int spacedim, class LacType>
39  const std::string &component_names,
40  const std::string &problem_name)
41  : ParameterAcceptor(problem_name == "" ? "" : "/" + problem_name)
42  , component_names(component_names)
43  , n_components(ParsedTools::Components::n_components(component_names))
44  , problem_name(problem_name)
45  , section_name(problem_name == "" ? "" : "/" + problem_name)
46  , mpi_communicator(MPI_COMM_WORLD)
47  , mpi_rank(Utilities::MPI::this_mpi_process(mpi_communicator))
48  , mpi_size(Utilities::MPI::n_mpi_processes(mpi_communicator))
49  , pcout(std::cout, mpi_rank == 0)
50  , timer(pcout, TimerOutput::summary, TimerOutput::cpu_and_wall_times)
51  , evolution_type(EvolutionType::steady_state)
52  , grid_generator(section_name + "/Grid")
53  , grid_refinement(section_name + "/Grid/Refinement",
54  1,
56  "kelly",
57  0.3,
58  0.1,
59  0,
60  0,
61  0,
62  {{"custom", [&](auto &v) { custom_estimator(v); }}})
63  , triangulation(mpi_communicator)
64  // typename Triangulation<dim, spacedim>::MeshSmoothing(
65  // Triangulation<dim, spacedim>::smoothing_on_refinement |
66  // Triangulation<dim, spacedim>::smoothing_on_coarsening))
67  , finite_element(section_name,
68  component_names,
69  "FESystem[FE_Q(1)^" + std::to_string(n_components) + "]")
70  , dof_handler(triangulation)
71  , inverse_operator(section_name + "/Solver/System")
72  , preconditioner(section_name + "/Solver/System AMG preconditioner")
73  , mass_inverse_operator(section_name + "/Solver/Mass")
74  , mass_preconditioner(section_name + "/Solver/Mass AMG preconditioner")
75  , forcing_term(section_name + "/Functions",
76  join(std::vector<std::string>(n_components, "0"), ";"),
77  "Forcing term")
78  , exact_solution(section_name + "/Functions",
79  join(std::vector<std::string>(n_components, "0"), ";"),
80  "Exact solution")
81  , initial_value(section_name + "/Functions",
82  join(std::vector<std::string>(n_components, "0"), ";"),
83  "Initial value")
84  , boundary_conditions(section_name + "/Boundary conditions",
85  component_names,
87  {"all"},
89  {join(std::vector<std::string>(n_components, "0"),
90  ";")})
91  , error_table(section_name + "/Error",
92  Utilities::split_string_list(component_names),
93  std::vector<std::set<VectorTools::NormType>>(
94  ParsedTools::Components::n_blocks(component_names),
96  , data_out(section_name + "/Output")
97  , ark_ode_data(section_name + "/ARKode")
98  {
99  add_parameter("n_threads",
100  number_of_threads,
101  "Fix number of threads during the execution");
102  add_parameter("verbosity",
103  verbosity_level,
104  "Verbosity level used with deallog");
105  add_parameter("evolution type",
106  evolution_type,
107  "The type of time evolution to use in the linear problem.");
108  enter_subsection("Quasi-static");
109  add_parameter("start time", start_time, "Start time of the simulation");
110  add_parameter("end time", end_time, "End time of the simulation");
111  add_parameter("initial time step",
112  desired_start_step_size,
113  "Initial time step of the simulation");
114  leave_subsection();
115 
116  advance_time_call_back.connect(
117  [&](const auto &time, const auto &, const auto &) {
118  boundary_conditions.set_time(time);
119  forcing_term.set_time(time);
120  exact_solution.set_time(time);
121  });
122  }
123 
124 
125 
126  template <int dim, int spacedim, class LacType>
127  void
129  {
130  TimerOutput::Scope timer_section(timer, "setup_system");
131  if (mpi_rank == 0)
132  deallog.depth_console(verbosity_level);
133  else
135 
136  deallog << "System setup " << std::endl;
137  const auto ref_cells = triangulation.get_reference_cells();
138  AssertThrow(
139  ref_cells.size() == 1,
141  "This program does nots support mixed simplex/hex grid types."));
142 
143  // Compatible FE space and grid.
144  AssertThrow(finite_element().reference_cell() == ref_cells[0],
145  ExcMessage("The finite element must be defined on the same "
146  "cell type as the grid."));
147 
148  dof_handler.distribute_dofs(finite_element);
149 
150  // Since our code runs both for simplex grids and for hyper-cube grids, we
151  // need to make sure that we build the correct mapping for the grid. In
152  // this code we actually use a linear mapping, independently on the order
153  // of the finite element space.
154  mapping = get_default_linear_mapping(triangulation).clone();
155 
156  const auto [block_names, block_multiplicities] =
158 
159  const auto blocks =
160  ParsedTools::Components::block_indices(component_names, component_names);
161  // renumber dofs in a blockwise manner.
162  DoFRenumbering::component_wise(dof_handler, blocks);
163  dofs_per_block = DoFTools::count_dofs_per_fe_block(dof_handler, blocks);
164 
165  locally_owned_dofs =
166  dof_handler.locally_owned_dofs().split_by_block(dofs_per_block);
167 
168  IndexSet non_blocked_locally_relevant_dofs;
170  non_blocked_locally_relevant_dofs);
171  locally_relevant_dofs =
172  non_blocked_locally_relevant_dofs.split_by_block(dofs_per_block);
173 
174  deallog << "Number of degrees of freedom [total / ("
175  << Patterns::Tools::to_string(block_names) << ")] : ["
176  << dof_handler.n_dofs() << " / ("
177  << Patterns::Tools::to_string(dofs_per_block) << ")]" << std::endl;
178 
179  constraints.clear();
180  constraints.reinit(non_blocked_locally_relevant_dofs);
181  DoFTools::make_hanging_node_constraints(dof_handler, constraints);
182 
183  // We now check that the boundary conditions are consistent with the
184  // triangulation object, that is, we check that the boundary indicators
185  // specified in the parameter file are actually present in the
186  // triangulation, that no boundary indicator is specified twice, and that
187  // all boundary ids of the triangulation are actually covered by the
188  // parameter file configuration.
189  boundary_conditions.check_consistency(triangulation);
190 
191  // This is where we apply essential boundary conditions. The
192  // ParsedTools::BoundaryConditions class takes care of collecting boundary
193  // ids, and calling the appropriate function to apply the boundary
194  // condition on the selected boundary ids. Essential boundary conditions
195  // need to be incorporated in the constraints of the linear system, since
196  // they are part of the definition of the solution space.
197  //
198  // Natural bondary conditions, on the other hand, need access to the rhs
199  // of the problem and are not treated via constraints. We will deal with
200  // them later on.
201  boundary_conditions.apply_essential_boundary_conditions(dof_handler,
202  constraints);
203 
204  // If necessary, derived functions can add constraints to the system here.
205  add_constraints_call_back();
206  constraints.close();
207 
208  LAC::BlockInitializer initializer(dofs_per_block,
209  locally_owned_dofs,
210  locally_relevant_dofs,
211  mpi_communicator);
212 
214  for (unsigned int i = 0; i < n_components; ++i)
215  for (unsigned int j = 0; j < n_components; ++j)
216  coupling[i][j] = DoFTools::always;
217  initializer(sparsity, dof_handler, constraints, coupling);
218  initializer(sparsity, matrix);
219  if (evolution_type == EvolutionType::transient)
220  initializer(sparsity, mass_matrix);
221 
222  initializer(solution);
223  initializer(rhs);
224  initializer.ghosted(locally_relevant_solution);
225 
226  error_per_cell.reinit(triangulation.n_active_cells());
227 
228  boundary_conditions.apply_natural_boundary_conditions(
229  *mapping, dof_handler, constraints, matrix, rhs);
230  // Update functions with standard constants
231  exact_solution.update_constants({});
232  forcing_term.update_constants({});
233 
234  // Setup the quadrature formulas
236  triangulation, finite_element().tensor_degree() + 1);
237 
239  triangulation, finite_element().tensor_degree() + 1);
240 
241  // Now call anything else that may be needed from the user side
242  setup_system_call_back();
243  }
244 
245 
246 
247  template <int dim, int spacedim, class LacType>
248  void
251  ScratchData &,
252  CopyData &)
253  {
254  Assert(false, ExcPureFunctionCalled());
255  }
256 
257 
258 
259  template <int dim, int spacedim, class LacType>
260  void
262  dealii::Vector<float> &) const
263  {
264  Assert(false, ExcPureFunctionCalled());
265  }
266 
267 
268 
269  template <int dim, int spacedim, class LacType>
270  void
272  {
273  constraints.distribute_local_to_global(copy.matrices[0],
274  copy.vectors[0],
275  copy.local_dof_indices[0],
276  matrix,
277  rhs);
278  }
279 
280 
281 
282  template <int dim, int spacedim, class LacType>
283  void
285  {
286  TimerOutput::Scope timer_section(timer, "assemble_system");
287 
288  ScratchData scratch(*mapping,
289  finite_element(),
290  cell_quadrature,
293  face_quadrature,
296 
297  CopyData copy(finite_element().n_dofs_per_cell());
298 
299  auto worker = [&](const auto &cell, auto &scratch, auto &copy) {
300  assemble_system_one_cell(cell, scratch, copy);
301  };
302 
303  auto copier = [&](const auto &copy) { copy_one_cell(copy); };
304 
305  using CellFilter = FilteredIterator<
307 
309  dof_handler.begin_active()),
311  dof_handler.end()),
312  worker,
313  copier,
314  scratch,
315  copy);
316 
317  matrix.compress(VectorOperation::add);
318  rhs.compress(VectorOperation::add);
319 
320  // We assemble the mass matrix only in the transient case
321  if (evolution_type == EvolutionType::transient)
322  {
323  // Assemble also the mass matrix.
324  ScratchData scratch(*mapping,
325  finite_element(),
326  cell_quadrature,
328 
329  CopyData copy(finite_element().n_dofs_per_cell());
330 
331  auto worker = [&](const auto &cell, auto &scratch, auto &copy) {
332  const auto &fev = scratch.reinit(cell);
333  copy.matrices[0] = 0;
334  cell->get_dof_indices(copy.local_dof_indices[0]);
335  for (const auto &q : fev.quadrature_point_indices())
336  for (const auto &i : fev.dof_indices())
337  for (const auto &j : fev.dof_indices())
338  if (finite_element().system_to_component_index(i).first ==
339  finite_element().system_to_component_index(j).first)
340  copy.matrices[0](i, j) +=
341  fev.shape_value(i, q) * fev.shape_value(j, q) * fev.JxW(q);
342  };
343 
344  auto copier = [&](const auto &copy) {
345  constraints.distribute_local_to_global(copy.matrices[0],
346  copy.local_dof_indices[0],
347  mass_matrix);
348  };
349 
350  using CellFilter = FilteredIterator<
352 
354  dof_handler.begin_active()),
356  dof_handler.end()),
357  worker,
358  copier,
359  scratch,
360  copy);
361  mass_matrix.compress(VectorOperation::add);
362  }
363 
364  assemble_system_call_back();
365  }
366 
367 
368 
369  template <int dim, int spacedim, class LacType>
370  void
372  {
373  Assert(false, ExcPureFunctionCalled());
374  }
375 
376 
377 
378  template <int dim, int spacedim, class LacType>
379  void
381  Vector<float> &error_per_cell) const
382  {
383  TimerOutput::Scope timer_section(timer, "estimate");
384  grid_refinement.estimate_error(*mapping,
385  dof_handler,
386  locally_relevant_solution,
387  error_per_cell);
388 
389  error_table.error_from_exact(*mapping,
390  dof_handler,
391  locally_relevant_solution,
392  exact_solution);
393  }
394 
395 
396 
397  template <int dim, int spacedim, class LacType>
398  void
400  const Vector<float> &error_per_cell)
401  {
402  TimerOutput::Scope timer_section(timer, "mark");
403  grid_refinement.mark_cells(error_per_cell, triangulation);
404  }
405 
406 
407 
408  template <int dim, int spacedim, class LacType>
409  void
411  {
412  TimerOutput::Scope timer_section(timer, "refine");
413  // Cells have been marked in the mark() method.
414  triangulation.execute_coarsening_and_refinement();
415  }
416 
417 
418 
419  template <int dim, int spacedim, class LacType>
420  void
422  const unsigned cycle) const
423  {
424  TimerOutput::Scope timer_section(timer, "output_results");
425  deallog << "Output results (" << component_names << ")" << std::endl;
426  // Save each cycle in its own file
427  const auto suffix =
430  grid_refinement.get_n_refinement_cycles()));
431  data_out.attach_dof_handler(dof_handler, suffix);
432  data_out.add_data_vector(locally_relevant_solution,
433  component_names,
434  dealii::DataOut<dim, spacedim>::type_dof_data);
435  // call any additional call backs
436  add_data_vector(data_out);
437  data_out.write_data_and_clear(*mapping);
438 
439  output_results_call_back();
440  }
441 
442 
443 
444  template <int dim, int spacedim, class LacType>
445  void
447  {
448  if (number_of_threads != -1 && number_of_threads > 0)
450  static_cast<unsigned int>(number_of_threads));
451 
452  deallog << "Running " << problem_name << std::endl
453  << "Number of cores : " << MultithreadInfo::n_cores()
454  << std::endl
455  << "Number of threads : " << MultithreadInfo::n_threads()
456  << std::endl
457  << "Number of MPI processes : " << mpi_size << std::endl
458  << "MPI rank of this process: " << mpi_rank << std::endl;
459 
460  AssertThrow((lac_is_dealii && mpi_size == 1) || (lac_is_dealii == false),
461  ExcMessage("deal.II LAC only works in serial"));
462  }
463 
464 
465 
466  template <int dim, int spacedim, class LacType>
467  void
469  {
470  switch (evolution_type)
471  {
473  run_steady_state();
474  break;
476  run_quasi_static();
477  break;
479  run_transient();
480  break;
481  default:
482  Assert(false, ExcNotImplemented());
483  }
484  }
485 
486 
487 
488  template <int dim, int spacedim, class LacType>
489  void
491  {
492  print_system_info();
493  deallog << "Solving quasi-static problem" << std::endl;
494  grid_generator.generate(triangulation);
495  DiscreteTime time(start_time, end_time, desired_start_step_size);
496  unsigned int output_cycle = 0;
497  while (time.is_at_end() == false)
498  {
499  const auto cycle = time.get_step_number();
500  const auto t = time.get_current_time();
501  const auto dt = time.get_next_step_size();
502  deallog << "Timestep " << cycle << ", current time = " << t
503  << " , step size = " << dt << std::endl;
504 
505  advance_time_call_back(t, dt, cycle);
506 
507  setup_system();
508  // Before actually solving, output the current solution if required
509  if (cycle % output_frequency == 0)
510  output_results(output_cycle++);
511 
512  assemble_system();
513  solve();
514  time.advance_time();
515  // Check if we need to output one last time
516  if (time.is_at_end())
517  {
518  advance_time_call_back(time.get_current_time(),
519  time.get_previous_step_size(),
520  time.get_step_number());
521  if (time.get_step_number() % output_frequency == 0)
522  output_results(output_cycle++);
523  }
524  }
525  }
526 
527 
528 
529  template <int dim, int spacedim, class LacType>
530  void
532  {
533  arkode.output_step =
534  [&](const double, const auto &vector, const auto step) {
535  locally_relevant_solution = vector;
536  output_results(step);
537  };
538 
539  arkode.implicit_function = [&](const double t, const auto &y, auto &res) {
540  deallog << "Evaluation at time " << t << std::endl;
541  advance_time_call_back(t, 0.0, 0);
542  matrix.vmult(res, y);
543  res.sadd(-1.0, 1.0, rhs);
544  return 0;
545  };
546 
547  arkode.mass_times_vector = [&](const double, const auto &src, auto &dst) {
548  mass_matrix.vmult(dst, src);
549  return 0;
550  };
551 
552 
553  arkode.jacobian_times_vector =
554  [&](const auto &v, auto &Jv, double, const auto &, const auto &) {
555  matrix.vmult(Jv, v);
556  Jv *= -1.0;
557  return 0;
558  };
559 
560 
561  arkode.solve_mass =
562  [&](auto &op, auto &prec, auto &dst, const auto &src, double tol) -> int {
563  try
564  {
565  deallog << "Solving mass system" << std::endl;
566  mass_inverse_operator.solve(op, prec, src, dst, tol);
567  return 0;
568  }
569  catch (...)
570  {
571  return 1;
572  }
573  };
574 
575  arkode.solve_linearized_system =
576  [&](auto &op, auto &prec, auto &dst, const auto &src, double tol) -> int {
577  try
578  {
579  deallog << "Solving linearized system" << std::endl;
580  inverse_operator.solve(op, prec, src, dst, tol);
581  return 0;
582  }
583  catch (...)
584  {
585  return 1;
586  }
587  };
588  }
589 
590 
591 
592  template <int dim, int spacedim, class LacType>
593  void
595  {
596  print_system_info();
597  deallog << "Solving transient problem" << std::endl;
598  grid_generator.generate(triangulation);
599  setup_system();
600  assemble_system();
601 
602  VectorTools::interpolate(*mapping, dof_handler, initial_value, solution);
603 
604  ARKode arkode(ark_ode_data, mpi_communicator);
605  setup_transient(arkode);
606  setup_arkode_call_back(arkode);
607 
608  // Just start the solver.
609  auto res = arkode.solve_ode(solution);
610 
611  // Check the result.
612  AssertThrow(res != 0,
613  ExcMessage("ARKode solver failed with error code " +
614  std::to_string(res)));
615  }
616 
617 
618 
619  template <int dim, int spacedim, class LacType>
620  void
622  {
623  print_system_info();
624  deallog << "Solving steady state problem" << std::endl;
625  grid_generator.generate(triangulation);
626  for (const auto &cycle : grid_refinement.get_refinement_cycles())
627  {
628  deallog << "Cycle " << cycle << std::endl;
629  setup_system();
630  assemble_system();
631  solve();
632  estimate(error_per_cell);
633  output_results(cycle);
634  if (cycle < grid_refinement.get_n_refinement_cycles() - 1)
635  {
636  mark(error_per_cell);
637  refine();
638  }
639  }
640  if (this->mpi_rank == 0)
641  error_table.output_table(std::cout);
642  }
643 
644  template class LinearProblem<1, 1, LAC::LAdealii>;
645  template class LinearProblem<1, 2, LAC::LAdealii>;
646  template class LinearProblem<1, 3, LAC::LAdealii>;
647  template class LinearProblem<2, 2, LAC::LAdealii>;
648  template class LinearProblem<2, 3, LAC::LAdealii>;
649  template class LinearProblem<3, 3, LAC::LAdealii>;
650 
651  template class LinearProblem<1, 1, LAC::LAPETSc>;
652  template class LinearProblem<1, 2, LAC::LAPETSc>;
653  template class LinearProblem<1, 3, LAC::LAPETSc>;
654  template class LinearProblem<2, 2, LAC::LAPETSc>;
655  template class LinearProblem<2, 3, LAC::LAPETSc>;
656  template class LinearProblem<3, 3, LAC::LAPETSc>;
657 
664 } // namespace PDEs
double get_next_step_size() const
unsigned int get_step_number() const
bool is_at_end() const
double get_current_time() const
double get_previous_step_size() const
void advance_time()
std::vector< IndexSet > split_by_block(const std::vector< types::global_dof_index > &n_indices_per_block) const
unsigned int depth_console(const unsigned int n)
static unsigned int n_cores()
static unsigned int n_threads()
static void set_thread_limit(const unsigned int max_threads=numbers::invalid_unsigned_int)
General class, used to initialize different types of block vectors, block atrices and block sparsity ...
Construct a LinearProblem.
void run_steady_state()
Solve a steady state problem.
virtual void run()
Main entry point of the problem.
void refine()
Refine the grid.
virtual void setup_system()
Initial setup: distribute degrees of freedom, make all vectors and matrices of the right size,...
virtual void output_results(const unsigned cycle) const
Output the solution and the grid in a format that can be read by Paraview or Visit.
virtual void assemble_system()
Actually loop over cells, and assemble the global system.
virtual void print_system_info() const
print some information about the current processes/mpi/ranks/etc.
void run_quasi_static()
Solve a quasi static problem.
virtual void copy_one_cell(const CopyData &copy)
Distribute the data that has been assembled by assemble_system_on_cell() to the global matrix and rhs...
virtual void custom_estimator(Vector< float > &error_per_cell) const
Overload this function to use a custom error estimator in the mesh refinement process.
virtual void setup_transient(ARKode &arkode)
Setup the transient problem.
virtual void solve()
Solve the global system.
virtual void assemble_system_one_cell(const typename DoFHandler< dim, spacedim >::active_cell_iterator &cell, ScratchData &scratch, CopyData &copy)
Assemble the local system matrix on cell, using scratch for FEValues and other expensive scratch obje...
void run_transient()
Solve a dynamic problem.
virtual void estimate(Vector< float > &error_per_cell) const
Perform a posteriori error estimation, and store the results in the error_per_cell vector.
typename SUNDIALS::ARKode< typename LacType::BlockVector > ARKode
SUNDIALS time integrator.
void mark(const Vector< float > &error_per_cell)
According to the chosen strategy, mark some cells for refinement, possibily using the error_per_cell ...
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcPureFunctionCalled()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
update_values
update_JxW_values
update_gradients
update_quadrature_points
LogStream deallog
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
void component_wise(DoFHandler< dim, spacedim > &dof_handler, const std::vector< unsigned int > &target_component=std::vector< unsigned int >())
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
std::vector< types::global_dof_index > count_dofs_per_fe_block(const DoFHandler< dim, spacedim > &dof, const std::vector< unsigned int > &target_block=std::vector< unsigned int >())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
std::string to_string(const T &t)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
unsigned int needed_digits(const unsigned int max_number)
void interpolate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Function< spacedim, typename VectorType::value_type > &function, VectorType &vec, const ComponentMask &component_mask={})
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
We collect in this namespace all PDEs that are relevant to Fluid Structure Interaction Problems.
EvolutionType
Describe the dependencies of the linear problem w.r.t.
std::pair< std::vector< std::string >, std::vector< unsigned int > > names_to_blocks(const std::string &component_names)
Build block names and multiplicities from component names.
Definition: components.cc:56
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.
unsigned int n_blocks(const std::string &component_names)
Count the number of components in the given list of comma separated components.
Definition: components.cc:217
std::vector< unsigned int > block_indices(const std::string &component_names, const std::string &selected_components)
Return the indices within the block corresponding to the given selected components,...
Definition: components.cc:134
Quadrature< dim > get_cell_quadrature(const Triangulation< dim, spacedim > &tria, const unsigned int degree)
Return a Quadrature object that can be used on the given Triangulation cells.
std::string join(const Container &strings, const std::string &separator)
Join strings in a container together using a given separator.
unsigned int n_components(const std::string &component_names)
Count the number of components in the given list of comma separated components.
Definition: components.cc:32
We collect in this namespace some wrappers around commonly used deal.II classes, derived from the Par...
RefinementStrategy
Refinement strategy implemented in the GridRefinement class.
const types::boundary_id internal_face_boundary_id
STL namespace.
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation