The finite element method using deal.II - 2021/2022
step-40.cc
Go to the documentation of this file.
1 /* ---------------------------------------------------------------------
2  *
3  * Copyright (C) 2009 - 2020 by the deal.II authors
4  *
5  * This file is part of the deal.II library.
6  *
7  * The deal.II library is free software; you can use it, redistribute
8  * it, and/or modify it under the terms of the GNU Lesser General
9  * Public License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  * The full text of the license can be found in the file LICENSE.md at
12  * the top level directory of deal.II.
13  *
14  * ---------------------------------------------------------------------
15 
16  *
17  * Author: Wolfgang Bangerth, Texas A&M University, 2009, 2010
18  * Timo Heister, University of Goettingen, 2009, 2010
19  */
20 
21 
22 #include <deal.II/base/function.h>
24 #include <deal.II/base/timer.h>
25 
27 
28 namespace LA
29 {
30 #if defined(DEAL_II_WITH_PETSC) && !defined(DEAL_II_PETSC_WITH_COMPLEX) && \
31  !(defined(DEAL_II_WITH_TRILINOS) && defined(FORCE_USE_OF_TRILINOS))
32  using namespace dealii::LinearAlgebraPETSc;
33 # define USE_PETSC_LA
34 #elif defined(DEAL_II_WITH_TRILINOS)
35  using namespace dealii::LinearAlgebraTrilinos;
36 #else
37 # error DEAL_II_WITH_PETSC or DEAL_II_WITH_TRILINOS required
38 #endif
39 } // namespace LA
40 
41 
43 #include <deal.II/base/index_set.h>
44 #include <deal.II/base/utilities.h>
45 
48 
50 #include <deal.II/dofs/dof_tools.h>
51 
52 #include <deal.II/fe/fe_q.h>
53 #include <deal.II/fe/fe_values.h>
54 
56 
60 #include <deal.II/lac/solver_cg.h>
62 #include <deal.II/lac/vector.h>
63 
67 
68 #include <fstream>
69 #include <iostream>
70 
71 namespace Step40
72 {
73  using namespace dealii;
74 
75 
76  template <int dim>
78  {
79  public:
81 
82  void
83  run();
84 
85  private:
86  void
87  setup_system();
88  void
89  assemble_system();
90  void
91  solve();
92  void
93  refine_grid();
94  void
95  output_results(const unsigned int cycle) const;
96 
97  MPI_Comm mpi_communicator;
98 
100 
103 
106 
108 
112 
115  };
116 
117 
118 
119  template <int dim>
121  : mpi_communicator(MPI_COMM_WORLD)
122  , triangulation(mpi_communicator,
123  typename Triangulation<dim>::MeshSmoothing(
124  Triangulation<dim>::smoothing_on_refinement |
125  Triangulation<dim>::smoothing_on_coarsening))
126  , fe(2)
127  , dof_handler(triangulation)
128  , pcout(std::cout,
129  (Utilities::MPI::this_mpi_process(mpi_communicator) == 0))
130  , computing_timer(mpi_communicator,
131  pcout,
132  TimerOutput::summary,
133  TimerOutput::wall_times)
134  {}
135 
136 
137 
138  template <int dim>
139  void
141  {
142  TimerOutput::Scope t(computing_timer, "setup");
143 
144  dof_handler.distribute_dofs(fe);
145 
146  locally_owned_dofs = dof_handler.locally_owned_dofs();
147  DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
148 
149  locally_relevant_solution.reinit(locally_owned_dofs,
150  locally_relevant_dofs,
151  mpi_communicator);
152  system_rhs.reinit(locally_owned_dofs, mpi_communicator);
153 
154  constraints.clear();
155  constraints.reinit(locally_relevant_dofs);
158  0,
160  constraints);
161  constraints.close();
162 
163  DynamicSparsityPattern dsp(locally_relevant_dofs);
164 
165  DoFTools::make_sparsity_pattern(dof_handler, dsp, constraints, false);
167  dof_handler.locally_owned_dofs(),
168  mpi_communicator,
169  locally_relevant_dofs);
170 
171  system_matrix.reinit(locally_owned_dofs,
172  locally_owned_dofs,
173  dsp,
174  mpi_communicator);
175  }
176 
177 
178 
179  template <int dim>
180  void
182  {
183  TimerOutput::Scope t(computing_timer, "assembly");
184 
185  const QGauss<dim> quadrature_formula(fe.degree + 1);
186 
187  FEValues<dim> fe_values(fe,
188  quadrature_formula,
191 
192  const unsigned int dofs_per_cell = fe.n_dofs_per_cell();
193  const unsigned int n_q_points = quadrature_formula.size();
194 
195  FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
196  Vector<double> cell_rhs(dofs_per_cell);
197 
198  std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
199 
200  for (const auto &cell : dof_handler.active_cell_iterators())
201  if (cell->is_locally_owned())
202  {
203  cell_matrix = 0.;
204  cell_rhs = 0.;
205 
206  fe_values.reinit(cell);
207 
208  for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
209  {
210  const double rhs_value =
211  (fe_values.quadrature_point(q_point)[1] >
212  0.5 +
213  0.25 * std::sin(4.0 * numbers::PI *
214  fe_values.quadrature_point(q_point)[0]) ?
215  1. :
216  -1.);
217 
218  for (unsigned int i = 0; i < dofs_per_cell; ++i)
219  {
220  for (unsigned int j = 0; j < dofs_per_cell; ++j)
221  cell_matrix(i, j) += fe_values.shape_grad(i, q_point) *
222  fe_values.shape_grad(j, q_point) *
223  fe_values.JxW(q_point);
224 
225  cell_rhs(i) += rhs_value * fe_values.shape_value(i, q_point) *
226  fe_values.JxW(q_point);
227  }
228  }
229 
230  cell->get_dof_indices(local_dof_indices);
232  cell_rhs,
234  system_matrix,
235  system_rhs);
236  }
237 
238  system_matrix.compress(VectorOperation::add);
239  system_rhs.compress(VectorOperation::add);
240  }
241 
242 
243 
244  template <int dim>
245  void
247  {
248  TimerOutput::Scope t(computing_timer, "solve");
249  LA::MPI::Vector completely_distributed_solution(locally_owned_dofs,
250  mpi_communicator);
251 
252  SolverControl solver_control(dof_handler.n_dofs(), 1e-12);
253 
254 #ifdef USE_PETSC_LA
255  LA::SolverCG solver(solver_control, mpi_communicator);
256 #else
257  LA::SolverCG solver(solver_control);
258 #endif
259 
260  LA::MPI::PreconditionAMG preconditioner;
261 
263 
264 #ifdef USE_PETSC_LA
265  data.symmetric_operator = true;
266 #else
267  /* Trilinos defaults are good */
268 #endif
269  preconditioner.initialize(system_matrix, data);
270 
271  solver.solve(system_matrix,
272  completely_distributed_solution,
273  system_rhs,
275 
276  pcout << " Solved in " << solver_control.last_step() << " iterations."
277  << std::endl;
278 
279  constraints.distribute(completely_distributed_solution);
280 
281  locally_relevant_solution = completely_distributed_solution;
282  }
283 
284 
285 
286  template <int dim>
287  void
289  {
290  TimerOutput::Scope t(computing_timer, "refine");
291 
292  Vector<float> estimated_error_per_cell(triangulation.n_active_cells());
294  dof_handler,
295  QGauss<dim - 1>(fe.degree + 1),
296  std::map<types::boundary_id, const Function<dim> *>(),
297  locally_relevant_solution,
298  estimated_error_per_cell);
300  triangulation, estimated_error_per_cell, 0.3, 0.03);
301  triangulation.execute_coarsening_and_refinement();
302  }
303 
304 
305 
306  template <int dim>
307  void
308  LaplaceProblem<dim>::output_results(const unsigned int cycle) const
309  {
310  DataOut<dim> data_out;
311  data_out.attach_dof_handler(dof_handler);
312  data_out.add_data_vector(locally_relevant_solution, "u");
313 
314  Vector<float> subdomain(triangulation.n_active_cells());
315  for (unsigned int i = 0; i < subdomain.size(); ++i)
316  subdomain(i) = triangulation.locally_owned_subdomain();
317  data_out.add_data_vector(subdomain, "subdomain");
318 
319  data_out.build_patches();
320 
322  "./", "solution", cycle, mpi_communicator, 2, 8);
323  }
324 
325 
326 
327  template <int dim>
328  void
330  {
331  pcout << "Running with "
332 #ifdef USE_PETSC_LA
333  << "PETSc"
334 #else
335  << "Trilinos"
336 #endif
337  << " on " << Utilities::MPI::n_mpi_processes(mpi_communicator)
338  << " MPI rank(s)..." << std::endl;
339 
340  const unsigned int n_cycles = 8;
341  for (unsigned int cycle = 0; cycle < n_cycles; ++cycle)
342  {
343  pcout << "Cycle " << cycle << ':' << std::endl;
344 
345  if (cycle == 0)
346  {
348  triangulation.refine_global(5);
349  }
350  else
351  refine_grid();
352 
353  setup_system();
354 
355  pcout << " Number of active cells: "
356  << triangulation.n_global_active_cells() << std::endl
357  << " Number of degrees of freedom: " << dof_handler.n_dofs()
358  << std::endl;
359 
360  assemble_system();
361  solve();
362 
363  if (Utilities::MPI::n_mpi_processes(mpi_communicator) <= 32)
364  {
365  TimerOutput::Scope t(computing_timer, "output");
366  output_results(cycle);
367  }
368 
369  computing_timer.print_summary();
370  computing_timer.reset();
371 
372  pcout << std::endl;
373  }
374  }
375 } // namespace Step40
376 
377 
378 
379 int
380 main(int argc, char *argv[])
381 {
382  try
383  {
384  using namespace dealii;
385  using namespace Step40;
386 
387  Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
388 
389  LaplaceProblem<2> laplace_problem_2d;
390  laplace_problem_2d.run();
391  }
392  catch (std::exception &exc)
393  {
394  std::cerr << std::endl
395  << std::endl
396  << "----------------------------------------------------"
397  << std::endl;
398  std::cerr << "Exception on processing: " << std::endl
399  << exc.what() << std::endl
400  << "Aborting!" << std::endl
401  << "----------------------------------------------------"
402  << std::endl;
403 
404  return 1;
405  }
406  catch (...)
407  {
408  std::cerr << std::endl
409  << std::endl
410  << "----------------------------------------------------"
411  << std::endl;
412  std::cerr << "Unknown exception!" << std::endl
413  << "Aborting!" << std::endl
414  << "----------------------------------------------------"
415  << std::endl;
416  return 1;
417  }
418 
419  return 0;
420 }
FEValues::shape_value
const double & shape_value(const unsigned int function_no, const unsigned int point_no) const
LA
Definition: poisson.h:66
Step40::LaplaceProblem::locally_relevant_solution
LA::MPI::Vector locally_relevant_solution
Definition: step-40.cc:110
Step40::LaplaceProblem::refine_grid
void refine_grid()
Definition: step-40.cc:288
local_dof_indices
std::vector< types::global_dof_index > local_dof_indices
cycle
unsigned int cycle
FEValues::reinit
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, level_dof_access >> &cell)
tria.h
dynamic_sparsity_pattern.h
triangulation
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
Vector
Vector< double > Vector
update_quadrature_points
update_quadrature_points
Step40::LaplaceProblem::constraints
AffineConstraints< double > constraints
Definition: step-40.cc:107
TimerOutput
FE_Q< dim >
SolverControl
dealii
Step40::LaplaceProblem::assemble_system
void assemble_system()
Definition: step-40.cc:181
grid_generator.h
data
Table< 2, float > data
parallel::distributed::GridRefinement::refine_and_coarsen_fixed_number
void refine_and_coarsen_fixed_number(parallel::distributed::Triangulation< dim, spacedim > &tria, const ::Vector< Number > &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const types::global_cell_index max_n_cells=std::numeric_limits< types::global_cell_index >::max())
Step40::LaplaceProblem::fe
FE_Q< dim > fe
Definition: step-40.cc:101
utilities.h
Step40::LaplaceProblem::dof_handler
DoFHandler< dim > dof_handler
Definition: step-40.cc:102
Step40::LaplaceProblem
Definition: step-40.cc:77
error_estimator.h
Step40::LaplaceProblem::run
void run()
Definition: step-40.cc:329
VectorOperation::add
add
e
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
DataOut::write_vtu_with_pvtu_record
std::string write_vtu_with_pvtu_record(const std::string &directory, const std::string &filename_without_extension, const unsigned int counter, const MPI_Comm &mpi_communicator, const unsigned int n_digits_for_counter=numbers::invalid_unsigned_int, const unsigned int n_groups=0) const
conditional_ostream.h
types::boundary_id
unsigned int boundary_id
Vector::size
size_type size() const
Step40::LaplaceProblem::solve
void solve()
Definition: step-40.cc:246
cell_matrix
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double >> &velocity, const double factor=1.)
update_values
update_values
SparseMatrix
friend friend class SparseMatrix
constraints
AffineConstraints< double > constraints
DataOut::attach_dof_handler
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
DoFHandler< dim >
Step40::LaplaceProblem::system_rhs
LA::MPI::Vector system_rhs
Definition: step-40.cc:111
fe_values.h
function.h
Step40::LaplaceProblem::setup_system
void setup_system()
Definition: step-40.cc:140
DoFTools::make_hanging_node_constraints
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
SolverControl::last_step
unsigned int last_step() const
FEValues< dim >
Triangulation
n_cycles
unsigned int n_cycles
main
int main(int argc, char *argv[])
Definition: step-40.cc:380
AffineConstraints< double >::distribute_local_to_global
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
FEValues::shape_grad
const Tensor< 1, spacedim > & shape_grad(const unsigned int function_no, const unsigned int quadrature_point) const
KellyErrorEstimator::estimate
static void estimate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim - 1 > &quadrature, const std::map< types::boundary_id, const Function< spacedim, typename InputVector::value_type > * > &neumann_bc, const InputVector &solution, Vector< float > &error, const ComponentMask &component_mask=ComponentMask(), const Function< spacedim > *coefficients=nullptr, const unsigned int n_threads=numbers::invalid_unsigned_int, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id, const types::material_id material_id=numbers::invalid_material_id, const Strategy strategy=cell_diameter_over_24)
DoFTools::make_sparsity_pattern
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternType &sparsity_pattern, const AffineConstraints< number > &constraints=AffineConstraints< number >(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
AdditionalData
typename BaseClass::AdditionalData AdditionalData
vector_tools.h
generic_linear_algebra.h
Step40::LaplaceProblem::locally_relevant_dofs
IndexSet locally_relevant_dofs
Definition: step-40.cc:105
DataOut::build_patches
virtual void build_patches(const unsigned int n_subdivisions=0)
update_gradients
update_gradients
DoFTools::extract_locally_relevant_dofs
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
run
virtual void run(ParameterHandler &prm)=0
parallel::distributed::Triangulation< dim >
Step40::LaplaceProblem::locally_owned_dofs
IndexSet locally_owned_dofs
Definition: step-40.cc:104
DynamicSparsityPattern
VectorTools::interpolate_boundary_values
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, std::map< types::global_dof_index, number > &boundary_values, const ComponentMask &component_mask=ComponentMask())
FEValues::JxW
double JxW(const unsigned int quadrature_point) const
data_out.h
IndexSet
AffineConstraints< double >::reinit
void reinit(const IndexSet &local_constraints=IndexSet())
timer.h
QGauss
fe_q.h
AffineConstraints< double >
update_JxW_values
update_JxW_values
AffineConstraints< double >::distribute
void distribute(VectorType &vec) const
affine_constraints.h
Step40::LaplaceProblem::output_results
void output_results(const unsigned int cycle) const
Definition: step-40.cc:308
AffineConstraints< double >::clear
void clear()
dof_tools.h
Step40::LaplaceProblem::computing_timer
TimerOutput computing_timer
Definition: step-40.cc:114
this_mpi_process
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
GridGenerator::hyper_cube
void hyper_cube(Triangulation< dim, spacedim > &tria, const double left=0., const double right=1., const bool colorize=false)
DataOut::add_data_vector
void add_data_vector(const VectorType &data, const std::vector< std::string > &names, const DataVectorType type=type_automatic, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretation={})
Utilities::MPI::n_mpi_processes
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
sparsity_tools.h
grid_refinement.h
ConditionalOStream
SparsityTools::distribute_sparsity_pattern
void distribute_sparsity_pattern(DynamicSparsityPattern &dsp, const IndexSet &locally_owned_rows, const MPI_Comm &mpi_comm, const IndexSet &locally_relevant_rows)
Functions::ZeroFunction
FEValues::quadrature_point
const Point< spacedim > & quadrature_point(const unsigned int q) const
QGauss::size
unsigned int size() const
FullMatrix< double >
Function< dim >
Step40::LaplaceProblem::pcout
ConditionalOStream pcout
Definition: step-40.cc:113
full_matrix.h
DataOut< dim >
numbers::PI
static constexpr double PI
dof_handler.h
Vector< double >
Step40::LaplaceProblem::triangulation
parallel::distributed::Triangulation< dim > triangulation
Definition: step-40.cc:99
vector.h
solver_cg.h
AffineConstraints< double >::close
void close()
Utilities
quadrature_lib.h
preconditioner
std::shared_ptr< PreconditionerType > preconditioner
Step40::LaplaceProblem::mpi_communicator
MPI_Comm mpi_communicator
Definition: step-40.cc:97
Step40
Definition: step-40.cc:71
Utilities::MPI::MPI_InitFinalize
Step40::LaplaceProblem::system_matrix
LA::MPI::SparseMatrix system_matrix
Definition: step-40.cc:109
index_set.h