Fluid structure interaction suite
poisson.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 #include "pdes/mpi/poisson.h"
17 
19 
20 using namespace dealii;
21 
22 namespace PDEs
23 {
24  namespace MPI
25  {
26  template <int dim, int spacedim>
28  : LinearProblem<dim, spacedim, LAC::LATrilinos>("u", "Poisson")
29  , coefficient("/Poisson/Functions", "1", "Diffusion coefficient")
30  {}
31 
32 
33 
34  template <int dim, int spacedim>
35  void
38  ScratchData &scratch,
39  CopyData &copy)
40  {
41  auto &cell_matrix = copy.matrices[0];
42  auto &cell_rhs = copy.vectors[0];
43 
44  cell->get_dof_indices(copy.local_dof_indices[0]);
45 
46  const auto &fe_values = scratch.reinit(cell);
47  cell_matrix = 0;
48  cell_rhs = 0;
49 
50  for (const unsigned int q_index : fe_values.quadrature_point_indices())
51  {
52  for (const unsigned int i : fe_values.dof_indices())
53  for (const unsigned int j : fe_values.dof_indices())
54  cell_matrix(i, j) +=
55  (coefficient.value(
56  fe_values.quadrature_point(q_index)) * // a(x_q)
57  fe_values.shape_grad(i, q_index) * // grad phi_i(x_q)
58  fe_values.shape_grad(j, q_index) * // grad phi_j(x_q)
59  fe_values.JxW(q_index)); // dx
60  for (const unsigned int i : fe_values.dof_indices())
61  cell_rhs(i) += (fe_values.shape_value(i, q_index) * // phi_i(x_q)
62  this->forcing_term.value(
63  fe_values.quadrature_point(q_index)) * // f(x_q)
64  fe_values.JxW(q_index)); // dx
65  }
66  }
67 
68 
69 
70  template <int dim, int spacedim>
71  void
73  {
74  TimerOutput::Scope timer_section(this->timer, "solve");
75  const auto A = linear_operator<VectorType>(this->matrix.block(0, 0));
76  this->preconditioner.initialize(this->matrix.block(0, 0));
77  const auto Ainv = this->inverse_operator(A, this->preconditioner);
78  this->solution.block(0) = Ainv * this->rhs.block(0);
79  this->constraints.distribute(this->solution);
80  this->locally_relevant_solution = this->solution;
81  }
82 
83 
84 
85  template <int dim, int spacedim>
86  void
88  dealii::Vector<float> &error_per_cell) const
89  {
90  TimerOutput::Scope timer_section(this->timer, "custom_estimator");
91  error_per_cell = 0;
92  Quadrature<dim> quadrature_formula =
94  this->triangulation, this->finite_element().tensor_degree() + 1);
95 
96  Quadrature<dim - 1> face_quadrature_formula =
98  this->triangulation, this->finite_element().tensor_degree() + 1);
99 
100  ScratchData scratch(*this->mapping,
101  this->finite_element(),
102  quadrature_formula,
105  face_quadrature_formula,
108 
109  // A copy data for error estimators for each cell. We store the indices of
110  // the cells, and the values of the error estimator to be added to the
111  // cell indicators.
112  struct MyCopyData
113  {
114  std::vector<unsigned int> cell_indices;
115  std::vector<float> indicators;
116  };
117 
118  MyCopyData copy;
119 
120  // I will use this FEValuesExtractor to leverage the capabilities of the
121  // ScratchData
122  FEValuesExtractors::Scalar scalar(0);
123 
124  // This is called in each cell
125  auto cell_worker = [&](const auto &cell, auto &scratch, auto &copy) {
126  const auto &fe_v = scratch.reinit(cell);
127  const auto H = cell->diameter();
128 
129  // Reset the copy data
130  copy.cell_indices.resize(0);
131  copy.indicators.resize(0);
132 
133  // Save the index of this cell
134  copy.cell_indices.emplace_back(cell->active_cell_index());
135 
136  // At every call of this function, a new vector of dof values is
137  // generated and stored internally, so that you can later call
138  // scratch.get_values(...)
139  scratch.extract_local_dof_values("solution",
140  this->locally_relevant_solution);
141 
142  // Get the values of the solution at the quadrature points
143  const auto &lap_u = scratch.get_laplacians("solution", scalar);
144 
145  // Points and weights of the quadrature formula
146  const auto &q_points = scratch.get_quadrature_points();
147  const auto &JxW = scratch.get_JxW_values();
148 
149  // Reset vectors
150  float cell_indicator = 0;
151 
152  // Now store the values of the residual square in the copy data
153  for (const auto q_index : fe_v.quadrature_point_indices())
154  {
155  const auto res =
156  lap_u[q_index] + this->forcing_term.value(q_points[q_index]);
157 
158  cell_indicator += (H * H * res * res * JxW[q_index]); // dx
159  }
160  copy.indicators.emplace_back(cell_indicator);
161  };
162 
163  // This is called in each face, refined or not.
164  auto face_worker = [&](const auto &cell,
165  const auto &f,
166  const auto &sf,
167  const auto &ncell,
168  const auto &nf,
169  const auto &nsf,
170  auto &scratch,
171  auto &copy) {
172  // Here we intialize the inteface values
173  const auto &fe_iv = scratch.reinit(cell, f, sf, ncell, nf, nsf);
174 
175  const auto h = cell->face(f)->diameter();
176 
177  // Add this cell to the copy data
178  copy.cell_indices.emplace_back(cell->active_cell_index());
179 
180  // Same as before. Extract local dof values of the solution
181  scratch.extract_local_dof_values("solution",
182  this->locally_relevant_solution);
183 
184  // ...so that we can call scratch.get_(...)
185  const auto jump_grad =
186  scratch.get_jumps_in_gradients("solution", scalar);
187 
188  const auto &JxW = scratch.get_JxW_values();
189  const auto &normals = scratch.get_normal_vectors();
190 
191  // Now store the values of the gradient jump in the copy data
192  float face_indicator = 0;
193  for (const auto q_index : fe_iv.quadrature_point_indices())
194  {
195  const auto J = jump_grad[q_index] * normals[q_index];
196 
197  face_indicator += (h * J * J * JxW[q_index]); // dx
198  }
199  copy.indicators.emplace_back(face_indicator);
200  };
201 
202 
203  auto copier = [&](const auto &copy) {
204  AssertDimension(copy.cell_indices.size(), copy.indicators.size());
205  for (unsigned int i = 0; i < copy.cell_indices.size(); ++i)
206  {
207  error_per_cell[copy.cell_indices[i]] += copy.indicators[i];
208  }
209  };
210 
211  using CellFilter = FilteredIterator<
213 
214  MeshWorker::mesh_loop(this->dof_handler.begin_active(),
215  this->dof_handler.end(),
216  cell_worker,
217  copier,
218  scratch,
219  copy,
222  {},
223  face_worker);
224 
225  // Collect errors from the other processors
226  const double total_error =
227  Utilities::MPI::sum(this->error_per_cell.l1_norm(),
228  this->mpi_communicator);
229 
230  deallog << "Error estimator: " << total_error << std::endl;
231  }
232 
233 
234  template class Poisson<2, 2>;
235  template class Poisson<2, 3>;
236  template class Poisson<3, 3>;
237  } // namespace MPI
238 } // namespace PDEs
void reinit(const Triangulation< dim, spacedim > &tria)
Construct a LinearProblem.
Solve the Poisson problem, in parallel.
Definition: poisson.h:31
typename LinearProblem< dim, spacedim, LAC::LATrilinos >::ScratchData ScratchData
Definition: poisson.h:51
virtual void custom_estimator(Vector< float > &error_per_cell) const override
Build a custom error estimator.
Definition: poisson.cc:87
virtual void solve() override
Make sure we initialize the right type of linear solver.
Definition: poisson.cc:72
virtual void assemble_system_one_cell(const typename DoFHandler< dim, spacedim >::active_cell_iterator &cell, ScratchData &scratch, CopyData &copy) override
Explicitly assemble the Poisson problem on a single cell.
Definition: poisson.cc:36
typename LinearProblem< dim, spacedim, LAC::LATrilinos >::CopyData CopyData
Definition: poisson.h:54
#define AssertDimension(dim1, dim2)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
void mesh_loop(const CellIteratorType &begin, const CellIteratorType &end, const CellWorkerFunctionType &cell_worker, const CopierType &copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const AssembleFlags flags=assemble_own_cells, const BoundaryWorkerFunctionType &boundary_worker=BoundaryWorkerFunctionType(), const FaceWorkerFunctionType &face_worker=FaceWorkerFunctionType(), const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
update_hessians
update_normal_vectors
update_JxW_values
update_gradients
update_quadrature_points
LogStream deallog
assemble_own_interior_faces_both
T sum(const T &t, const MPI_Comm mpi_communicator)
Wrappers for linear algebra classes.
Definition: lac.h:62
We collect in this namespace all PDEs that are relevant to Fluid Structure Interaction Problems.
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.
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.
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation