137 * #include <deal.II/base/
numbers.h>
138 * #include <deal.II/base/thread_management.h>
139 * #include <deal.II/grid/tria.h>
140 * #include <deal.II/dofs/dof_handler.h>
141 * #include <deal.II/grid/grid_generator.h>
142 * #include <deal.II/grid/tria_accessor.h>
143 * #include <deal.II/grid/tria_iterator.h>
144 * #include <deal.II/dofs/dof_accessor.h>
145 * #include <deal.II/dofs/dof_renumbering.h>
146 * #include <deal.II/fe/fe_q.h>
147 * #include <deal.II/fe/fe_dgq.h>
148 * #include <deal.II/fe/fe_system.h>
149 * #include <deal.II/dofs/dof_tools.h>
150 * #include <deal.II/fe/fe_values.h>
151 * #include <deal.II/base/quadrature_lib.h>
152 * #include <deal.II/base/function.h>
153 * #include <deal.II/numerics/vector_tools.h>
154 * #include <deal.II/numerics/matrix_tools.h>
155 * #include <deal.II/numerics/derivative_approximation.h>
156 * #include <deal.II/lac/block_vector.h>
157 * #include <deal.II/lac/full_matrix.h>
158 * #include <deal.II/lac/block_sparse_matrix.h>
159 * #include <deal.II/lac/block_sparsity_pattern.h>
160 * #include <deal.II/lac/sparse_direct.h>
161 * #include <deal.II/particles/particle_handler.h>
162 * #include <deal.II/particles/data_out.h>
164 * #include <deal.II/numerics/data_out.h>
166 * #include <iostream>
168 * #include <deal.II/base/logstream.h>
169 * #include <deal.II/grid/grid_refinement.h>
176 * The following is the main
class. It resembles a variation of the @ref step_6
"step-6"
177 * principal
class, with the addition of information-specific stuff. It also
178 * has to deal with solving a vector-valued problem
for (c,lambda,f) as
179 * primal variable, dual variable, and right hand side, as explained
184 *
class InformationDensityMeshRefinement
187 * InformationDensityMeshRefinement ();
191 *
void compute_synthetic_measurements();
192 *
void bounce_measurement_points_to_cell_centers ();
193 *
void setup_system();
194 *
void assemble_system ();
196 *
void compute_information_content ();
197 *
void output_results (
const unsigned int cycle)
const;
198 *
void refine_grid ();
201 *
const double source_radius;
203 * std::vector<Point<dim>> detector_locations;
205 *
const double regularization_parameter;
222 * std::vector<Point<dim>> detector_locations_on_mesh;
223 * std::vector<double> measurement_values;
224 * std::vector<double> noise_level;
231 * InformationDensityMeshRefinement<dim>::InformationDensityMeshRefinement ()
234 * source_radius (0.2),
235 * regularization_parameter (10000),
245 * We have 50 detector points on an outer ring...
248 *
for (
unsigned int i=0; i<50; ++i)
252 * detector_locations.push_back (p);
257 * ...and another 50 detector points on an innner ring:
260 *
for (
unsigned int i=0; i<50; ++i)
264 * detector_locations.push_back (p);
269 * Generate the grid we will work on:
277 * The detector locations are
static, so we can already here
278 * generate a file that contains their locations. We use the
279 * particle framework to
do this,
using detector locations as
280 * particle locations.
286 *
for (
const auto &loc : detector_locations)
289 * new_particle.set_location(loc);
292 * Insert the particle. It is a lie that the particle is in
293 * the
first cell, but
nothing we
do actually cares about the
294 * cell a particle is in.
297 * particle_handler.insert_particle(new_particle,
303 * std::ofstream output(
"detector_locations.vtu");
304 * particle_out.write_vtu(output);
309 * While we
're generating output, also output the source location. Do this
310 * by outputting many (1000) points that indicate the perimeter of the source
314 * Particles::ParticleHandler<dim> particle_handler(triangulation,
315 * StaticMappingQ1<dim>::mapping);
317 * const unsigned int n_points = 1000;
318 * for (unsigned int i=0; i<n_points; ++i)
320 * Point<dim> loc = source_location;
321 * loc[0] += source_radius * std::cos(2*numbers::PI*i/n_points);
322 * loc[1] += source_radius * std::sin(2*numbers::PI*i/n_points);
324 * Particles::Particle<dim> new_particle;
325 * new_particle.set_location(loc);
326 * particle_handler.insert_particle(new_particle,
327 * triangulation.begin_active());
330 * Particles::DataOut<dim> particle_out;
331 * particle_out.build_patches(particle_handler);
332 * std::ofstream output("source_locations.vtu");
333 * particle_out.write_vtu(output);
341 * The following function solves a forward problem on a twice
342 * refined mesh to compute "synthetic data". Refining the mesh
343 * beyond the mesh used for the inverse problem avoids an
348 * void InformationDensityMeshRefinement<dim>::compute_synthetic_measurements ()
350 * std::cout << "Computing synthetic data by solving the forward problem..."
355 * Create a triangulation and DoFHandler that corresponds to a
356 * twice-refined mesh so that we obtain the synthetic data with
357 * higher accuracy than we do on the regular mesh used for all other
361 * Triangulation<dim> forward_triangulation;
362 * forward_triangulation.copy_triangulation (triangulation);
363 * forward_triangulation.refine_global (2);
365 * const FE_Q<dim> forward_fe (fe.base_element(0).degree);
366 * DoFHandler<dim> forward_dof_handler (forward_triangulation);
367 * forward_dof_handler.distribute_dofs (forward_fe);
369 * AffineConstraints<double> constraints;
370 * DoFTools::make_hanging_node_constraints(forward_dof_handler, constraints);
371 * constraints.close();
373 * SparsityPattern sparsity (forward_dof_handler.n_dofs(),
374 * forward_dof_handler.max_couplings_between_dofs());
375 * DoFTools::make_sparsity_pattern (forward_dof_handler, sparsity);
376 * constraints.condense (sparsity);
377 * sparsity.compress ();
379 * SparseMatrix<double> system_matrix (sparsity);
380 * Vector<double> system_rhs (forward_dof_handler.n_dofs());
382 * QGauss<dim> quadrature_formula(3);
383 * FEValues<dim> fe_values (forward_fe, quadrature_formula,
384 * update_values | update_gradients |
385 * update_quadrature_points | update_JxW_values);
387 * const unsigned int dofs_per_cell = forward_fe.dofs_per_cell;
388 * const unsigned int n_q_points = quadrature_formula.size();
392 * First assemble the system matrix and right hand side for the forward
397 * FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
398 * Vector<double> cell_rhs (dofs_per_cell);
399 * std::vector<unsigned int> local_dof_indices (dofs_per_cell);
401 * for (const auto &cell : forward_dof_handler.active_cell_iterators())
403 * fe_values.reinit (cell);
407 * for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
408 * for (unsigned int i=0; i<dofs_per_cell; ++i)
409 * for (unsigned int j=0; j<dofs_per_cell; ++j)
410 * cell_matrix(i,j) += (fe_values.shape_grad(i,q_point) *
411 * fe_values.shape_grad(j,q_point)
413 * fe_values.shape_value(i,q_point) *
414 * (velocity * fe_values.shape_grad(j,q_point))
417 * fe_values.JxW(q_point);
418 * for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
419 * if (fe_values.quadrature_point(q_point).distance (source_location)
421 * for (unsigned int i=0; i<dofs_per_cell; ++i)
424 * fe_values.shape_value (i, q_point) *
425 * fe_values.JxW(q_point);
427 * cell->get_dof_indices (local_dof_indices);
428 * constraints.distribute_local_to_global (cell_matrix,
435 * std::map<unsigned int, double> boundary_values;
436 * VectorTools::interpolate_boundary_values (forward_dof_handler,
438 * Functions::ZeroFunction<dim>(),
440 * Vector<double> tmp (forward_dof_handler.n_dofs());
441 * MatrixTools::apply_boundary_values (boundary_values,
449 * Solve the forward problem and output it into its own VTU file :
452 * SparseDirectUMFPACK A_inverse;
453 * Vector<double> forward_solution (forward_dof_handler.n_dofs());
454 * forward_solution = system_rhs;
455 * A_inverse.solve(system_matrix, forward_solution);
457 * const double max_forward_solution = forward_solution.linfty_norm();
460 * DataOut<dim> data_out;
461 * data_out.attach_dof_handler (forward_dof_handler);
462 * data_out.add_data_vector (forward_solution, "c");
463 * data_out.build_patches (4);
465 * std::ofstream out ("forward-solution.vtu");
466 * data_out.write_vtu (out);
471 * Now evaluate the forward solution at the measurement points:
474 * for (const auto &p : detector_locations)
478 * same 10% noise level for all points
481 * noise_level.push_back (0.1 * max_forward_solution);
483 * const double z_n = VectorTools::point_value(forward_dof_handler, forward_solution, p);
484 * const double eps_n = Utilities::generate_normal_random_number(0, noise_level.back());
486 * measurement_values.push_back (z_n + eps_n);
489 * std::cout << std::endl;
495 * It will make our lives easier if we can always assume that detector
496 * locations are at cell centers, because then we can evaluate the
497 * solution there using a quadrature formula whose sole quadrature
498 * point lies at the center of a cell. That's of course not where the
499 *
"real" detector locations are, but it does not introduce a large
504 *
void InformationDensityMeshRefinement<dim>::bounce_measurement_points_to_cell_centers ()
506 * detector_locations_on_mesh = detector_locations;
507 *
for (
auto &p : detector_locations_on_mesh)
509 * for (const auto &cell :
triangulation.active_cell_iterators())
510 * if (cell->point_inside (p))
512 * p = cell->center();
521 * The following
functions are all quite standard by what we have
522 * shown in @ref step_4
"step-4", @ref step_6
"step-6", and @ref step_22
"step-22" (to name just a few of the
523 * more typical programs):
527 * void InformationDensityMeshRefinement<dim>::setup_system ()
529 *
std::cout <<
"Setting up the linear system for the inverse problem..."
532 * dof_handler.distribute_dofs (fe);
535 * hanging_node_constraints.clear ();
537 * hanging_node_constraints);
538 * hanging_node_constraints.close();
540 * std::cout <<
" Number of active cells: "
543 * std::cout <<
" Number of degrees of freedom: "
544 * << dof_handler.n_dofs()
547 *
const std::vector<types::global_dof_index> dofs_per_component =
551 * hanging_node_constraints.condense(c_sparsity);
552 * sparsity_pattern.copy_from(c_sparsity);
554 * system_matrix.reinit (sparsity_pattern);
556 * solution.reinit (dofs_per_component);
557 * system_rhs.reinit (dofs_per_component);
563 *
void InformationDensityMeshRefinement<dim>::assemble_system ()
565 * std::cout <<
"Assembling the linear system for the inverse problem..."
574 *
const unsigned int dofs_per_cell = fe.dofs_per_cell;
575 *
const unsigned int n_q_points = quadrature_formula.size();
580 * std::vector<unsigned int> local_dof_indices (dofs_per_cell);
584 *
for (
const auto &cell : dof_handler.active_cell_iterators())
586 * fe_values.
reinit (cell);
590 *
for (
unsigned int q_point=0; q_point<n_q_points; ++q_point)
591 *
for (
unsigned int i=0; i<dofs_per_cell; ++i)
593 *
const Tensor<1,dim> grad_phi_i = fe_values[c].gradient (i,q_point);
596 *
const double phi_i = fe_values[c].value (i,q_point);
597 *
const double psi_i = fe_values[
lambda].value (i,q_point);
598 *
const double chi_i = fe_values[f].value (i,q_point);
600 *
for (
unsigned int j=0; j<dofs_per_cell; ++j)
602 *
const Tensor<1,dim> grad_phi_j = fe_values[c].gradient (j,q_point);
605 *
const double phi_j = fe_values[c].value (j,q_point);
606 *
const double psi_j= fe_values[
lambda].value (j,q_point);
607 *
const double chi_j = fe_values[f].value (j,q_point);
610 * ((grad_phi_i * grad_phi_j
612 * phi_i * (velocity * grad_phi_j)
616 * grad_psi_i * grad_psi_j
618 * psi_i * (velocity * grad_psi_j)
622 * regularization_parameter * chi_i * chi_j
624 * fe_values.JxW (q_point));
626 *
for (
unsigned int n=0; n< detector_locations_on_mesh.size(); ++n)
627 *
if (fe_values.quadrature_point(q_point).distance (detector_locations_on_mesh[n]) < 1e-12)
629 *
cell_matrix(i,j) += psi_i * phi_j / noise_level[n] / noise_level[n];
633 *
for (
unsigned int n=0; n< detector_locations_on_mesh.size(); ++n)
634 *
if (fe_values.quadrature_point(q_point).distance (detector_locations_on_mesh[n]) < 1e-12)
635 * cell_rhs(i) += psi_i * measurement_values[n] / noise_level[n] / noise_level[n];
638 * cell->get_dof_indices (local_dof_indices);
639 *
for (
unsigned int i=0; i<dofs_per_cell; ++i)
641 *
for (
unsigned int j=0; j<dofs_per_cell; ++j)
642 * system_matrix.add (local_dof_indices[i],
643 * local_dof_indices[j],
646 * system_rhs(local_dof_indices[i]) += cell_rhs(i);
650 * hanging_node_constraints.condense (system_matrix);
651 * hanging_node_constraints.condense (system_rhs);
653 * std::map<unsigned int,double> boundary_values;
654 * std::vector<bool> component_mask (3);
655 * component_mask[0] = component_mask[1] =
true;
656 * component_mask[2] =
false;
667 * std::cout << std::endl;
673 *
void InformationDensityMeshRefinement<dim>::solve ()
675 * std::cout <<
"Solving the linear system for the inverse problem..."
679 * solution = system_rhs;
680 * A_direct.
solve(system_matrix, solution);
682 * hanging_node_constraints.distribute (solution);
684 * std::cout << std::endl;
691 * This is really the only interesting function of
this program. It
692 * computes the
functions @f$h_K = A^{-1} s_K@f$
for each source function
693 * (corresponding to each cell of the mesh). To
do so, it
first
695 *
class to build an LU decomposition
for this matrix. Then it loops
696 * over all cells @f$K@f$ and computes the corresponding @f$h_K@f$ by applying
697 * the LU decomposition to a right hand side vector
for each @f$s_K@f$.
701 * The actual information content is then computed by evaluating these
702 * functions @f$h_K@f$ at measurement locations.
706 *
void InformationDensityMeshRefinement<dim>::compute_information_content ()
708 * std::cout <<
"Computing the information content..."
711 * information_content.reinit (
triangulation.n_active_cells());
713 *
const FE_Q<dim> information_fe (fe.base_element(0).degree);
715 * information_dof_handler.distribute_dofs (information_fe);
719 * constraints.close();
722 * information_dof_handler.max_couplings_between_dofs());
724 * constraints.condense (sparsity);
725 * sparsity.compress ();
731 *
const unsigned int dofs_per_cell = information_fe.dofs_per_cell;
732 *
const unsigned int n_q_points = quadrature_formula.size();
736 * First build the forward
operator
740 *
FEValues<dim> fe_values (information_fe, quadrature_formula,
745 * std::vector<unsigned int> local_dof_indices (dofs_per_cell);
747 *
for (
const auto &cell : information_dof_handler.active_cell_iterators())
749 * fe_values.
reinit (cell);
752 *
for (
unsigned int q_point=0; q_point<n_q_points; ++q_point)
753 *
for (
unsigned int i=0; i<dofs_per_cell; ++i)
754 *
for (
unsigned int j=0; j<dofs_per_cell; ++j)
755 *
cell_matrix(i,j) += (fe_values.shape_grad (i,q_point) *
756 * fe_values.shape_grad(j,q_point)
758 * fe_values.shape_value(i,q_point) *
759 * (velocity * fe_values.shape_grad(j,q_point))) *
760 * fe_values.JxW(q_point);
762 * cell->distribute_local_to_global (cell_matrix,
766 * constraints.condense (system_matrix);
768 * std::map<unsigned int, double> boundary_values;
790 * Now compute the solutions corresponding to the possible
791 * sources. Each source is active on exactly one cell.
795 * As mentioned in the paper,
this is a trivially
parallel job, so
796 * we send the computations
for each of these cells onto a separate
797 * task and let the OS schedule them onto individual processor
808 * std::vector<unsigned int> local_dof_indices (dofs_per_cell);
811 * cell = information_dof_handler.begin_active();
812 * std::advance (cell, K);
814 *
FEValues<dim> fe_values (information_fe, quadrature_formula,
818 * fe_values.reinit (cell);
821 *
for (
unsigned int q_point=0; q_point<n_q_points; ++q_point)
822 *
for (
unsigned int i=0; i<dofs_per_cell; ++i)
823 * cell_rhs(i) += fe_values.shape_value (i,q_point) *
824 * fe_values.JxW(q_point);
826 * cell->distribute_local_to_global (cell_rhs,
829 * constraints.condense (rhs);
831 * A_inverse.solve(rhs);
833 * constraints.distribute (rhs);
837 * Having computed the forward solutions
838 * corresponding to
this source term, evaluate its
839 * contribution to the information content on all
840 * cells of the mesh by taking into account the
841 * detector locations. We add these into global
842 * objects, so we have to guard access to the
846 *
static std::mutex m;
847 * std::lock_guard<std::mutex> g(m);
850 * information_content(K) = regularization_parameter * cell->measure() * cell->measure();
851 * std::vector<double> local_h_K_values (n_q_points);
852 *
for (
const auto &cell : information_dof_handler.active_cell_iterators())
854 * fe_values.
reinit (cell);
855 * fe_values.get_function_values (rhs, local_h_K_values);
857 *
for (
unsigned int q_point=0; q_point<n_q_points; ++q_point)
858 *
for (
unsigned int n=0; n< detector_locations_on_mesh.size(); ++n)
859 *
if (fe_values.quadrature_point(q_point).distance (detector_locations_on_mesh[n]) < 1e-12)
860 * information_content(K) += local_h_K_values[q_point]
861 * * local_h_K_values[q_point]
862 * / noise_level[n] / noise_level[n];
874 * std::cout << std::endl;
881 * Create graphical output
for all of the principal variables of the
882 * problem (c,lambda,f) as well as
for the information content and
883 * density. Then also output the various blocks of the
matrix so we
888 *
void InformationDensityMeshRefinement<dim>::output_results (
const unsigned int cycle)
const
890 * std::cout <<
"Outputting solutions..." << std::flush;
894 * std::vector<std::string> names;
895 * names.push_back (
"forward_solution");
896 * names.push_back (
"adjoint_solution");
897 * names.push_back (
"recovered_parameter");
900 * data_out.add_data_vector (solution, names);
901 * data_out.add_data_vector (information_content,
"information_content");
904 *
for (
const auto &cell :
triangulation.active_cell_iterators())
905 * information_density(cell->active_cell_index())
906 * =
std::
sqrt(information_content(cell->active_cell_index())) / cell->measure();
907 * data_out.add_data_vector (information_density,
"information_density");
909 * data_out.build_patches ();
911 * std::string filename =
"solution-";
912 * filename += (
'0'+cycle);
913 * filename +=
".vtu";
915 * std::ofstream output (filename.c_str());
916 * data_out.write_vtu (output);
921 * Now output the individual blocks of the
matrix into files.
924 *
auto write_block = [&](
const unsigned int block_i,
925 *
const unsigned int block_j,
926 *
const std::string &filename)
928 * std::ofstream o(filename);
929 * system_matrix.block(block_i,block_j).print (o);
931 * write_block(0,0,
"matrix-" + std::to_string(cycle) +
"-A.txt");
932 * write_block(0,2,
"matrix-" + std::to_string(cycle) +
"-B.txt");
933 * write_block(1,0,
"matrix-" + std::to_string(cycle) +
"-C.txt");
934 * write_block(2,2,
"matrix-" + std::to_string(cycle) +
"-M.txt");
936 * std::cout << std::endl;
943 * The following is then a function that refines the mesh based on the
944 * refinement criteria described in the paper. Which criterion to use
945 * is determined by which
value the `refinement_criterion` variable
950 *
void InformationDensityMeshRefinement<dim>::refine_grid ()
952 * std::cout <<
"Refining the mesh..." << std::endl;
954 *
enum RefinementCriterion
957 * information_content,
961 *
const RefinementCriterion refinement_criterion = information_content;
963 *
switch (refinement_criterion)
971 *
case information_content:
974 * this->information_content,
989 * std::vector<double> lambda_values (quadrature.size());
990 * std::vector<double> f_values (quadrature.size());
992 *
for (
const auto &cell : dof_handler.active_cell_iterators())
994 * fe_values.
reinit (cell);
995 * fe_values[
lambda].get_function_values (solution, lambda_values);
996 * fe_values[f].get_function_values (solution, f_values);
998 *
for (
unsigned int q=0; q<quadrature.size(); ++q)
999 * refinement_indicators(cell->active_cell_index())
1000 * += (std::fabs (regularization_parameter * f_values[q]
1003 * * fe_values.JxW(q));
1007 * refinement_indicators,
1020 * refinement_indicators,
1024 * and
scale it to obtain an error indicator.
1027 *
for (
const auto &cell :
triangulation.active_cell_iterators())
1028 * refinement_indicators[cell->active_cell_index()] *=
1033 * refinement_indicators,
1040 *
Assert (
false, ExcInternalError());
1043 * bounce_measurement_points_to_cell_centers ();
1046 * std::cout << std::endl;
1052 *
template <
int dim>
1053 *
void InformationDensityMeshRefinement<dim>::run ()
1055 * std::cout <<
"Solving problem in " << dim <<
" space dimensions." << std::endl;
1057 * compute_synthetic_measurements ();
1058 * bounce_measurement_points_to_cell_centers ();
1060 *
for (
unsigned int cycle=0; cycle<7; ++cycle)
1062 * std::cout <<
"---------- Cycle " << cycle <<
" ------------" << std::endl;
1065 * assemble_system ();
1067 * compute_information_content ();
1068 * output_results (cycle);
1081 * InformationDensityMeshRefinement<2> information_density_mesh_refinement;
1082 * information_density_mesh_refinement.run ();
1084 *
catch (std::exception &exc)
1086 * std::cerr << std::endl << std::endl
1087 * <<
"----------------------------------------------------"
1089 * std::cerr <<
"Exception on processing: " << std::endl
1090 * << exc.what() << std::endl
1091 * <<
"Aborting!" << std::endl
1092 * <<
"----------------------------------------------------"
1099 * std::cerr << std::endl << std::endl
1100 * <<
"----------------------------------------------------"
1102 * std::cerr <<
"Unknown exception!" << std::endl
1103 * <<
"Aborting!" << std::endl
1104 * <<
"----------------------------------------------------"
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
unsigned int depth_console(const unsigned int n)
void build_patches(const Particles::ParticleHandler< dim, spacedim > &particles, const std::vector< std::string > &data_component_names={}, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretations={})
void solve(Vector< double > &rhs_and_solution, const bool transpose=false) const
void factorize(const Matrix &matrix)
#define Assert(cond, exc)
typename ActiveSelector::active_cell_iterator active_cell_iterator
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_values
Shape function values.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
Task< RT > new_task(const std::function< RT()> &function)
CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt K
void approximate_gradient(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const InputVector &solution, Vector< float > &derivative_norm, const unsigned int component=0)
void component_wise(DoFHandler< dim, spacedim > &dof_handler, const std::vector< unsigned int > &target_component=std::vector< unsigned int >())
void hyper_cube(Triangulation< dim, spacedim > &tria, const double left=0., const double right=1., const bool colorize=false)
void refine_and_coarsen_fixed_number(Triangulation< dim, spacedim > &triangulation, const Vector< Number > &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
@ matrix
Contents is actually a 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.)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
int(&) functions(const void *v1, const void *v2)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
static constexpr double PI
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)