OGS
TangentOperatorBlocksView.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <MGIS/Behaviour/Variable.hxx>
14#include <boost/mp11.hpp>
15#include <range/v3/view/enumerate.hpp>
16#include <range/v3/view/filter.hpp>
17#include <range/v3/view/map.hpp>
18#include <range/v3/view/zip.hpp>
19
20#include "BaseLib/cpp23.h"
23
25{
26namespace detail
27{
31static constexpr std::array<double, 3 * 3 * 3 * 3>
33} // namespace detail
34
37{
38 std::vector<double> data;
39};
40
63template <typename Gradients, typename TDynForces, typename ExtStateVars>
65{
66 static_assert(boost::mp11::mp_is_set<Gradients>::value);
67 static_assert(boost::mp11::mp_is_set<TDynForces>::value);
68 static_assert(boost::mp11::mp_is_set<ExtStateVars>::value);
69
71 boost::mp11::mp_append<Gradients, ExtStateVars>;
72
73 static_assert(boost::mp11::mp_is_set<GradientsAndExtStateVars>::value);
74
75 using type = boost::mp11::
76 mp_product<boost::mp11::mp_list, TDynForces, GradientsAndExtStateVars>;
77};
78
92template <int DisplacementDim, typename ForcesGradsCombinations>
94{
95 static_assert(boost::mp11::mp_is_set<ForcesGradsCombinations>::value);
96
99 static constexpr std::size_t invalid_offset_ = -1;
100
101public:
105 std::vector<std::pair<mgis::behaviour::Variable,
106 mgis::behaviour::Variable>> const& to_blocks)
107 {
109
110 std::vector<bool> used_blocks(
111 to_blocks.size(), false); // checked after creation of all offsets.
112
113 boost::mp11::mp_for_each<ForcesGradsCombinations>(
114 [&to_blocks,
115 &used_blocks,
116 this]<typename Force, typename GradOrExtStateVar>(
117 boost::mp11::mp_list<Force, GradOrExtStateVar>)
118 {
119 std::size_t data_offset = 0;
120 for (auto [block, is_used] :
121 ranges::views::zip(to_blocks, used_blocks))
122 {
123 auto const& [force, grad] = block;
124 if (force.name == Force::name &&
125 grad.name == GradOrExtStateVar::name)
126 {
127 auto constexpr block_idx =
128 blockIndex<Force, GradOrExtStateVar>();
129 offsets_[block_idx] = data_offset;
130 is_used = true;
131 return;
132 }
133
134 data_offset += size(force.type) * size(grad.type);
135 }
136 });
137
138 // Indices of unused blocks.
139 auto indices = ranges::views::enumerate(used_blocks) |
140 ranges::views::filter([](auto const& pair)
141 { return !pair.second; }) |
142 ranges::views::keys;
143
144 if (!indices.empty())
145 {
146 ERR("There are unused tangent operator blocks provided by MFront. "
147 "Following blocks are unused:");
148
149 for (auto const i : indices)
150 {
151 auto const& [force, grad] = to_blocks[i];
152 ERR("\t{}/{}", force.name, grad.name);
153 }
154 OGS_FATAL("All tangent operator blocks must be used.");
155 }
156 }
157
164 template <typename Force, typename GradOrExtStateVar>
165 auto block(Force,
166 GradOrExtStateVar,
167 OGSMFrontTangentOperatorData const& data) const
168 {
169 static_assert(
170 boost::mp11::mp_contains<
172 boost::mp11::mp_list<Force, GradOrExtStateVar>>::value,
173 "Requested tangent block was not created in the "
174 "OGSMFrontTangentOperatorBlocksView.");
175
176 constexpr auto index = blockIndex<Force, GradOrExtStateVar>();
177 const auto offset = offsets_[index];
178
179 constexpr auto force_size = Force::template size<DisplacementDim>();
180 constexpr auto grad_size =
181 GradOrExtStateVar::template size<DisplacementDim>();
182
183 if constexpr (grad_size == 1 && force_size == 1)
184 {
185 if (offset == invalid_offset_)
186 {
187 return 0.0;
188 }
189
190 return data.data[offset];
191 }
192 else
193 {
194 constexpr auto order =
195 grad_size == 1 ? Eigen::ColMajor : Eigen::RowMajor;
196
197 using Result = Eigen::Map<
198 const Eigen::Matrix<double, force_size, grad_size, order>>;
199
200 if (offset == invalid_offset_)
201 {
202 return Result{
204 }
205
206 return Result{data.data.data() + offset};
207 }
208 }
209
210private:
211 static constexpr std::size_t size(mgis::behaviour::Variable::Type vt)
212 {
213 using VT = mgis::behaviour::Variable::Type;
214
215 switch (vt)
216 {
217 case VT::SCALAR:
218 return 1;
219 case VT::STENSOR:
221 DisplacementDim);
222 case VT::VECTOR:
223 return DisplacementDim;
224 case VT::TENSOR:
225 return MaterialPropertyLib::tensorSize(DisplacementDim);
226 }
227
228 OGS_FATAL("Unsupported variable type {}", BaseLib::to_underlying(vt));
229 }
230
232 template <typename Force, typename GradOrExtStateVar>
233 static constexpr std::size_t blockIndex()
234 {
235 return boost::mp11::mp_find<
237 boost::mp11::mp_list<Force, GradOrExtStateVar>>::value;
238 }
239
244 std::array<std::size_t,
245 boost::mp11::mp_size<ForcesGradsCombinations>::value>
247};
248} // namespace MaterialLib::Solids::MFront
#define OGS_FATAL(...)
Definition Error.h:26
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
OGSMFrontTangentOperatorBlocksView(std::vector< std::pair< mgis::behaviour::Variable, mgis::behaviour::Variable > > const &to_blocks)
static constexpr std::size_t size(mgis::behaviour::Variable::Type vt)
static constexpr std::size_t blockIndex()
Computes the index of a tangent operator block in the offsets_ array.
std::array< std::size_t, boost::mp11::mp_size< ForcesGradsCombinations >::value > offsets_
auto block(Force, GradOrExtStateVar, OGSMFrontTangentOperatorData const &data) const
constexpr auto to_underlying(E e) noexcept
Converts an enumeration to its underlying type.
Definition cpp23.h:29
static constexpr std::array< double, 3 *3 *3 *3 > OGSMFrontTangentOperatorBlocksViewZeroes
constexpr int tensorSize(int dim)
See Tensor type for details.
Definition Tensor.h:19
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
boost::mp11:: mp_product< boost::mp11::mp_list, TDynForces, GradientsAndExtStateVars > type
boost::mp11::mp_append< Gradients, ExtStateVars > GradientsAndExtStateVars
Used for disambiguation with MFront's thermodynamic forces data.