4#include <deal.II/base/multithread_info.h>
5#include <deal.II/base/quadrature_lib.h>
6#include <deal.II/base/timer.h>
7#include <deal.II/dofs/dof_handler.h>
8#include <deal.II/dofs/dof_tools.h>
9#include <deal.II/fe/fe_interface_values.h>
10#include <deal.II/fe/fe_values.h>
11#include <deal.II/lac/full_matrix.h>
12#include <deal.II/lac/sparse_matrix.h>
13#include <deal.II/lac/vector.h>
14#include <deal.II/meshworker/mesh_loop.h>
15#include <deal.II/numerics/fe_field_function.h>
16#include <deal.II/numerics/matrix_tools.h>
17#include <deal.II/numerics/vector_tools.h>
18#include <spdlog/spdlog.h>
28 using namespace dealii;
36 template <
typename Discretization_,
typename Model_>
38 typename Discretization_::SparseMatrixType, Discretization_::dim>
43 template <
typename... T>
static constexpr auto v_tie(T &&...t)
45 return named_tuple<std::tuple<T &...>,
"variables",
"extractors">(std::tie(t...));
48 template <
typename... T>
static constexpr auto e_tie(T &&...t)
50 return named_tuple<std::tuple<T &...>,
"fe_functions",
"fe_derivatives",
"fe_hessians",
"extractors",
51 "variables">(std::tie(t...));
61 static constexpr uint dim = Discretization::dim;
66 threads(json.get_uint(
"/discretization/threads")),
batch_size(json.get_uint(
"/discretization/batch_size")),
69 EoM_abs_tol(json.get_double(
"/discretization/EoM_abs_tol")),
70 EoM_max_iter(json.get_uint(
"/discretization/EoM_max_iter"))
72 if (this->
threads == 0) this->
threads = dealii::MultithreadInfo::n_threads() / 2;
73 spdlog::get(
"log")->info(
"FEM: Using {} threads for assembly.",
threads);
78 ComponentMask component_mask(
model.template differential_components<dim>());
79 return DoFTools::extract_dofs(
dof_handler, component_mask);
86 const auto fe_function_names = Components::FEFunction_Descriptor::get_names_vector();
87 std::vector<std::string> fe_function_names_residual;
88 for (
const auto &name : fe_function_names)
89 fe_function_names_residual.push_back(name +
"_residual");
90 std::vector<std::string> fe_function_names_dot;
91 for (
const auto &name : fe_function_names)
92 fe_function_names_dot.push_back(name +
"_dot");
95 fe_out.attach(
dof_handler, solution, fe_function_names);
96 if (dt_solution.size() > 0) fe_out.attach(
dof_handler, dt_solution, fe_function_names_dot);
99 readouts(data_out, solution, variables);
108 std::vector<IndexSet> component_boundary_dofs(Components::count_fe_functions());
109 for (
uint c = 0; c < Components::count_fe_functions(); ++c) {
110 ComponentMask component_mask(Components::count_fe_functions(),
false);
111 component_mask.set(c,
true);
112 component_boundary_dofs[c] = DoFTools::extract_boundary_dofs(
dof_handler, component_mask);
114 std::vector<std::vector<Point<dim>>> component_boundary_points(Components::count_fe_functions());
115 for (
uint c = 0; c < Components::count_fe_functions(); ++c) {
116 component_boundary_points[c].resize(component_boundary_dofs[c].n_elements());
117 for (
uint i = 0; i < component_boundary_dofs[c].n_elements(); ++i)
118 component_boundary_points[c][i] =
119 discretization.get_support_point(component_boundary_dofs[c].nth_index_in_set(i));
124 DoFTools::make_hanging_node_constraints(
dof_handler, constraints);
125 model.affine_constraints(constraints, component_boundary_dofs, component_boundary_points);
139 std::array<
NumberType, Components::count_extractors()> __extracted_data{{}};
140 if constexpr (Components::count_extractors() > 0)
141 extract(__extracted_data, spatial_solution, variables,
true,
false,
false);
142 const auto &extracted_data = __extracted_data;
150 std::array<
NumberType, Components::count_extractors()> __extracted_data{{}};
151 if constexpr (Components::count_extractors() > 0)
152 extract(__extracted_data, spatial_solution, variables,
true,
false,
false);
153 const auto &extracted_data = __extracted_data;
161 auto helper = [&](
auto EoMfun,
auto outputter) {
168 Vector<typename VectorType::value_type> values(
dof_handler.get_fe().n_components());
169 std::vector<Tensor<1, dim, typename VectorType::value_type>> gradients(
dof_handler.get_fe().n_components());
171 FEValues<dim> fe_v(
mapping,
fe, EoM_unit,
172 update_values | update_gradients | update_quadrature_points | update_JxW_values |
176 std::vector<Vector<NumberType>> solution{Vector<NumberType>(Components::count_fe_functions())};
177 std::vector<std::vector<Tensor<1, dim, NumberType>>> solution_grad{
178 std::vector<Tensor<1, dim, NumberType>>(Components::count_fe_functions())};
179 std::vector<std::vector<Tensor<2, dim, NumberType>>> solution_hess{
180 std::vector<Tensor<2, dim, NumberType>>(Components::count_fe_functions())};
181 fe_v.get_function_values(solution_global, solution);
182 fe_v.get_function_gradients(solution_global, solution_grad);
183 fe_v.get_function_hessians(solution_global, solution_hess);
185 std::array<
NumberType, Components::count_extractors()> __extracted_data{{}};
186 if constexpr (Components::count_extractors() > 0)
187 extract(__extracted_data, solution_global, variables,
true,
false,
false);
188 const auto &extracted_data = __extracted_data;
190 outputter(data_out,
EoM,
e_tie(solution[0], solution_grad[0], solution_hess[0], extracted_data, variables));
192 model.template readouts_multiple(helper, data_out);
196 const VectorType &variables,
bool search_EoM,
bool set_EoM,
bool postprocess)
const
203 [&](
const auto &p,
const auto &values) {
return model.EoM(p, values); },
204 [&](
const auto &p,
const auto &values) {
return postprocess ?
model.EoM_postprocess(p, values) : p; },
212 Vector<typename VectorType::value_type> values(
dof_handler.get_fe().n_components());
213 std::vector<Tensor<1, dim, typename VectorType::value_type>> gradients(
dof_handler.get_fe().n_components());
215 FEValues<dim> fe_v(
mapping,
fe, EoM_unit,
216 update_values | update_gradients | update_quadrature_points | update_JxW_values |
220 std::vector<Vector<NumberType>> solution{Vector<NumberType>(Components::count_fe_functions())};
221 std::vector<std::vector<Tensor<1, dim, NumberType>>> solution_grad{
222 std::vector<Tensor<1, dim, NumberType>>(Components::count_fe_functions())};
223 std::vector<std::vector<Tensor<2, dim, NumberType>>> solution_hess{
224 std::vector<Tensor<2, dim, NumberType>>(Components::count_fe_functions())};
225 fe_v.get_function_values(solution_global, solution);
226 fe_v.get_function_gradients(solution_global, solution_grad);
227 fe_v.get_function_hessians(solution_global, solution_hess);
237 extractor_jacobian_u = FullMatrix<NumberType>(Components::count_extractors(), Components::count_fe_functions());
241 FullMatrix<NumberType>(Components::count_extractors(), Components::count_fe_functions() *
dim);
245 FullMatrix<NumberType>(Components::count_extractors(), Components::count_fe_functions() *
dim *
dim);
249 [&](
const auto &p,
const auto &values) {
return model.EoM(p, values); },
250 [&](
const auto &p,
const auto &values) {
return model.EoM_postprocess(p, values); },
EoM_abs_tol,
256 Vector<typename VectorType::value_type> values(
dof_handler.get_fe().n_components());
257 std::vector<Tensor<1, dim, typename VectorType::value_type>> gradients(
dof_handler.get_fe().n_components());
259 FEValues<dim> fe_v(
mapping,
fe, EoM_unit,
260 update_values | update_gradients | update_quadrature_points | update_JxW_values |
264 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
272 std::vector<Vector<NumberType>> solution{Vector<NumberType>(Components::count_fe_functions())};
273 std::vector<std::vector<Tensor<1, dim, NumberType>>> solution_grad{
274 std::vector<Tensor<1, dim, NumberType>>(Components::count_fe_functions())};
275 std::vector<std::vector<Tensor<2, dim, NumberType>>> solution_hess{
276 std::vector<Tensor<2, dim, NumberType>>(Components::count_fe_functions())};
277 fe_v.get_function_values(solution_global, solution);
278 fe_v.get_function_gradients(solution_global, solution_grad);
279 fe_v.get_function_hessians(solution_global, solution_hess);
285 e_tie(solution[0], solution_grad[0], solution_hess[0],
nothing, variables));
287 e_tie(solution[0], solution_grad[0], solution_hess[0],
nothing, variables));
289 e_tie(solution[0], solution_grad[0], solution_hess[0],
nothing, variables));
294 for (
uint e = 0; e < Components::count_extractors(); ++e)
295 for (
uint i = 0; i < n_dofs; ++i) {
296 const auto component_i = fe_v.get_fe().system_to_component_index(i).first;
299 for (
uint d1 = 0; d1 <
dim; ++d1) {
302 for (
uint d2 = 0; d2 <
dim; ++d2)
304 fe_v.shape_hessian_component(i, 0, component_i)[d1][d2];
334 const FiniteElement<dim> &
fe;
341 mutable typename DoFHandler<dim>::cell_iterator
EoM_cell;
This is the general assembler interface for any kind of discretization. An assembler is responsible f...
Definition abstract_assembler.hh:39
void jacobian(SparseMatrixType &jacobian, const VectorType &solution_global, NumberType weight, NumberType mass_weight, const VectorType &variables=VectorType())
Definition abstract_assembler.hh:251
void residual(VectorType &residual, const VectorType &solution_global, NumberType weight, NumberType weight_mass, const VectorType &variables=VectorType())
Definition abstract_assembler.hh:177
Class to manage writing to files. FEM functions are written to vtk files and other data is written to...
Definition data_output.hh:20
FEOutput< dim, VectorType > & fe_output()
Returns a reference to the FEOutput object used to write FEM functions to .vtu files and ....
The basic assembler that can be used for any standard CG scheme with flux and source.
Definition common.hh:39
uint num_variable_jacobians() const
Definition common.hh:329
Model & model
Definition common.hh:333
const auto & get_discretization() const
Definition common.hh:102
typename Discretization::NumberType NumberType
Definition common.hh:57
const Mapping< dim > & mapping
Definition common.hh:336
static constexpr auto v_tie(T &&...t)
Definition common.hh:43
virtual void residual_variables(VectorType &residual, const VectorType &variables, const VectorType &spatial_solution) override
Definition common.hh:135
double average_time_variable_jacobian_assembly()
Definition common.hh:321
const uint EoM_max_iter
Definition common.hh:344
uint num_variable_residuals() const
Definition common.hh:319
const double EoM_abs_tol
Definition common.hh:343
FullMatrix< NumberType > extractor_jacobian
Definition common.hh:346
virtual void set_time(double t) override
Set the current time. The assembler should usually just forward this to the numerical model.
Definition common.hh:131
double average_time_variable_residual_assembly()
Definition common.hh:311
static constexpr uint dim
Definition common.hh:61
const FiniteElement< dim > & fe
Definition common.hh:334
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:195
typename Discretization::Components Components
Definition common.hh:60
bool jacobian_extractors(FullMatrix< NumberType > &extractor_jacobian, const VectorType &solution_global, const VectorType &variables)
Definition common.hh:232
FullMatrix< NumberType > extractor_jacobian_du
Definition common.hh:348
DoFHandler< dim >::cell_iterator EoM_cell
Definition common.hh:341
virtual void refinement_indicator(Vector< double > &, const VectorType &)=0
uint threads
Definition common.hh:338
void readouts(DataOutput< dim, VectorType > &data_out, const VectorType &solution_global, const VectorType &variables) const
Definition common.hh:158
Point< dim > EoM
Definition common.hh:345
virtual void jacobian_variables(FullMatrix< NumberType > &jacobian, const VectorType &variables, const VectorType &spatial_solution) override
Definition common.hh:146
FullMatrix< NumberType > extractor_jacobian_ddu
Definition common.hh:349
Model_ Model
Definition common.hh:56
std::vector< double > timings_variable_jacobian
Definition common.hh:353
DoFHandler< dim >::cell_iterator old_EoM_cell
Definition common.hh:342
std::vector< double > timings_variable_residual
Definition common.hh:352
auto & get_discretization()
Definition common.hh:103
virtual void reinit() override
Reinitialize the assembler. This is necessary if the mesh has changed, e.g. after a mesh refinement.
Definition common.hh:105
const DoFHandler< dim > & dof_handler
Definition common.hh:335
typename Discretization::VectorType VectorType
Definition common.hh:58
Discretization & discretization
Definition common.hh:332
virtual IndexSet get_differential_indices() const override
Obtain the dofs which contain time derivatives.
Definition common.hh:76
uint batch_size
Definition common.hh:339
static constexpr auto e_tie(T &&...t)
Definition common.hh:48
virtual void attach_data_output(DataOutput< dim, VectorType > &data_out, const VectorType &solution, const VectorType &variables, const VectorType &dt_solution=VectorType(), const VectorType &residual=VectorType()) override
Definition common.hh:82
std::vector< types::global_dof_index > extractor_dof_indices
Definition common.hh:350
virtual void rebuild_jacobian_sparsity()=0
FullMatrix< NumberType > extractor_jacobian_u
Definition common.hh:347
static constexpr int nothing
Definition common.hh:41
Discretization_ Discretization
Definition common.hh:55
FEMAssembler(Discretization &discretization, Model &model, const JSONValue &json)
Definition common.hh:63
A wrapper around the boost json value class.
Definition json.hh:19
Definition complex_math.hh:14
dealii::Point< dim > get_EoM_point(typename dealii::DoFHandler< dim >::cell_iterator &EoM_cell, const VectorType &sol, const dealii::DoFHandler< dim > &dof_handler, const dealii::Mapping< dim > &mapping, const EoMFUN &get_EoM, const EoMPFUN &EoM_postprocess=[](const auto &p, const auto &values) { return p;}, const double EoM_abs_tol=1e-5, const uint max_iter=100)
Get the EoM point for a given solution and model.
Definition EoM.hh:662
unsigned int uint
Definition utils.hh:22
A class to store a tuple with elements that can be accessed by name. The names are stored as FixedStr...
Definition tuples.hh:27