/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/FEM/assembler/cg.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/FEM/assembler/cg.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
cg.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <sstream>
5
6// DiFfRG
12
13namespace DiFfRG
14{
15 namespace CG
16 {
17 using namespace dealii;
18 using std::array;
19
20 template <typename... T> auto fe_tie(T &&...t)
21 {
22 return named_tuple<std::tuple<T &...>, StringSet<"fe_functions", "fe_derivatives", "fe_hessians", "extractors",
23 "variables", "cell_width">>(std::tie(t...));
24 }
25
26 template <typename... T> auto i_tie(T &&...t)
27 {
28 return named_tuple<std::tuple<T &...>, StringSet<"fe_functions", "fe_derivatives", "fe_hessians">>(
29 std::tie(t...));
30 }
31
32 namespace internal
33 {
40 template <typename Discretization> struct ScratchData {
41 static constexpr uint dim = Discretization::dim;
43
44 ScratchData(const Mapping<dim> &mapping, const FiniteElement<dim> &fe,
45 const dealii::Quadrature<dim> &quadrature, const dealii::Quadrature<dim - 1> &quadrature_face,
46 const UpdateFlags update_flags = update_values | update_gradients | update_quadrature_points |
47 update_JxW_values | update_hessians,
48 const UpdateFlags interface_update_flags = update_values | update_gradients |
49 update_quadrature_points | update_JxW_values |
50 update_normal_vectors | update_hessians)
51 : n_components(fe.n_components()), fe_values(mapping, fe, quadrature, update_flags),
52 fe_interface_values(mapping, fe, quadrature_face, interface_update_flags)
53 {
54 solution.resize(quadrature.size(), Vector<NumberType>(n_components));
55 solution_grad.resize(quadrature.size(), std::vector<Tensor<1, dim, NumberType>>(n_components));
56 solution_hess.resize(quadrature.size(), std::vector<Tensor<2, dim, NumberType>>(n_components));
57 solution_dot.resize(quadrature.size(), Vector<NumberType>(n_components));
58 solution_interface[0].resize(quadrature_face.size(), Vector<NumberType>(n_components));
59 solution_interface[1].resize(quadrature_face.size(), Vector<NumberType>(n_components));
60 solution_grad_interface[0].resize(quadrature_face.size(),
61 std::vector<Tensor<1, dim, NumberType>>(n_components));
62 solution_grad_interface[1].resize(quadrature_face.size(),
63 std::vector<Tensor<1, dim, NumberType>>(n_components));
64 solution_hess_interface[0].resize(quadrature_face.size(),
65 std::vector<Tensor<2, dim, NumberType>>(n_components));
66 solution_hess_interface[1].resize(quadrature_face.size(),
67 std::vector<Tensor<2, dim, NumberType>>(n_components));
68 const uint n_dofs = fe.n_dofs_per_cell();
69 comp.resize(n_dofs);
70 cached_shape_values.resize(n_dofs);
71 cached_shape_grads.resize(n_dofs);
72 cached_shape_hessians.resize(n_dofs);
73 }
74
76 : n_components(scratch_data.fe_values.get_fe().n_components()),
77 fe_values(scratch_data.fe_values.get_mapping(), scratch_data.fe_values.get_fe(),
78 scratch_data.fe_values.get_quadrature(), scratch_data.fe_values.get_update_flags()),
79 fe_interface_values(scratch_data.fe_interface_values.get_mapping(),
80 scratch_data.fe_interface_values.get_fe(),
81 scratch_data.fe_interface_values.get_quadrature(),
82 scratch_data.fe_interface_values.get_update_flags())
83 {
84 const uint q_size = scratch_data.fe_values.get_quadrature().size();
85 const uint q_face_size = scratch_data.fe_interface_values.get_quadrature().size();
86
87 solution.resize(q_size, Vector<NumberType>(n_components));
88 solution_grad.resize(q_size, std::vector<Tensor<1, dim, NumberType>>(n_components));
89 solution_hess.resize(q_size, std::vector<Tensor<2, dim, NumberType>>(n_components));
90 solution_dot.resize(q_size, Vector<NumberType>(n_components));
91 solution_interface[0].resize(q_face_size, Vector<NumberType>(n_components));
92 solution_interface[1].resize(q_face_size, Vector<NumberType>(n_components));
93 solution_grad_interface[0].resize(q_face_size, std::vector<Tensor<1, dim, NumberType>>(n_components));
94 solution_grad_interface[1].resize(q_face_size, std::vector<Tensor<1, dim, NumberType>>(n_components));
95 solution_hess_interface[0].resize(q_face_size, std::vector<Tensor<2, dim, NumberType>>(n_components));
96 solution_hess_interface[1].resize(q_face_size, std::vector<Tensor<2, dim, NumberType>>(n_components));
97 const uint n_dofs_copy = scratch_data.comp.size();
98 comp.resize(n_dofs_copy);
99 cached_shape_values.resize(n_dofs_copy);
100 cached_shape_grads.resize(n_dofs_copy);
101 cached_shape_hessians.resize(n_dofs_copy);
102 }
103
105
106 FEValues<dim> fe_values;
107 FEInterfaceValues<dim> fe_interface_values;
108
109 std::vector<Vector<NumberType>> solution;
110 std::vector<std::vector<Tensor<1, dim, NumberType>>> solution_grad;
111 std::vector<std::vector<Tensor<2, dim, NumberType>>> solution_hess;
112 std::vector<Vector<NumberType>> solution_dot;
113 array<std::vector<Vector<NumberType>>, 2> solution_interface;
114 array<std::vector<std::vector<Tensor<1, dim, NumberType>>>, 2> solution_grad_interface;
115 array<std::vector<std::vector<Tensor<2, dim, NumberType>>>, 2> solution_hess_interface;
116
117 std::vector<uint> comp;
118
119 // Cached per-DoF shape function data for jacobian assembly
120 std::vector<double> cached_shape_values;
121 std::vector<Tensor<1, dim>> cached_shape_grads;
122 std::vector<Tensor<2, dim>> cached_shape_hessians;
123 };
124
125 template <typename NumberType> struct CopyData_R {
126 Vector<NumberType> cell_residual;
127 std::vector<types::global_dof_index> local_dof_indices;
128
129 template <class Iterator> void reinit(const Iterator &cell, uint dofs_per_cell)
130 {
131 cell_residual.reinit(dofs_per_cell);
132 local_dof_indices.resize(dofs_per_cell);
133 cell->get_dof_indices(local_dof_indices);
134 }
135 };
136
137 template <typename NumberType> struct CopyData_J {
138 FullMatrix<NumberType> cell_jacobian;
139 FullMatrix<NumberType> extractor_cell_jacobian;
140 std::vector<types::global_dof_index> local_dof_indices;
141
142 template <class Iterator> void reinit(const Iterator &cell, uint dofs_per_cell, uint n_extractors)
143 {
144 cell_jacobian.reinit(dofs_per_cell, dofs_per_cell);
145 if (n_extractors > 0) extractor_cell_jacobian.reinit(dofs_per_cell, n_extractors);
146 local_dof_indices.resize(dofs_per_cell);
147 cell->get_dof_indices(local_dof_indices);
148 }
149 };
150
151 template <typename NumberType> struct CopyData_I {
153 std::array<uint, 2> cell_indices;
154 std::array<double, 2> values;
155 };
156 std::vector<CopyFaceData_I> face_data;
157 double value = 0.;
159 };
160 } // namespace internal
161
167 template <typename Discretization_,
169 class Assembler : public FEMAssembler<Discretization_, Model_>
170 {
172
173 public:
174 using Discretization = Discretization_;
175 using Model = Model_;
179
181 static constexpr uint dim = Discretization::dim;
184 quadrature(fe.degree + 1 + config.get_uint("/discretization/overintegration", 0)),
185 quadrature_face(fe.degree + 1 + config.get_uint("/discretization/overintegration", 0))
186 {
187 static_assert(Components::count_fe_subsystems() == 1, "A CG model cannot have multiple submodels!");
188 reinit();
189 }
190
191 virtual void reinit_vector(VectorType &vec) const override
192 {
193 reinit_la_vector(vec, discretization.get_locally_owned_dofs(), discretization.get_communicator());
194 }
195 virtual void reinit_matrix(SparseMatrixType &matrix) const override
196 {
197 reinit_la_matrix(matrix, get_sparsity_pattern_jacobian(), discretization.get_locally_owned_dofs(),
198 discretization.get_communicator());
199 }
200
201 virtual MPI_Comm get_communicator() const override { return discretization.get_communicator(); }
202 virtual void reinit_solution_view(SolutionView<VectorType> &view) const override
203 {
204 view.reinit(discretization.get_locally_owned_dofs(), discretization.get_locally_relevant_dofs(),
205 discretization.get_communicator());
206 }
207
208 virtual void reinit() override
209 {
210 Timer timer;
211
212 Base::reinit();
213
214 // Mass sparsity pattern
215 {
216 DynamicSparsityPattern dsp(discretization.get_locally_relevant_dofs());
217 DoFTools::make_sparsity_pattern(dof_handler, dsp, discretization.get_constraints(),
218 /*keep_constrained_dofs = */ true);
220 discretization.get_locally_relevant_dofs(),
221 discretization.get_communicator());
223 discretization.get_communicator());
224 MatrixCreator::create_mass_matrix(dof_handler, quadrature, mass_matrix, (Function<dim, NumberType> *)nullptr,
225 discretization.get_constraints());
226 }
227 // Jacobian sparsity pattern
228 {
229 DynamicSparsityPattern dsp(discretization.get_locally_relevant_dofs());
230 DoFTools::make_sparsity_pattern(dof_handler, dsp, discretization.get_constraints(),
231 /*keep_constrained_dofs = */ true);
233 dsp, sparsity_pattern_jacobian, discretization.get_locally_owned_dofs(),
234 discretization.get_locally_relevant_dofs(), discretization.get_communicator());
235 }
236 timings_reinit.push_back(timer.wall_time());
237
239 const AffineConstraintContext<Components, dim> context(metadata);
240
241 auto &constraints = discretization.get_constraints();
242 constraints.clear();
243 DoFTools::make_hanging_node_constraints(dof_handler, constraints);
245 constraints.close();
246 }
247
248 virtual void rebuild_jacobian_sparsity() override
249 {
250 // Jacobian sparsity pattern
251 DynamicSparsityPattern dsp(discretization.get_locally_relevant_dofs());
252 DoFTools::make_sparsity_pattern(dof_handler, dsp, discretization.get_constraints(),
253 /*keep_constrained_dofs = */ true);
254 for (const auto &row : discretization.get_locally_relevant_dofs())
255 for (const auto &col : extractor_dof_indices)
256 dsp.add(row, col);
258 discretization.get_locally_relevant_dofs(),
259 discretization.get_communicator());
260 }
261
266 virtual const SparseMatrixType &get_mass_matrix() const override { return mass_matrix; }
267
275 virtual void refinement_indicator(Vector<double> &indicator, const VectorType &solution_global) override
276 {
277 using Iterator = typename DoFHandler<dim>::active_cell_iterator;
279 using CopyData = internal::CopyData_I<NumberType>;
280
281 const auto cell_worker = [&](const Iterator &t_cell, Scratch &scratch_data, CopyData &copy_data) {
282 scratch_data.fe_values.reinit(t_cell);
283 const auto &fe_v = scratch_data.fe_values;
284 copy_data.cell_index = t_cell->active_cell_index();
285 copy_data.value = 0;
286
287 const auto &JxW = fe_v.get_JxW_values();
288 const auto &q_points = fe_v.get_quadrature_points();
289 const auto &q_indices = fe_v.quadrature_point_indices();
290
291 auto &solution = scratch_data.solution;
292 auto &solution_grad = scratch_data.solution_grad;
293 auto &solution_hess = scratch_data.solution_hess;
294 fe_v.get_function_values(solution_global, solution);
295 fe_v.get_function_gradients(solution_global, solution_grad);
296 fe_v.get_function_hessians(solution_global, solution_hess);
297
298 double local_indicator = 0.;
299 for (const auto &q_index : q_indices) {
300 const auto &x_q = q_points[q_index];
301 model.cell_indicator(local_indicator, x_q,
302 i_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index]));
303 copy_data.value += JxW[q_index] * local_indicator;
304 }
305 };
306 const auto copier = [&](const CopyData &c) { indicator[c.cell_index] += c.value; };
307
308 Scratch scratch_data(mapping, fe, quadrature, quadrature_face);
309 CopyData copy_data;
310 MeshWorker::AssembleFlags assemble_flags = MeshWorker::assemble_own_cells;
311
312 // map() is collective and each rank visits only its own cells; see NoMapsHere.
313 const NoMapsHere no_maps_during_assembly;
314 const auto schedule = schedule_for(assembly_cost::local_fe);
315 MeshWorker::mesh_loop(locally_owned_cells(dof_handler), cell_worker, copier, scratch_data, copy_data,
316 assemble_flags, nullptr, nullptr, schedule.queue_length, schedule.chunk_size);
317 }
318
319 virtual void mass(VectorType &mass, const VectorType &solution_global, const VectorType &solution_global_dot,
320 NumberType weight) override
321 {
322 using Iterator = typename DoFHandler<dim>::active_cell_iterator;
324 using CopyData = internal::CopyData_R<NumberType>;
325 const auto &constraints = discretization.get_constraints();
326
327 const auto cell_worker = [&](const Iterator &cell, Scratch &scratch_data, CopyData &copy_data) {
328 scratch_data.fe_values.reinit(cell);
329 const auto &fe_v = scratch_data.fe_values;
330 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
331
332 copy_data.reinit(cell, n_dofs);
333 const auto &JxW = fe_v.get_JxW_values();
334 const auto &q_points = fe_v.get_quadrature_points();
335 const auto &q_indices = fe_v.quadrature_point_indices();
336
337 auto &comp = scratch_data.comp;
338 for (uint i = 0; i < n_dofs; ++i)
339 comp[i] = fe_v.get_fe().system_to_component_index(i).first;
340
341 auto &solution = scratch_data.solution;
342 auto &solution_dot = scratch_data.solution_dot;
343 fe_v.get_function_values(solution_global, solution);
344 fe_v.get_function_values(solution_global_dot, solution_dot);
345
346 array<NumberType, Components::count_fe_functions()> mass{};
347 for (const auto &q_index : q_indices) {
348 const auto &x_q = q_points[q_index];
349 model.mass(mass, x_q, solution[q_index], solution_dot[q_index]);
350
351 for (uint i = 0; i < n_dofs; ++i) {
352 copy_data.cell_residual(i) += weight * JxW[q_index] * fe_v.shape_value_component(i, q_index, comp[i]) *
353 mass[comp[i]]; // +phi_i(x_q) * mass(x_q, u_q)
354 }
355 }
356 };
357 const auto copier = [&](const CopyData &c) {
358 constraints.distribute_local_to_global(c.cell_residual, c.local_dof_indices, mass);
359 };
360
361 Scratch scratch_data(mapping, fe, quadrature, quadrature_face);
362 CopyData copy_data;
363 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells;
364
365 // map() is collective and each rank visits only its own cells; see NoMapsHere.
366 const NoMapsHere no_maps_during_assembly;
367 const auto schedule = schedule_for(assembly_cost::local_fe);
368 MeshWorker::mesh_loop(locally_owned_cells(dof_handler), cell_worker, copier, scratch_data, copy_data, flags,
369 nullptr, nullptr, schedule.queue_length, schedule.chunk_size);
370 // Resolve contributions this rank made to rows it does not own. A partition-boundary
371 // face is assembled by exactly one of its two neighbours (mesh_loop hands it to the
372 // smaller subdomain id), and that rank writes BOTH sides -- so the other side's rows
373 // arrive here. A no-op for the serial types.
374 mass.compress(dealii::VectorOperation::add);
375 }
376
377 virtual void residual(VectorType &residual, const VectorType &solution_global, NumberType weight,
378 const VectorType &solution_global_dot, NumberType weight_mass,
379 const VectorType &variables = VectorType()) override
380 {
381 using Iterator = typename DoFHandler<dim>::active_cell_iterator;
383 using CopyData = internal::CopyData_R<NumberType>;
384 const auto &constraints = discretization.get_constraints();
385
386 // Find the EoM and extract whatever data is needed for the model.
387 std::array<NumberType, Components::count_extractors()> __extracted_data{{}};
388 if constexpr (Components::count_extractors() > 0)
389 this->extract(__extracted_data, solution_global, variables, true, false, true);
390 const auto &extracted_data = __extracted_data;
391
392 const auto cell_worker = [&](const Iterator &cell, Scratch &scratch_data, CopyData &copy_data) {
393 const double cell_width = DiFfRG::internal::cell_width(cell);
394 scratch_data.fe_values.reinit(cell);
395 const auto &fe_v = scratch_data.fe_values;
396 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
397
398 copy_data.reinit(cell, n_dofs);
399 const auto &JxW = fe_v.get_JxW_values();
400 const auto &q_points = fe_v.get_quadrature_points();
401 const auto &q_indices = fe_v.quadrature_point_indices();
402
403 auto &comp = scratch_data.comp;
404 for (uint i = 0; i < n_dofs; ++i)
405 comp[i] = fe.system_to_component_index(i).first;
406
407 auto &solution = scratch_data.solution;
408 auto &solution_grad = scratch_data.solution_grad;
409 auto &solution_hess = scratch_data.solution_hess;
410 auto &solution_dot = scratch_data.solution_dot;
411 fe_v.get_function_values(solution_global, solution);
412 fe_v.get_function_gradients(solution_global, solution_grad);
413 fe_v.get_function_hessians(solution_global, solution_hess);
414 fe_v.get_function_values(solution_global_dot, solution_dot);
415
416 array<Tensor<1, dim, NumberType>, Components::count_fe_functions()> flux{};
417 array<NumberType, Components::count_fe_functions()> source{};
418 array<NumberType, Components::count_fe_functions()> mass{};
419 for (const auto &q_index : q_indices) {
420 const auto &x_q = q_points[q_index];
421 model.flux(flux, x_q,
422 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data,
423 variables, cell_width));
424 model.source(source, x_q,
425 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data,
426 variables, cell_width));
427 model.mass(mass, x_q, solution[q_index], solution_dot[q_index]);
428
429 for (uint i = 0; i < n_dofs; ++i) {
430 const auto &ci = comp[i];
431 copy_data.cell_residual(i) +=
432 JxW[q_index] * weight * // dx *
433 (-scalar_product(fe_v.shape_grad_component(i, q_index, ci),
434 flux[ci]) // -dphi_i(x_q) * flux(x_q, u_q)
435 + fe_v.shape_value_component(i, q_index, ci) * source[ci]); // -phi_i(x_q) * source(x_q, u_q)
436 copy_data.cell_residual(i) += weight_mass * JxW[q_index] * fe_v.shape_value_component(i, q_index, ci) *
437 mass[ci]; // +phi_i(x_q) * mass(x_q, u_q)
438 }
439 }
440 };
441 const auto boundary_worker = [&](const Iterator &cell, const uint &face_no, Scratch &scratch_data,
442 CopyData &copy_data) {
443 const double cell_width = DiFfRG::internal::cell_width(cell);
444 scratch_data.fe_interface_values.reinit(cell, face_no);
445 const auto &fe_fv = scratch_data.fe_interface_values.get_fe_face_values(0);
446 const uint n_dofs = fe_fv.get_fe().n_dofs_per_cell();
447
448 const auto &JxW = fe_fv.get_JxW_values();
449 const auto &q_points = fe_fv.get_quadrature_points();
450 const auto &q_indices = fe_fv.quadrature_point_indices();
451 const std::vector<Tensor<1, dim>> &normals = fe_fv.get_normal_vectors();
452
453 auto &solution = scratch_data.solution_interface[0];
454 auto &solution_grad = scratch_data.solution_grad_interface[0];
455 auto &solution_hess = scratch_data.solution_hess_interface[0];
456 fe_fv.get_function_values(solution_global, solution);
457 fe_fv.get_function_gradients(solution_global, solution_grad);
458 fe_fv.get_function_hessians(solution_global, solution_hess);
459
460 auto &comp = scratch_data.comp;
461 for (uint i = 0; i < n_dofs; ++i)
462 comp[i] = fe.system_to_component_index(i).first;
463
464 array<Tensor<1, dim, NumberType>, Components::count_fe_functions()> numflux{};
465 for (const auto &q_index : q_indices) {
466 const auto &x_q = q_points[q_index];
467 model.boundary_numflux(numflux, normals[q_index], x_q,
468 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index],
469 extracted_data, variables, cell_width));
470
471 for (uint i = 0; i < n_dofs; ++i) {
472 const auto &ci = comp[i];
473 copy_data.cell_residual(i) +=
474 weight * JxW[q_index] * // dx
475 (fe_fv.shape_value_component(i, q_index, ci) *
476 scalar_product(numflux[ci], normals[q_index])); // phi_i(x_q) * numflux(x_q, u_q) * n(x_q)
477 }
478 }
479 };
480 const auto copier = [&](const CopyData &c) {
481 constraints.distribute_local_to_global(c.cell_residual, c.local_dof_indices, residual);
482 };
483
484 Scratch scratch_data(mapping, fe, quadrature, quadrature_face);
485 CopyData copy_data;
486 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells | MeshWorker::assemble_boundary_faces;
487
488 Timer timer;
489 // map() is collective and each rank visits only its own cells; see NoMapsHere.
490 const NoMapsHere no_maps_during_assembly;
491 const auto schedule = schedule_for(assembly_cost::momentum_integral);
492 MeshWorker::mesh_loop(locally_owned_cells(dof_handler), cell_worker, copier, scratch_data, copy_data, flags,
493 boundary_worker, nullptr, schedule.queue_length, schedule.chunk_size);
494 // Resolve contributions this rank made to rows it does not own. A partition-boundary
495 // face is assembled by exactly one of its two neighbours (mesh_loop hands it to the
496 // smaller subdomain id), and that rank writes BOTH sides -- so the other side's rows
497 // arrive here. A no-op for the serial types.
498 residual.compress(dealii::VectorOperation::add);
499 timings_residual.push_back(timer.wall_time());
500 }
501
502 virtual void jacobian_mass(SparseMatrixType &jacobian, const VectorType &solution_global,
503 const VectorType &solution_global_dot, NumberType alpha, NumberType beta) override
504 {
505 using Iterator = typename DoFHandler<dim>::active_cell_iterator;
507 using CopyData = internal::CopyData_J<NumberType>;
508 const auto &constraints = discretization.get_constraints();
509
510 const auto cell_worker = [&](const Iterator &cell, Scratch &scratch_data, CopyData &copy_data) {
511 scratch_data.fe_values.reinit(cell);
512 const auto &fe_v = scratch_data.fe_values;
513 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
514
515 copy_data.reinit(cell, n_dofs, Components::count_extractors());
516 const auto &JxW = fe_v.get_JxW_values();
517 const auto &q_points = fe_v.get_quadrature_points();
518 const auto &q_indices = fe_v.quadrature_point_indices();
519
520 auto &comp = scratch_data.comp;
521 for (uint i = 0; i < n_dofs; ++i)
522 comp[i] = fe.system_to_component_index(i).first;
523
524 auto &solution = scratch_data.solution;
525 auto &solution_dot = scratch_data.solution_dot;
526
527 SimpleMatrix<NumberType, Components::count_fe_functions()> j_mass;
528 SimpleMatrix<NumberType, Components::count_fe_functions()> j_mass_dot;
529
530 fe_v.get_function_values(solution_global, solution);
531 fe_v.get_function_values(solution_global_dot, solution_dot);
532 for (const auto &q_index : q_indices) {
533 const auto &x_q = q_points[q_index];
534 model.template jacobian_mass<0>(j_mass, x_q, solution[q_index], solution_dot[q_index]);
535 model.template jacobian_mass<1>(j_mass_dot, x_q, solution[q_index], solution_dot[q_index]);
536
537 for (uint i = 0; i < n_dofs; ++i) {
538 for (uint j = 0; j < n_dofs; ++j) {
539 copy_data.cell_jacobian(i, j) +=
540 JxW[q_index] * fe_v.shape_value_component(j, q_index, comp[j]) *
541 fe_v.shape_value_component(i, q_index, comp[i]) *
542 (alpha * j_mass_dot(comp[i], comp[j]) + beta * j_mass(comp[i], comp[j]));
543 }
544 }
545 }
546 };
547 const auto copier = [&](const CopyData &c) {
548 constraints.distribute_local_to_global(c.cell_jacobian, c.local_dof_indices, jacobian);
549 };
550
551 Scratch scratch_data(mapping, fe, quadrature, quadrature_face);
552 CopyData copy_data;
553 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells;
554
555 Timer timer;
556 // map() is collective and each rank visits only its own cells; see NoMapsHere.
557 const NoMapsHere no_maps_during_assembly;
558 const auto schedule = schedule_for(assembly_cost::local_fe);
559 MeshWorker::mesh_loop(locally_owned_cells(dof_handler), cell_worker, copier, scratch_data, copy_data, flags,
560 nullptr, nullptr, schedule.queue_length, schedule.chunk_size);
561 // Resolve contributions this rank made to rows it does not own. A partition-boundary
562 // face is assembled by exactly one of its two neighbours (mesh_loop hands it to the
563 // smaller subdomain id), and that rank writes BOTH sides -- so the other side's rows
564 // arrive here. A no-op for the serial types.
565 jacobian.compress(dealii::VectorOperation::add);
566 timings_jacobian.push_back(timer.wall_time());
567 }
568
569 virtual void jacobian(SparseMatrixType &jacobian, const VectorType &solution_global, NumberType weight,
570 const VectorType &solution_global_dot, NumberType alpha, NumberType beta,
571 const VectorType &variables = VectorType()) override
572 {
573 using Iterator = typename DoFHandler<dim>::active_cell_iterator;
575 using CopyData = internal::CopyData_J<NumberType>;
576 const auto &constraints = discretization.get_constraints();
577
578 // Find the EoM and extract whatever data is needed for the model.
579 std::array<NumberType, Components::count_extractors()> extracted_data{{}};
580 if constexpr (Components::count_extractors() > 0) {
581 this->extract(extracted_data, solution_global, variables, true, true, true);
582 if (this->jacobian_extractors(this->extractor_jacobian, solution_global, variables))
584 discretization.get_communicator());
585 }
586
587 const auto cell_worker = [&](const Iterator &cell, Scratch &scratch_data, CopyData &copy_data) {
588 const double cell_width = DiFfRG::internal::cell_width(cell);
589 scratch_data.fe_values.reinit(cell);
590 const auto &fe_v = scratch_data.fe_values;
591 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
592
593 copy_data.reinit(cell, n_dofs, Components::count_extractors());
594 const auto &JxW = fe_v.get_JxW_values();
595 const auto &q_points = fe_v.get_quadrature_points();
596 const auto &q_indices = fe_v.quadrature_point_indices();
597
598 auto &comp = scratch_data.comp;
599 for (uint i = 0; i < n_dofs; ++i)
600 comp[i] = fe.system_to_component_index(i).first;
601
602 auto &solution = scratch_data.solution;
603 auto &solution_dot = scratch_data.solution_dot;
604 auto &solution_grad = scratch_data.solution_grad;
605 auto &solution_hess = scratch_data.solution_hess;
606
607 fe_v.get_function_values(solution_global, solution);
608 fe_v.get_function_gradients(solution_global, solution_grad);
609 fe_v.get_function_hessians(solution_global, solution_hess);
610 fe_v.get_function_values(solution_global_dot, solution_dot);
611
612 SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions()> j_flux;
613 SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NumberType>>, Components::count_fe_functions()> j_grad_flux;
614 SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NumberType>>, Components::count_fe_functions()> j_hess_flux;
615 SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions(), Components::count_extractors()>
616 j_extr_flux;
617 SimpleMatrix<NumberType, Components::count_fe_functions()> j_source;
618 SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions()> j_grad_source;
619 SimpleMatrix<Tensor<2, dim, NumberType>, Components::count_fe_functions()> j_hess_source;
620 SimpleMatrix<NumberType, Components::count_fe_functions(), Components::count_extractors()> j_extr_source;
621 SimpleMatrix<NumberType, Components::count_fe_functions()> j_mass;
622 SimpleMatrix<NumberType, Components::count_fe_functions()> j_mass_dot;
623
624 for (const auto &q_index : q_indices) {
625 const auto &x_q = q_points[q_index];
626 model.template jacobian_flux_source<0, 0>(j_flux, j_source, x_q,
627 fe_tie(solution[q_index], solution_grad[q_index],
628 solution_hess[q_index], extracted_data, variables,
629 cell_width));
630 model.template jacobian_flux_source_grad<1>(j_grad_flux, j_grad_source, x_q,
631 fe_tie(solution[q_index], solution_grad[q_index],
632 solution_hess[q_index], extracted_data, variables,
633 cell_width));
634 model.template jacobian_flux_source_hess<2>(j_hess_flux, j_hess_source, x_q,
635 fe_tie(solution[q_index], solution_grad[q_index],
636 solution_hess[q_index], extracted_data, variables,
637 cell_width));
638 if constexpr (Components::count_extractors() > 0) {
639 model.template jacobian_flux_source_extr<3>(j_extr_flux, j_extr_source, x_q,
640 fe_tie(solution[q_index], solution_grad[q_index],
641 solution_hess[q_index], extracted_data, variables,
642 cell_width));
643 }
644 model.template jacobian_mass<0>(j_mass, x_q, solution[q_index], solution_dot[q_index]);
645 model.template jacobian_mass<1>(j_mass_dot, x_q, solution[q_index], solution_dot[q_index]);
646
647 // Cache per-DoF shape function data for this quadrature point
648 auto &sv = scratch_data.cached_shape_values;
649 auto &sg = scratch_data.cached_shape_grads;
650 auto &sh = scratch_data.cached_shape_hessians;
651 for (uint k = 0; k < n_dofs; ++k) {
652 sv[k] = fe_v.shape_value_component(k, q_index, comp[k]);
653 sg[k] = fe_v.shape_grad_component(k, q_index, comp[k]);
654 sh[k] = fe_v.shape_hessian_component(k, q_index, comp[k]);
655 }
656
657 const auto do_work = [&](uint i_begin, uint i_end, uint j_begin, uint j_end) {
658 for (uint i = i_begin; i < i_end; ++i) {
659 const auto &ci = comp[i];
660 const auto &sv_i = sv[i];
661 const auto &sg_i = sg[i];
662 for (uint j = j_begin; j < j_end; ++j) {
663 const auto &cj = comp[j];
664 NumberType contribution = weight * JxW[q_index] *
665 (sv[j] * (-scalar_product(sg_i, j_flux(ci, cj)) + sv_i * j_source(ci, cj)) +
666 scalar_product(sg[j], -scalar_product(sg_i, j_grad_flux(ci, cj)) +
667 sv_i * j_grad_source(ci, cj)) +
668 scalar_product(sh[j], -scalar_product(sg_i, j_hess_flux(ci, cj)) +
669 sv_i * j_hess_source(ci, cj)));
670 contribution += JxW[q_index] * sv[j] * sv_i * (alpha * j_mass_dot(ci, cj) + beta * j_mass(ci, cj));
671 copy_data.cell_jacobian(i, j) += contribution;
672 }
673 }
674 };
675
676 if (n_dofs * n_dofs < 64)
677 do_work(0, n_dofs, 0, n_dofs);
678 else
679 tbb::parallel_for(
680 tbb::blocked_range2d<uint>(0, n_dofs, 0, n_dofs), [&](const tbb::blocked_range2d<uint> &range) {
681 do_work(range.rows().begin(), range.rows().end(), range.cols().begin(), range.cols().end());
682 });
683
684 // extractor contribution
685 if constexpr (Components::count_extractors() > 0) {
686 for (uint i = 0; i < n_dofs; ++i) {
687 for (uint e = 0; e < Components::count_extractors(); ++e)
688 copy_data.extractor_cell_jacobian(i, e) +=
689 weight * JxW[q_index] * // dx * phi_j * (
690 (-scalar_product(fe_v.shape_grad_component(i, q_index, comp[i]),
691 j_extr_flux(comp[i], e)) // -dphi_i * jflux
692 + fe_v.shape_value_component(i, q_index, comp[i]) *
693 j_extr_source(comp[i], e)); // -phi_i * jsource)
694 }
695 }
696 }
697 };
698
699 const auto boundary_worker = [&](const Iterator &cell, const uint &face_no, Scratch &scratch_data,
700 CopyData &copy_data) {
701 const double cell_width = DiFfRG::internal::cell_width(cell);
702 scratch_data.fe_interface_values.reinit(cell, face_no);
703 const auto &fe_fv = scratch_data.fe_interface_values.get_fe_face_values(0);
704 const uint n_dofs = fe_fv.get_fe().n_dofs_per_cell();
705
706 const auto &JxW = fe_fv.get_JxW_values();
707 const auto &q_points = fe_fv.get_quadrature_points();
708 const auto &q_indices = fe_fv.quadrature_point_indices();
709 const std::vector<Tensor<1, dim>> &normals = fe_fv.get_normal_vectors();
710
711 auto &solution = scratch_data.solution_interface[0];
712 auto &solution_grad = scratch_data.solution_grad_interface[0];
713 auto &solution_hess = scratch_data.solution_hess;
714 fe_fv.get_function_values(solution_global, solution);
715 fe_fv.get_function_gradients(solution_global, solution_grad);
716 fe_fv.get_function_hessians(solution_global, solution_hess);
717
718 auto &comp = scratch_data.comp;
719 for (uint i = 0; i < n_dofs; ++i)
720 comp[i] = fe.system_to_component_index(i).first;
721
722 SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions()> j_boundary_numflux;
723 SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NumberType>>, Components::count_fe_functions()>
724 j_grad_boundary_numflux;
725 SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NumberType>>, Components::count_fe_functions()>
726 j_hess_boundary_numflux;
727 SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions(), Components::count_extractors()>
728 j_extr_boundary_numflux;
729 for (const auto &q_index : q_indices) {
730 const auto &x_q = q_points[q_index];
731 model.template jacobian_boundary_numflux<0, 0>(j_boundary_numflux, normals[q_index], x_q,
732 fe_tie(solution[q_index], solution_grad[q_index],
733 solution_hess[q_index], extracted_data, variables,
734 cell_width));
735 model.template jacobian_boundary_numflux_grad<1>(j_grad_boundary_numflux, normals[q_index], x_q,
736 fe_tie(solution[q_index], solution_grad[q_index],
737 solution_hess[q_index], extracted_data, variables,
738 cell_width));
739 model.template jacobian_boundary_numflux_hess<2>(j_hess_boundary_numflux, normals[q_index], x_q,
740 fe_tie(solution[q_index], solution_grad[q_index],
741 solution_hess[q_index], extracted_data, variables,
742 cell_width));
743 if constexpr (Components::count_extractors() > 0) {
744 model.template jacobian_boundary_numflux_extr<3>(j_extr_boundary_numflux, normals[q_index], x_q,
745 fe_tie(solution[q_index], solution_grad[q_index],
746 solution_hess[q_index], extracted_data, variables,
747 cell_width));
748 }
749
750 // Cache per-DoF shape function data for boundary
751 auto &bsv = scratch_data.cached_shape_values;
752 auto &bsg = scratch_data.cached_shape_grads;
753 auto &bsh = scratch_data.cached_shape_hessians;
754 for (uint k = 0; k < n_dofs; ++k) {
755 bsv[k] = fe_fv.shape_value_component(k, q_index, comp[k]);
756 bsg[k] = fe_fv.shape_grad_component(k, q_index, comp[k]);
757 bsh[k] = fe_fv.shape_hessian_component(k, q_index, comp[k]);
758 }
759
760 const auto do_bnd_work = [&](uint i_begin, uint i_end, uint j_begin, uint j_end) {
761 for (uint i = i_begin; i < i_end; ++i) {
762 const auto &ci = comp[i];
763 const auto &sv_i = bsv[i];
764 for (uint j = j_begin; j < j_end; ++j) {
765 const auto &cj = comp[j];
766 const auto n_dot_jnf = scalar_product(j_boundary_numflux(ci, cj), normals[q_index]);
767 const auto n_dot_jgnf = scalar_product(j_grad_boundary_numflux(ci, cj), normals[q_index]);
768 const auto n_dot_jhnf = scalar_product(j_hess_boundary_numflux(ci, cj), normals[q_index]);
769 copy_data.cell_jacobian(i, j) +=
770 weight * JxW[q_index] *
771 (bsv[j] * sv_i * n_dot_jnf + scalar_product(bsg[j], sv_i * n_dot_jgnf) +
772 scalar_product(bsh[j], sv_i * n_dot_jhnf));
773 }
774 }
775 };
776
777 if (n_dofs * n_dofs < 64)
778 do_bnd_work(0, n_dofs, 0, n_dofs);
779 else
780 tbb::parallel_for(
781 tbb::blocked_range2d<uint>(0, n_dofs, 0, n_dofs), [&](const tbb::blocked_range2d<uint> &range) {
782 do_bnd_work(range.rows().begin(), range.rows().end(), range.cols().begin(), range.cols().end());
783 });
784
785 // extractor contribution
786 if constexpr (Components::count_extractors() > 0) {
787 for (uint i = 0; i < n_dofs; ++i) {
788 for (uint e = 0; e < Components::count_extractors(); ++e)
789 copy_data.extractor_cell_jacobian(i, e) +=
790 weight * JxW[q_index] * // dx * phi_j(x_q)
791 (fe_fv.shape_value_component(i, q_index, comp[i]) *
792 scalar_product(j_extr_boundary_numflux(comp[i], e),
793 normals[q_index])); // phi_i(x_q) * j_numflux(x_q, u_q) * n(x_q)
794 }
795 }
796 }
797 };
798
799 const auto copier = [&](const CopyData &c) {
800 constraints.distribute_local_to_global(c.cell_jacobian, c.local_dof_indices, jacobian);
801 if constexpr (Components::count_extractors() > 0) {
802 FullMatrix<NumberType> extractor_dependence(c.local_dof_indices.size(), extractor_dof_indices.size());
803 c.extractor_cell_jacobian.mmult(extractor_dependence, this->extractor_jacobian);
804 constraints.distribute_local_to_global(extractor_dependence, c.local_dof_indices, extractor_dof_indices,
805 jacobian);
806 }
807 };
808
809 Scratch scratch_data(mapping, fe, quadrature, quadrature_face);
810 CopyData copy_data;
811 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells | MeshWorker::assemble_boundary_faces;
812
813 Timer timer;
814 // map() is collective and each rank visits only its own cells; see NoMapsHere.
815 const NoMapsHere no_maps_during_assembly;
816 const auto schedule = schedule_for(assembly_cost::momentum_integral);
817 MeshWorker::mesh_loop(locally_owned_cells(dof_handler), cell_worker, copier, scratch_data, copy_data, flags,
818 boundary_worker, nullptr, schedule.queue_length, schedule.chunk_size);
819 // Resolve contributions this rank made to rows it does not own. A partition-boundary
820 // face is assembled by exactly one of its two neighbours (mesh_loop hands it to the
821 // smaller subdomain id), and that rank writes BOTH sides -- so the other side's rows
822 // arrive here. A no-op for the serial types.
823 jacobian.compress(dealii::VectorOperation::add);
824 timings_jacobian.push_back(timer.wall_time());
825 }
826 SummaryEvent summary() const override
827 {
828 SummaryEvent result{.component = "CG"};
829 result.timing("reinit", average_time_reinit() * 1000, num_reinits())
830 .timing("residual", average_time_residual_assembly() * 1000, num_residuals())
832 return result;
833 }
834
835 double average_time_reinit() const
836 {
837 double t = 0.;
838 double n = timings_reinit.size();
839 for (const auto &t_ : timings_reinit)
840 t += t_ / n;
841 return t;
842 }
843 uint num_reinits() const { return timings_reinit.size(); }
844
846 {
847 double t = 0.;
848 double n = timings_residual.size();
849 for (const auto &t_ : timings_residual)
850 t += t_ / n;
851 return t;
852 }
853 uint num_residuals() const { return timings_residual.size(); }
854
856 {
857 double t = 0.;
858 double n = timings_jacobian.size();
859 for (const auto &t_ : timings_jacobian)
860 t += t_ / n;
861 return t;
862 }
863 uint num_jacobians() const { return timings_jacobian.size(); }
864
865 protected:
867 using Base::dof_handler;
868 using Base::fe;
869 using Base::mapping;
870 using Base::model;
871
872 QGauss<dim> quadrature;
873 QGauss<dim - 1> quadrature_face;
874 using Base::schedule_for;
875
879
880 std::vector<double> timings_reinit;
881 std::vector<double> timings_residual;
882 std::vector<double> timings_jacobian;
883
885 };
886 } // namespace CG
887} // namespace DiFfRG
Definition affine_constraint_metadata.hh:24
The basic assembler that can be used for any standard CG scheme with flux and source.
Definition cg.hh:170
std::vector< double > timings_jacobian
Definition cg.hh:882
Model & model
Definition common.hh:405
const Mapping< dim > & mapping
Definition common.hh:409
uint num_reinits() const
Definition cg.hh:843
virtual void reinit_solution_view(SolutionView< VectorType > &view) const override
Definition cg.hh:202
virtual void mass(VectorType &mass, const VectorType &solution_global, const VectorType &solution_global_dot, NumberType weight) override
Definition cg.hh:319
virtual void jacobian(SparseMatrixType &jacobian, const VectorType &solution_global, NumberType weight, const VectorType &solution_global_dot, NumberType alpha, NumberType beta, const VectorType &variables=VectorType()) override
Definition cg.hh:569
const FiniteElement< dim > & fe
Definition common.hh:407
double average_time_reinit() const
Definition cg.hh:835
SummaryEvent summary() const override
Definition cg.hh:826
virtual MPI_Comm get_communicator() const override
The communicator this assembler's linear algebra lives on.
Definition cg.hh:201
virtual void refinement_indicator(Vector< double > &indicator, const VectorType &solution_global) override
refinement indicator for adaptivity. Only calls the model's cell_indicator function,...
Definition cg.hh:275
get_type::SparsityPattern< SparseMatrixType > sparsity_pattern_jacobian
Definition cg.hh:877
double average_time_residual_assembly() const
Definition cg.hh:845
static constexpr uint dim
Definition cg.hh:181
Model_ Model
Definition cg.hh:175
typename Discretization::Components Components
Definition cg.hh:180
typename Discretization::SparseMatrixType SparseMatrixType
Definition cg.hh:178
typename Discretization::NumberType NumberType
Definition cg.hh:176
double average_time_jacobian_assembly() const
Definition cg.hh:855
virtual const get_type::SparsityPattern< SparseMatrixType > & get_sparsity_pattern_jacobian() const override
Obtain the sparsity pattern of the jacobian matrix.
Definition cg.hh:262
std::vector< double > timings_residual
Definition cg.hh:881
virtual void rebuild_jacobian_sparsity() override
Definition cg.hh:248
std::vector< double > timings_reinit
Definition cg.hh:880
virtual void reinit() override
Reinitialize the assembler. This is necessary if the mesh has changed, e.g. after a mesh refinement.
Definition cg.hh:208
QGauss< dim > quadrature
Definition cg.hh:872
typename Discretization::VectorType VectorType
Definition cg.hh:177
const DoFHandler< dim > & dof_handler
Definition common.hh:408
virtual void residual(VectorType &residual, const VectorType &solution_global, NumberType weight, const VectorType &solution_global_dot, NumberType weight_mass, const VectorType &variables=VectorType()) override
Definition cg.hh:377
virtual void reinit_matrix(SparseMatrixType &matrix) const override
Definition cg.hh:195
QGauss< dim - 1 > quadrature_face
Definition cg.hh:873
SparseMatrixType mass_matrix
Definition cg.hh:878
Discretization & discretization
Definition common.hh:404
get_type::SparsityPattern< SparseMatrixType > sparsity_pattern_mass
Definition cg.hh:876
virtual void jacobian_mass(SparseMatrixType &jacobian, const VectorType &solution_global, const VectorType &solution_global_dot, NumberType alpha, NumberType beta) override
Definition cg.hh:502
Discretization_ Discretization
Definition cg.hh:174
virtual const SparseMatrixType & get_mass_matrix() const override
Obtain the mass matrix.
Definition cg.hh:266
std::vector< types::global_dof_index > extractor_dof_indices
Definition common.hh:463
Assembler(Discretization &discretization, Model &model, const ConfigTree &config)
Definition cg.hh:182
AssemblySchedule schedule_for(const double cost_ns) const
The mesh_loop schedule for a loop whose cell worker costs cost_ns nanoseconds.
Definition common.hh:418
uint num_residuals() const
Definition cg.hh:853
virtual void reinit_vector(VectorType &vec) const override
Definition cg.hh:191
uint num_jacobians() const
Definition cg.hh:863
typename DiFfRG::internal::components_of< ModelOrComponents_ >::type Components
Definition cg.hh:47
VectorType_ VectorType
Definition cg.hh:49
NumberType_ NumberType
Definition cg.hh:48
SparseMatrixType_ SparseMatrixType
Definition cg.hh:50
static constexpr uint dim
Definition cg.hh:52
A hierarchical configuration tree, readable from JSON and TOML files.
Definition config_tree.hh:32
The basic assembler that can be used for any standard CG scheme with flux and source.
Definition common.hh:42
Model & model
Definition common.hh:405
const Mapping< dim > & mapping
Definition common.hh:409
FullMatrix< NumberType > extractor_jacobian
Definition common.hh:459
const FiniteElement< dim > & fe
Definition common.hh:407
void extract(std::array< NumberType, Components::count_extractors()> &data, const VectorType &solution_global, const VectorType &variables, bool search_EoM, bool set_EoM, bool postprocess) const
Definition common.hh:274
bool jacobian_extractors(FullMatrix< NumberType > &extractor_jacobian, const VectorType &solution_global, const VectorType &variables)
Definition common.hh:302
virtual void reinit() override
Reinitialize the assembler. This is necessary if the mesh has changed, e.g. after a mesh refinement.
Definition common.hh:116
const DoFHandler< dim > & dof_handler
Definition common.hh:408
Discretization & discretization
Definition common.hh:404
std::vector< types::global_dof_index > extractor_dof_indices
Definition common.hh:463
AssemblySchedule schedule_for(const double cost_ns) const
The mesh_loop schedule for a loop whose cell worker costs cost_ns nanoseconds.
Definition common.hh:418
Decides, without any user input, which rank computes which part of each map().
Definition map_scheduler.hh:195
A simple NxM-matrix class, which is used for cell-wise Jacobians.
Definition tuples.hh:170
A read-only, fully-replicated view of the solution.
Definition solution_view.hh:48
void reinit(const dealii::IndexSet &, const dealii::IndexSet &, MPI_Comm)
Establish the layout. No-op for the serial policy.
Definition solution_view.hh:58
All compile-time knowledge about which linear algebra types DiFfRG uses.
auto fe_tie(T &&...t)
Definition cg.hh:20
auto i_tie(T &&...t)
Definition cg.hh:26
constexpr double local_fe
Local FE work only: mass matrices, refinement indicators. ~0.2-0.3 us/cell for CG p=3.
Definition assembly_schedule.hh:48
constexpr double momentum_integral
Definition assembly_schedule.hh:53
typename internal::_SparsityPattern< SparseMatrixType >::value SparsityPattern
Definition linear_algebra.hh:155
AffineConstraintMetadata< dim > build_affine_constraint_metadata(const Discretization &discretization)
Definition affine_constraint_metadata.hh:99
double cell_width(const CellIterator &cell)
The smallest face-normal width over all faces of cell.
Definition cell_geometry.hh:42
void apply_model_affine_constraints(Model &model, Constraints &constraints, const Context &context)
Definition affine_constraint_metadata.hh:79
Definition complex_math.hh:10
auto locally_owned_cells(const dealii::DoFHandler< dim > &dof_handler)
The cells this rank assembles.
Definition assembly_schedule.hh:154
@ config
/discretization/threads.
void reinit_la_matrix(SparseMatrixType &matrix, const get_type::SparsityPattern< SparseMatrixType > &pattern, const dealii::IndexSet &locally_owned, MPI_Comm comm)
Size a matrix from a finalized sparsity pattern.
Definition la_policy.hh:92
void reinit_la_vector(VectorType &vec, const dealii::IndexSet &locally_owned, MPI_Comm comm)
Size a vector to the rank's share of the rows.
Definition la_policy.hh:27
unsigned int uint
Definition utils.hh:24
void finalize_la_sparsity(dealii::DynamicSparsityPattern &dsp, get_type::SparsityPattern< SparseMatrixType > &pattern, const dealii::IndexSet &locally_owned, const dealii::IndexSet &locally_relevant, MPI_Comm comm)
Turn a freshly built DynamicSparsityPattern into the pattern type the matrix wants.
Definition la_policy.hh:50
std::array< double, 2 > values
Definition cg.hh:154
std::array< uint, 2 > cell_indices
Definition cg.hh:153
double value
Definition cg.hh:157
uint cell_index
Definition cg.hh:158
std::vector< CopyFaceData_I > face_data
Definition cg.hh:156
FullMatrix< NumberType > extractor_cell_jacobian
Definition cg.hh:139
std::vector< types::global_dof_index > local_dof_indices
Definition cg.hh:140
FullMatrix< NumberType > cell_jacobian
Definition cg.hh:138
void reinit(const Iterator &cell, uint dofs_per_cell, uint n_extractors)
Definition cg.hh:142
void reinit(const Iterator &cell, uint dofs_per_cell)
Definition cg.hh:129
Vector< NumberType > cell_residual
Definition cg.hh:126
std::vector< types::global_dof_index > local_dof_indices
Definition cg.hh:127
Class to hold data for each assembly thread, i.e. FEValues for cells, interfaces, as well as pre-allo...
Definition cg.hh:40
std::vector< Vector< NumberType > > solution
Definition cg.hh:109
std::vector< uint > comp
Definition cg.hh:117
array< std::vector< std::vector< Tensor< 1, dim, NumberType > > >, 2 > solution_grad_interface
Definition cg.hh:114
FEValues< dim > fe_values
Definition cg.hh:106
static constexpr uint dim
Definition cg.hh:41
array< std::vector< std::vector< Tensor< 2, dim, NumberType > > >, 2 > solution_hess_interface
Definition cg.hh:115
ScratchData(const Mapping< dim > &mapping, const FiniteElement< dim > &fe, const dealii::Quadrature< dim > &quadrature, const dealii::Quadrature< dim - 1 > &quadrature_face, const UpdateFlags update_flags=update_values|update_gradients|update_quadrature_points|update_JxW_values|update_hessians, const UpdateFlags interface_update_flags=update_values|update_gradients|update_quadrature_points|update_JxW_values|update_normal_vectors|update_hessians)
Definition cg.hh:44
std::vector< Tensor< 1, dim > > cached_shape_grads
Definition cg.hh:121
std::vector< std::vector< Tensor< 1, dim, NumberType > > > solution_grad
Definition cg.hh:110
std::vector< double > cached_shape_values
Definition cg.hh:120
FEInterfaceValues< dim > fe_interface_values
Definition cg.hh:107
ScratchData(const ScratchData< Discretization > &scratch_data)
Definition cg.hh:75
const uint n_components
Definition cg.hh:104
std::vector< Tensor< 2, dim > > cached_shape_hessians
Definition cg.hh:122
array< std::vector< Vector< NumberType > >, 2 > solution_interface
Definition cg.hh:113
std::vector< std::vector< Tensor< 2, dim, NumberType > > > solution_hess
Definition cg.hh:111
std::vector< Vector< NumberType > > solution_dot
Definition cg.hh:112
typename Discretization::NumberType NumberType
Definition cg.hh:42
Definition tuples.hh:34
Definition run_reporter.hh:73
SummaryEvent & timing(const std::string_view name, const double average_ms, const std::size_t calls)
Definition run_reporter.hh:78
std::conditional_t< CarriesModel< D >, typename D::Model, D > type
Definition types.hh:63
A class to store a tuple with elements that can be accessed by name. The names are stored as FixedStr...
Definition tuples.hh:56