Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : #include "Material.h"
13 : #include "CompileTimeDerivatives.h"
14 : #include "DerivativeMaterialInterface.h"
15 : #include "CompileTimeDerivativesMaterialInternal.h"
16 :
17 : /**
18 : * @brief Material class to set up an expression and its derivatives built at compile time using the
19 : * CompileTimeDerivatives framework.
20 : * @tparam N number of coupled variables
21 : * @tparam is_ad whether to use forward mode automatic differentiation and to generate Moose AD
22 : * material properties
23 : * @tparam MaxD maximum derivative order to build
24 : */
25 : template <int N, bool is_ad = false, int MaxD = 3>
26 : class CompileTimeDerivativesMaterial : public DerivativeMaterialInterface<Material>
27 : {
28 : public:
29 : CompileTimeDerivativesMaterial(const InputParameters & params,
30 : const std::array<std::string, N> variables);
31 : static InputParameters validParams();
32 :
33 : protected:
34 : /**
35 : * Entry point for the compile time loop that evaluates all derivatives and assigns them to their
36 : * respective material properties
37 : * @arg F the compile time derivative expression object
38 : */
39 : template <typename T>
40 : void evaluate(const T & F);
41 :
42 : const MaterialPropertyName _F_name;
43 : GenericMaterialProperty<Real, is_ad> & _prop_F;
44 :
45 : /**
46 : * The names of the coupled variables
47 : */
48 : std::array<VariableName, N> _var_name;
49 :
50 : /**
51 : * A serialized list of material properties for all derivatives up to and including order MaxD
52 : */
53 : std::array<GenericMaterialProperty<Real, is_ad> *,
54 : CompileTimeDerivativesMaterialInternal::total_derivatives<MaxD, N>()>
55 : _prop_dF;
56 :
57 : /**
58 : * Set up a tuple with one entry per coupled variable (each entry with an increment). The coupled
59 : * variables are wrapped in a CTD reference object with a different tag for differentiation. This
60 : * makes each reference a different type, so we need to store them in a tuple (as opposed to an
61 : * array).
62 : */
63 : typename decltype(CompileTimeDerivativesMaterialInternal::make_tuple_array<
64 : GenericVariableValue<is_ad>>(std::make_index_sequence<N>{}))::type _refs;
65 :
66 : private:
67 : template <std::size_t... Ns>
68 39 : auto makeRefsTuple(const std::array<std::string, N> & variables,
69 : const unsigned int & qp,
70 : std::index_sequence<Ns...>)
71 : {
72 : return std::make_tuple(
73 78 : CompileTimeDerivatives::makeRef<Ns>(coupledGenericValue<is_ad>(variables[Ns]), qp)...);
74 : }
75 :
76 : template <std::size_t I>
77 39 : constexpr void loopDeclareProperties(std::index_sequence<>)
78 : {
79 39 : }
80 : template <std::size_t I, std::size_t first, std::size_t... tail>
81 1521 : constexpr void loopDeclareProperties(std::index_sequence<first, tail...> int_seq)
82 : {
83 : using namespace CompileTimeDerivativesMaterialInternal;
84 : if constexpr (is_sorted(int_seq))
85 : {
86 2496 : _prop_dF[I] = &declarePropertyDerivative<Real, is_ad>(
87 1755 : _F_name, std::vector<VariableName>{_var_name[first], _var_name[tail]...});
88 741 : loopDeclareProperties<I + 1>(details::increment<N>(int_seq));
89 : }
90 : else
91 780 : loopDeclareProperties<I>(details::increment<N>(int_seq));
92 2262 : }
93 :
94 : /**
95 : * Entry point for the compile time loop that declares all derivative material properties
96 : */
97 39 : void declareProperties()
98 : {
99 : using namespace CompileTimeDerivativesMaterialInternal;
100 39 : loopDeclareProperties<0>(zeroes<MaxD>());
101 39 : }
102 :
103 : template <std::size_t I, typename T>
104 512 : constexpr void loopEvaluate(const T &, std::index_sequence<>)
105 : {
106 512 : }
107 : template <std::size_t I, typename T, std::size_t first, std::size_t... tail>
108 19968 : constexpr void loopEvaluate(const T & expression, std::index_sequence<first, tail...> int_seq)
109 : {
110 : using namespace CompileTimeDerivativesMaterialInternal;
111 : if constexpr (is_sorted(int_seq))
112 : {
113 9728 : (*_prop_dF[I])[_qp] = take_derivatives(expression, int_seq)();
114 9728 : loopEvaluate<I + 1>(expression, details::increment<N>(int_seq));
115 : }
116 : else
117 10240 : loopEvaluate<I>(expression, details::increment<N>(int_seq));
118 19968 : }
119 : };
120 :
121 : template <int N, bool is_ad, int MaxD>
122 : InputParameters
123 14314 : CompileTimeDerivativesMaterial<N, is_ad, MaxD>::validParams()
124 : {
125 14314 : auto params = DerivativeMaterialInterface<Material>::validParams();
126 14314 : params.addRequiredParam<MaterialPropertyName>("property_name",
127 : "Name of the parsed material property");
128 14314 : return params;
129 0 : }
130 :
131 : template <int N, bool is_ad, int MaxD>
132 39 : CompileTimeDerivativesMaterial<N, is_ad, MaxD>::CompileTimeDerivativesMaterial(
133 : const InputParameters & params, const std::array<std::string, N> variables)
134 : : DerivativeMaterialInterface<Material>(params),
135 39 : _F_name(getParam<MaterialPropertyName>("property_name")),
136 39 : _prop_F(declareGenericProperty<Real, is_ad>(_F_name)),
137 78 : _refs(makeRefsTuple(variables, _qp, std::make_index_sequence<N>{}))
138 : {
139 : // get the names of all coupled variables
140 156 : for (const auto i : make_range(N))
141 117 : _var_name[i] = coupledName(variables[i]);
142 :
143 : // declare all material properties
144 39 : declareProperties();
145 39 : }
146 :
147 : template <int N, bool is_ad, int MaxD>
148 : template <typename T>
149 : void
150 512 : CompileTimeDerivativesMaterial<N, is_ad, MaxD>::evaluate(const T & F)
151 : {
152 512 : _prop_F[_qp] = F();
153 : using namespace CompileTimeDerivativesMaterialInternal;
154 512 : loopEvaluate<0>(F, zeroes<MaxD>());
155 512 : }
|