/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/model/model.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/model/model.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
model.hh
Go to the documentation of this file.
1#pragma once
2
3// external libraries
5#include <deal.II/base/point.h>
6#include <deal.II/base/tensor.h>
7
8// standard library
9#include <cmath>
10#include <limits>
11#include <optional>
12#include <vector>
13
14// DiFfRG
17#include <DiFfRG/model/ad.hh>
21
22namespace DiFfRG
23{
24 using namespace dealii;
25
30 namespace def
31 {
33 inline constexpr int no_wave_speed = -1;
34
44 template <typename Model, typename Components_> class AbstractModel
45 {
46 Model &asImp()
47 {
48 static_assert(
49 std::is_base_of_v<AbstractModel<Model, Components_>, Model>,
50 "AbstractModel<Model, Components>: Model must inherit from AbstractModel<Model, Components> (CRTP). "
51 "Check that your model class passes itself as the first template argument.");
52 return static_cast<Model &>(*this);
53 }
54 const Model &asImp() const
55 {
56 static_assert(
57 std::is_base_of_v<AbstractModel<Model, Components_>, Model>,
58 "AbstractModel<Model, Components>: Model must inherit from AbstractModel<Model, Components> (CRTP). "
59 "Check that your model class passes itself as the first template argument.");
60 return static_cast<const Model &>(*this);
61 }
62
63 protected:
64 Components_ m_components;
65 auto &components() { return m_components; }
66
67 public:
68 const auto &get_components() const { return m_components; }
69 using Components = Components_;
74
84 template <int dim, typename Vector> void initial_condition(const Point<dim> &x, Vector &u_i) const = delete;
85
103 template <int dim, typename NumberType, typename Vector, typename Vector_dot, size_t n_fe_functions>
104 void mass([[maybe_unused]] std::array<NumberType, n_fe_functions> &m_i, [[maybe_unused]] const Point<dim> &x,
105 [[maybe_unused]] const Vector &u_i, const Vector_dot &dt_u_i) const
106 {
107 for (uint i = 0; i < n_fe_functions; ++i)
108 m_i[i] = dt_u_i[i];
109 }
110
125 template <int dim, typename NumberType, size_t n_fe_functions>
126 void mass(std::array<std::array<NumberType, n_fe_functions>, n_fe_functions> &m_ij,
127 [[maybe_unused]] const Point<dim> &x) const
128 {
129 for (uint i = 0; i < n_fe_functions; ++i)
130 for (uint j = 0; j < n_fe_functions; ++j)
131 m_ij[i][j] = 0.;
132 for (uint i = 0; i < n_fe_functions; ++i)
133 m_ij[i][i] = 1.;
134 }
135
171 template <int dim, typename NumberType, typename Solutions, size_t n_fe_functions>
172 void flux([[maybe_unused]] std::array<Tensor<1, dim, NumberType>, n_fe_functions> &F_i,
173 [[maybe_unused]] const Point<dim> &x, [[maybe_unused]] const Solutions &sol) const
174 {
175 }
176
205 template <int dim, typename NumberType, typename Solutions, size_t n_fe_functions>
206 void diffusion_flux([[maybe_unused]] std::array<Tensor<1, dim, NumberType>, n_fe_functions> &F_i,
207 [[maybe_unused]] const Point<dim> &x, [[maybe_unused]] const Solutions &sol) const
208 {
209 }
210
235 template <int dim, typename NumberType, typename Solutions, size_t n_fe_functions>
236 void source([[maybe_unused]] std::array<NumberType, n_fe_functions> &s_i, [[maybe_unused]] const Point<dim> &x,
237 [[maybe_unused]] const Solutions &sol) const
238 {
239 }
240
250 template <uint dim> std::vector<bool> differential_components() const
251 {
252 std::vector<bool> differential_components(Model::Components::count_fe_functions(), false);
253
254 // First we need two reference solutions u_i and dt_u_i, which we then both fill with 1.s
255 std::array<double, Model::Components::count_fe_functions()> u_i{{}};
256 std::array<double, Model::Components::count_fe_functions()> dt_u_i{{}};
257 for (uint i = 0; i < Model::Components::count_fe_functions(); ++i) {
258 u_i[i] = 1.;
259 dt_u_i[i] = 1.;
260 }
261 // Set the point to be at 1. in all directions
262 Point<dim> x;
263 for (uint i = 0; i < dim; ++i)
264 x[i] = 1.;
265 // Get the mass function m_i
266 std::array<double, Model::Components::count_fe_functions()> m_i{{}};
267 asImp().mass(m_i, x, u_i, dt_u_i);
268
269 // Now we check which components are differential by changing dt_u_i slightly and checking whether the mass
270 // function changes.
271 for (uint i = 0; i < Model::Components::count_fe_functions(); ++i) {
272 dt_u_i[i] = 1. + 1e-1;
273 std::array<double, Model::Components::count_fe_functions()> m_i_new{{}};
274 asImp().mass(m_i_new, x, u_i, dt_u_i);
275 dt_u_i[i] = 1.;
276 for (uint j = 0; j < Model::Components::count_fe_functions(); ++j)
277 if (!is_close(m_i[j], m_i_new[j])) differential_components[j] = true;
278 }
279
281 }
282
322 template <size_t n_fe_functions> void wave_speed_blocks(std::array<int, n_fe_functions> &blocks) const
323 {
324 blocks.fill(0);
325 }
326
328
332
333 template <typename Vector> void initial_condition_variables([[maybe_unused]] Vector &v_a) const
334 {
335 // Just to avoid warnings
336 }
337
338 template <typename Vector, typename Solution>
339 void dt_variables([[maybe_unused]] Vector &r_a, [[maybe_unused]] const Solution &sol) const
340 {
341 // Just to avoid warnings
342 }
343
345
349
359 template <int dim, typename Vector, typename Solutions>
360 void extract([[maybe_unused]] Vector &result, [[maybe_unused]] const Point<dim> &x,
361 [[maybe_unused]] const Solutions &sol) const
362 {
363 }
364
366
370
393 template <uint dependent, int dim, typename NumberType, typename Vector, size_t n_fe_functions_dep>
394 void ldg_flux([[maybe_unused]] std::array<Tensor<1, dim, NumberType>, n_fe_functions_dep> &F,
395 [[maybe_unused]] const Point<dim> &x, [[maybe_unused]] const Vector &u) const
396 {
397 }
398
421 template <uint dependent, int dim, typename NumberType, typename Vector, size_t n_fe_functions_dep>
422 void ldg_source([[maybe_unused]] std::array<NumberType, n_fe_functions_dep> &s,
423 [[maybe_unused]] const Point<dim> &x, [[maybe_unused]] const Vector &u) const
424 {
425 }
426
427 template <int dim, typename NumberType, typename Solutions_s, typename Solutions_n>
428 void face_indicator([[maybe_unused]] std::array<NumberType, 2> &indicator,
429 [[maybe_unused]] const Tensor<1, dim> &normal, [[maybe_unused]] const Point<dim> &p,
430 [[maybe_unused]] const Solutions_s &sol_s, [[maybe_unused]] const Solutions_n &sol_n) const
431 {
432 }
433
434 template <int dim, typename NumberType, typename Solution>
435 void cell_indicator([[maybe_unused]] NumberType &indicator, [[maybe_unused]] const Point<dim> &p,
436 [[maybe_unused]] const Solution &sol) const
437 {
438 }
439
440 template <int dim, typename Vector>
441 std::array<double, dim> EoM([[maybe_unused]] const Point<dim> &x, const Vector &u) const
442 {
443 return std::array<double, dim>{{u[0]}};
444 }
445
456 static constexpr bool extract_uses_potential = true;
457
466 template <int dim, typename Vector>
467 std::array<double, dim> raw_potential_gradient([[maybe_unused]] const Point<dim> &x, const Vector &u) const
468 {
469 std::array<double, dim> gradient{};
470 for (uint d = 0; d < dim && d < u.size(); ++d)
471 gradient[d] = u[d];
472 return gradient;
473 }
474
483 template <int dim, typename Vector> Point<dim> EoM_postprocess(const Point<dim> &EoM, const Vector &) const
484 {
485 return EoM;
486 }
487
488 template <typename FUN, typename DataOut> void readouts_multiple(FUN &helper, DataOut &) const
489 {
490 helper(
491 "primary", [&](const auto &x, const auto &u_i) { return asImp().EoM(x, u_i); }, // chiral EoM
492 [&](auto &output, const auto &x, const auto &sol) { asImp().readouts(output, x, sol); });
493 }
494
495 template <int dim, typename DataOut, typename Solutions>
496 void readouts([[maybe_unused]] DataOut &output, [[maybe_unused]] const Point<dim> &x,
497 [[maybe_unused]] const Solutions &sol) const
498 {
499 }
500
513 template <typename Constraints, typename Context>
514 void affine_constraints(Constraints &constraints, const Context &context) const
515 {
516 if constexpr (requires(const Model &model, Constraints &constraint_matrix,
517 const Context &affine_constraint_context) {
518 model.apply_boundary_affine_constraints(constraint_matrix, affine_constraint_context);
519 })
520 asImp().apply_boundary_affine_constraints(constraints, context);
521 if constexpr (requires(const Model &model, Constraints &constraint_matrix,
522 const Context &affine_constraint_context) {
523 model.apply_affine_constraints(constraint_matrix, affine_constraint_context);
524 })
525 asImp().apply_affine_constraints(constraints, context);
526 }
527 };
528
529 namespace internal
530 {
531 template <typename> inline constexpr bool dependent_false_v = false;
532
533 template <FixedString component_name, typename Model, int dim>
534 double origin_constraint_coordinate(const Point<dim> &point)
535 {
536 if constexpr (dim == 1) {
537 return point[0];
538 } else {
539 if constexpr (requires {
540 Model::template OriginConstraintCoordinate<component_name>::signed_coordinate(point);
541 }) {
542 return Model::template OriginConstraintCoordinate<component_name>::signed_coordinate(point);
543 } else {
544 static_assert(dependent_false_v<Model>,
545 "Multidimensional origin affine-constraint helpers require Model::"
546 "OriginConstraintCoordinate<component_name>::signed_coordinate(point).");
547 return 0.0;
548 }
549 }
550 }
551
552 template <FixedString component_name, typename Model, typename Context>
553 std::vector<types::global_dof_index> select_origin_candidates([[maybe_unused]] const Context &context,
554 const auto &view)
555 {
556 constexpr int dim = Context::dimension;
557 static_assert(dim == 1 || dim == 2,
558 "Origin affine-constraint helpers currently support only one- and two-dimensional domains.");
559 static_assert(Context::template component_size<component_name>() == 1,
560 "Origin affine-constraint helpers require a scalar FE-function component.");
561
562 double best_abs_coordinate = std::numeric_limits<double>::infinity();
563 bool has_non_negative_best = false;
564
565 for (uint i = 0; i < view.dofs.n_elements(); ++i) {
566 const double coordinate = origin_constraint_coordinate<component_name, Model>(view.points[i]);
567 const double abs_coordinate = std::abs(coordinate);
568 if (abs_coordinate < best_abs_coordinate) {
569 best_abs_coordinate = abs_coordinate;
570 has_non_negative_best = coordinate >= 0.0;
571 } else if (abs_coordinate == best_abs_coordinate && coordinate >= 0.0) {
572 has_non_negative_best = true;
573 }
574 }
575
576 std::vector<types::global_dof_index> candidates;
577 for (uint i = 0; i < view.dofs.n_elements(); ++i) {
578 const double coordinate = origin_constraint_coordinate<component_name, Model>(view.points[i]);
579 const double abs_coordinate = std::abs(coordinate);
580 if (abs_coordinate != best_abs_coordinate) continue;
581 if ((coordinate >= 0.0) != has_non_negative_best) continue;
582 candidates.push_back(view.dofs.nth_index_in_set(i));
583 }
584
585 return candidates;
586 }
587
588 template <FixedString component_name, typename Context>
589 std::optional<types::global_dof_index> select_origin_candidate(const Context &context, const auto &view)
590 {
591 constexpr int dim = Context::dimension;
592 static_assert(dim == 1, "select_origin_candidate supports only one-dimensional domains; use "
593 "select_origin_candidates for multi-dimensional domains.");
594
595 const auto candidates = select_origin_candidates<component_name, void>(context, view);
596 if (candidates.empty()) return std::nullopt;
597 return candidates.front();
598 }
599 } // namespace internal
600
609 template <FixedString component_name, typename Model> class ConstrainOriginBoundaryPointToZero
610 {
611 public:
612 template <typename Constraints, typename Context>
613 void apply_boundary_affine_constraints(Constraints &constraints, const Context &context) const
614 {
616 context, context.template boundary<component_name>());
617 for (const auto dof : candidates) {
618 constraints.add_line(dof);
619 constraints.set_inhomogeneity(dof, 0.0);
620 }
621 }
622 };
623
631 template <FixedString component_name, typename Model> class ConstrainOriginSupportPointToZero
632 {
633 public:
634 template <typename Constraints, typename Context>
635 void apply_affine_constraints(Constraints &constraints, const Context &context) const
636 {
638 context, context.template support<component_name>());
639 for (const auto dof : candidates) {
640 constraints.add_line(dof);
641 constraints.set_inhomogeneity(dof, 0.0);
642 }
643 }
644 };
645
646 template <typename Model> class NoAffineConstraints
647 {
648 };
649
650 class Time
651 {
652 public:
653 void set_time(double t);
654 const double &get_time() const;
655
656 protected:
657 // Initialized, like fRG::t below: a model is routinely built and read before the timestepper
658 // first calls set_time(), and an indeterminate t is a bug that only shows up once the memory
659 // happens to be dirty.
660 double t = 0.;
661 };
662
666 class fRG
667 {
668 public:
674 fRG(double Lambda);
675
682
688 void set_time(double t);
689
695 const double &get_time() const;
696
697 protected:
698 const double Lambda;
699 double t = 0., k = 0., k2 = 0., k3 = 0., k4 = 0., k5 = 0., k6 = 0.;
700 bool time_initialized = false;
701 };
702 } // namespace def
703} // namespace DiFfRG
A hierarchical configuration tree, readable from JSON and TOML files.
Definition config_tree.hh:32
The abstract interface for any numerical model. Most methods have a standard implementation,...
Definition model.hh:45
std::vector< bool > differential_components() const
A method to find out which components of the mass function are differential when using a DAE.
Definition model.hh:250
void dt_variables(Vector &r_a, const Solution &sol) const
Definition model.hh:339
std::array< double, dim > raw_potential_gradient(const Point< dim > &x, const Vector &u) const
The unmodified gradient of the scalar potential reconstructed for readouts and extractors.
Definition model.hh:467
void source(std::array< NumberType, n_fe_functions > &s_i, const Point< dim > &x, const Solutions &sol) const
The source function is implemented by this method.
Definition model.hh:236
void diffusion_flux(std::array< Tensor< 1, dim, NumberType >, n_fe_functions > &F_i, const Point< dim > &x, const Solutions &sol) const
If the Kurganov Tadmor Scheme is used, this is the implementation of the diffusion (parabolic) part o...
Definition model.hh:206
auto & components()
Definition model.hh:65
const Model & asImp() const
Definition model.hh:54
Components_ m_components
Definition model.hh:64
void mass(std::array< std::array< NumberType, n_fe_functions >, n_fe_functions > &m_ij, const Point< dim > &x) const
If not using a DAE, the mass matrix is implemented in this method.
Definition model.hh:126
Model & asImp()
Definition model.hh:46
void extract(Vector &result, const Point< dim > &x, const Solutions &sol) const
Read data off the FE solution at a single point and hand it to the Variables.
Definition model.hh:360
const auto & get_components() const
Definition model.hh:68
void flux(std::array< Tensor< 1, dim, NumberType >, n_fe_functions > &F_i, const Point< dim > &x, const Solutions &sol) const
The flux function is implemented by this method.
Definition model.hh:172
void cell_indicator(NumberType &indicator, const Point< dim > &p, const Solution &sol) const
Definition model.hh:435
void ldg_flux(std::array< Tensor< 1, dim, NumberType >, n_fe_functions_dep > &F, const Point< dim > &x, const Vector &u) const
The LDG flux function is implemented by this method.
Definition model.hh:394
void affine_constraints(Constraints &constraints, const Context &context) const
Add affine constraints to the FE/DG system before sparsity patterns and operators are rebuilt.
Definition model.hh:514
void wave_speed_blocks(std::array< int, n_fe_functions > &blocks) const
Which FE components share a wave speed, and which carry no hyperbolic flux at all.
Definition model.hh:322
void mass(std::array< NumberType, n_fe_functions > &m_i, const Point< dim > &x, const Vector &u_i, const Vector_dot &dt_u_i) const
The mass function is implemented in this method.
Definition model.hh:104
void readouts_multiple(FUN &helper, DataOut &) const
Definition model.hh:488
void initial_condition(const Point< dim > &x, Vector &u_i) const =delete
This method implements the initial condition for the FE functions.
void ldg_source(std::array< NumberType, n_fe_functions_dep > &s, const Point< dim > &x, const Vector &u) const
The LDG source function is implemented by this method.
Definition model.hh:422
std::array< double, dim > EoM(const Point< dim > &x, const Vector &u) const
Definition model.hh:441
void initial_condition_variables(Vector &v_a) const
Definition model.hh:333
void readouts(DataOut &output, const Point< dim > &x, const Solutions &sol) const
Definition model.hh:496
Point< dim > EoM_postprocess(const Point< dim > &EoM, const Vector &) const
Relocate the point found by the EoM search, given the solution values there.
Definition model.hh:483
void face_indicator(std::array< NumberType, 2 > &indicator, const Tensor< 1, dim > &normal, const Point< dim > &p, const Solutions_s &sol_s, const Solutions_n &sol_n) const
Definition model.hh:428
Components_ Components
Definition model.hh:69
static constexpr bool extract_uses_potential
Whether extract() reads the reconstructed potential handed to it.
Definition model.hh:456
Constrain the boundary dofs of a named scalar FE-function component nearest its origin coordinate to ...
Definition model.hh:610
void apply_boundary_affine_constraints(Constraints &constraints, const Context &context) const
Definition model.hh:613
Constrain the support dofs of a named scalar FE-function component nearest its origin coordinate to z...
Definition model.hh:632
void apply_affine_constraints(Constraints &constraints, const Context &context) const
Definition model.hh:635
Definition model.hh:647
Definition model.hh:651
const double & get_time() const
void set_time(double t)
double t
Definition model.hh:660
The fRG class is used to keep track of the RG time and the cutoff scale.
Definition model.hh:667
double k3
Definition model.hh:699
double k
Definition model.hh:699
double k4
Definition model.hh:699
double k6
Definition model.hh:699
double t
Definition model.hh:699
fRG(double Lambda)
Construct a new fRG object from a given initial cutoff scale.
fRG(const ConfigTree &config)
Construct a new fRG object from a given ConfigTree object.
double k5
Definition model.hh:699
const double Lambda
Definition model.hh:698
bool time_initialized
Definition model.hh:700
void set_time(double t)
Set the time of the fRG object, updating the cutoff scale and its powers.
const double & get_time() const
Get the time of the fRG object.
double k2
Definition model.hh:699
constexpr bool dependent_false_v
Definition model.hh:531
std::vector< types::global_dof_index > select_origin_candidates(const Context &context, const auto &view)
Definition model.hh:553
double origin_constraint_coordinate(const Point< dim > &point)
Definition model.hh:534
std::optional< types::global_dof_index > select_origin_candidate(const Context &context, const auto &view)
Definition model.hh:589
constexpr int no_wave_speed
Block id for a component that carries no hyperbolic flux.
Definition model.hh:33
Definition complex_math.hh:10
@ config
/discretization/threads.
unsigned int uint
Definition utils.hh:24
bool KOKKOS_INLINE_FUNCTION is_close(T1 a, T2 b, T3 eps_)
Function to evaluate whether two floats are equal to numerical precision. Tests for both relative and...
Definition math.hh:177