Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
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 : #include "KokkosMaterialPropertyStorage.h"
11 :
12 : #include "FEProblemBase.h"
13 : #include "MaterialBase.h"
14 :
15 : namespace Moose::Kokkos
16 : {
17 :
18 : std::unordered_map<std::type_index, PropertyStore> MaterialPropertyStorage::_store_functions;
19 : std::unordered_map<std::type_index, PropertyLoad> MaterialPropertyStorage::_load_functions;
20 :
21 139779 : MaterialPropertyStorage::MaterialPropertyStorage(MaterialPropertyRegistry & registry,
22 158688 : FEProblemBase & problem)
23 533904 : : ::MaterialPropertyStorage(registry, problem)
24 : {
25 139779 : }
26 :
27 : MaterialPropertyStorage &
28 10429 : MaterialPropertyStorage::cast(::MaterialPropertyStorage & storage)
29 : {
30 10429 : return static_cast<MaterialPropertyStorage &>(storage);
31 : }
32 :
33 : MaterialPropertyBase &
34 6196 : MaterialPropertyStorage::addKokkosProperty(const std::string & prop_name,
35 : const std::type_info & type,
36 : const unsigned int state,
37 : const ::MaterialBase * declarer,
38 : std::shared_ptr<MaterialPropertyBase> shell)
39 : {
40 6196 : auto id = addProperty(prop_name, type, state, declarer);
41 :
42 6196 : if (state)
43 2252 : return addKokkosPropertyState(prop_name, state, shell);
44 :
45 3944 : auto & record = _kokkos_prop_records[prop_name];
46 :
47 3944 : if (record.id == libMesh::invalid_uint)
48 : {
49 2755 : record.type = MooseUtils::prettyCppType(libMesh::demangle(type.name()));
50 2755 : record.id = id;
51 : }
52 :
53 3944 : if (declarer)
54 2990 : record.declarers.insert(declarer);
55 :
56 3944 : if (!_kokkos_props[0].count(prop_name))
57 : {
58 2755 : _kokkos_props[0][prop_name] = shell;
59 2755 : _kokkos_props[0][prop_name]->init(record, {});
60 : }
61 :
62 3944 : return *_kokkos_props[0][prop_name];
63 : }
64 :
65 : MaterialPropertyBase &
66 3239 : MaterialPropertyStorage::addKokkosPropertyState(const std::string & prop_name,
67 : const unsigned int state,
68 : std::shared_ptr<MaterialPropertyBase> shell)
69 : {
70 3239 : auto & record = _kokkos_prop_records[prop_name];
71 :
72 3239 : if (!_kokkos_props[state].count(prop_name))
73 : {
74 902 : _kokkos_props[state][prop_name] = shell;
75 902 : _kokkos_props[state][prop_name]->init(record, {});
76 : }
77 :
78 3239 : return *_kokkos_props[state][prop_name];
79 : }
80 :
81 : MaterialPropertyBase &
82 2996 : MaterialPropertyStorage::declareKokkosProperty(const std::string & prop_name,
83 : const std::type_info & type,
84 : const ::MaterialBase * declarer,
85 : const std::vector<unsigned int> & dims,
86 : const bool bnd,
87 : const bool on_demand,
88 : const PropertyConstantOption constant_option,
89 : std::shared_ptr<MaterialPropertyBase> shell)
90 : {
91 2996 : auto & record = _kokkos_prop_records[prop_name];
92 2996 : auto & blocks = declarer->boundaryRestricted() ? declarer->meshBlockIDs() : declarer->blockIDs();
93 :
94 3310 : for (const auto & [_, record_dims] : record.dims)
95 316 : if (record_dims.size() != dims.size())
96 : {
97 2 : std::stringstream ss;
98 :
99 2 : ss << "The declared " << dims.size() << "D Kokkos material property '" << prop_name << "'";
100 2 : ss << " was already declared as a " << record_dims.size() << "D property.";
101 :
102 2 : mooseError(ss.str());
103 0 : }
104 :
105 3286 : for (const auto other : record.declarers)
106 296 : if (declarer->boundaryRestricted() && other->boundaryRestricted())
107 : {
108 4 : if (auto it = record.dims.begin(); it->second != dims)
109 : {
110 2 : std::stringstream ss;
111 :
112 2 : ss << "The declared boundary-restricted Kokkos material property '" << prop_name << "'";
113 8 : ss << " with dimensions (" << Moose::stringify(dims) << ")";
114 2 : ss << " was already declared as a property";
115 8 : ss << " with dimensions (" << Moose::stringify(it->second) << ").\n";
116 0 : ss << "Currently, boundary-restricted Kokkos material properties should have the same "
117 2 : "dimension size across the entire domain.";
118 :
119 2 : mooseError(ss.str());
120 0 : }
121 :
122 2 : if (auto it = record.constant_option.begin(); it->second != constant_option)
123 : {
124 0 : static const std::unordered_map<PropertyConstantOption, std::string> option = {
125 0 : {PropertyConstantOption::NONE, "NONE"},
126 0 : {PropertyConstantOption::ELEMENT, "ELEMENT"},
127 12 : {PropertyConstantOption::SUBDOMAIN, "SUBDOMAIN"}};
128 :
129 2 : std::stringstream ss;
130 2 : std::string adding = option.at(constant_option);
131 2 : std::string existing = option.at(it->second);
132 :
133 2 : ss << "The declared boundary-restricted Kokkos material property '" << prop_name << "'";
134 2 : ss << " with constant_on = " << adding;
135 2 : ss << " was already declared as a property";
136 2 : ss << " with constant_on = " << existing << ".\n";
137 0 : ss << "Currently, boundary-restricted Kokkos material properties should have the same "
138 2 : "constant_on option across the entire domain.";
139 :
140 2 : mooseError(ss.str());
141 0 : }
142 : }
143 :
144 7318 : for (const auto block : blocks)
145 : {
146 4328 : record.dims[block] = dims;
147 4328 : record.constant_option[block] = constant_option;
148 : }
149 :
150 2990 : if (record.declarers.size())
151 : {
152 241 : if (record.on_demand != on_demand)
153 0 : mooseError(
154 : "The Kokkos material property '",
155 : prop_name,
156 : "' is being declared by multiple materials, and some of them are declaring it as an "
157 : "on-demand property while others are not.");
158 : }
159 : else
160 : {
161 2749 : record.bnd = bnd;
162 2749 : record.on_demand = on_demand;
163 : }
164 :
165 2990 : return addKokkosProperty(prop_name, type, 0, declarer, shell);
166 2 : }
167 :
168 : MaterialPropertyBase &
169 971 : MaterialPropertyStorage::getKokkosProperty(std::string prop_name, unsigned int state)
170 : {
171 971 : return *_kokkos_props[state][prop_name];
172 : }
173 :
174 : void
175 6795 : MaterialPropertyStorage::allocateKokkosProperties()
176 : {
177 6795 : auto & mesh = *_problem.mesh().getKokkosMesh();
178 6795 : auto & assembly = _problem.kokkosAssembly();
179 :
180 14492 : for (unsigned int state = 0; state < numStates(); ++state)
181 11338 : for (auto & [name, prop] : _kokkos_props[state])
182 : {
183 3641 : auto & record = _kokkos_prop_records[name];
184 :
185 3641 : if (!record.on_demand || _problem.isMatPropRequested(name))
186 7424 : for (auto * const declarer : record.declarers)
187 : {
188 1692 : auto & blocks =
189 2142 : declarer->boundaryRestricted() ? declarer->meshBlockIDs() : declarer->blockIDs();
190 :
191 3834 : prop->allocate(mesh, assembly, blocks, record.bnd, {});
192 : }
193 : }
194 6795 : }
195 :
196 : bool
197 17 : MaterialPropertyStorage::haveKokkosProperty(std::string prop_name, unsigned int state)
198 : {
199 17 : return _kokkos_props[state].count(prop_name);
200 : }
201 :
202 : void
203 2252 : MaterialPropertyStorage::registerLoadStore(std::type_index type,
204 : PropertyStore store,
205 : PropertyLoad load)
206 : {
207 2252 : _store_functions[type] = store;
208 2252 : _load_functions[type] = load;
209 2252 : }
210 :
211 : void
212 1773 : MaterialPropertyStorage::shift()
213 : {
214 4581 : for (unsigned int state = maxState(); state != 0; --state)
215 5616 : for (auto & [name, prop] : _kokkos_props[state])
216 2808 : prop->swap(*_kokkos_props[state - 1][name], {});
217 1773 : }
218 :
219 : void
220 2343 : MaterialPropertyStorage::copy()
221 : {
222 3905 : for (unsigned int state : statefulIndexRange())
223 3124 : for (auto & [name, prop] : _kokkos_props[state])
224 1562 : if (!isRestoredProperty(name))
225 1419 : prop->copy(*_kokkos_props[0][name], {});
226 2343 : }
227 :
228 : } // namespace Moose::Kokkos
229 :
230 : void
231 109134 : dataStore(std::ostream & stream, Moose::Kokkos::MaterialPropertyStorage & storage, void * context)
232 : {
233 109134 : auto & base = static_cast<MaterialPropertyStorage &>(storage);
234 :
235 109134 : dataStore(stream, base, context);
236 :
237 109134 : auto & props = storage._kokkos_props;
238 109134 : auto & records = storage._kokkos_prop_records;
239 :
240 109134 : unsigned int num_stateful_properties = 0;
241 :
242 109554 : for (auto & prop : props[0])
243 : {
244 420 : auto name = prop.first;
245 420 : auto id = records[name].id;
246 :
247 420 : if (storage.getPropRecord(id).stateful())
248 235 : num_stateful_properties++;
249 420 : }
250 :
251 109134 : dataStore(stream, num_stateful_properties, nullptr);
252 :
253 109554 : for (auto & prop : props[0])
254 : {
255 420 : auto name = prop.first;
256 420 : auto id = records[name].id;
257 :
258 420 : if (storage.getPropRecord(id).stateful())
259 : {
260 235 : dataStore(stream, name, nullptr);
261 :
262 235 : unsigned int num_states = storage.getPropRecord(id).state + 1;
263 235 : dataStore(stream, num_states, nullptr);
264 :
265 : // Store data in a temporary stream to allow skipping loading
266 235 : std::stringstream ss;
267 :
268 765 : for (unsigned int state = 0; state < num_states; ++state)
269 : {
270 530 : auto it = storage._store_functions.find(props[state][name]->propertyType());
271 : mooseAssert(it != storage._store_functions.end(),
272 : "Store function was not properly registered.");
273 :
274 530 : it->second(ss, props[state][name].get());
275 : }
276 :
277 : // Write the temporary stream to the output stream
278 235 : dataStore(stream, ss, nullptr);
279 235 : }
280 420 : }
281 109134 : }
282 :
283 : void
284 33264 : dataLoad(std::istream & stream, Moose::Kokkos::MaterialPropertyStorage & storage, void * context)
285 : {
286 33264 : auto & base = static_cast<MaterialPropertyStorage &>(storage);
287 :
288 : // All exceptions are expected to be handled here
289 33264 : dataLoad(stream, base, context);
290 :
291 33258 : auto & props = storage._kokkos_props;
292 33258 : auto & records = storage._kokkos_prop_records;
293 :
294 : unsigned int num_stateful_properties;
295 33258 : dataLoad(stream, num_stateful_properties, nullptr);
296 :
297 33410 : for (unsigned int prop = 0; prop < num_stateful_properties; ++prop)
298 : {
299 152 : std::string name;
300 152 : dataLoad(stream, name, nullptr);
301 :
302 : unsigned int num_states;
303 152 : dataLoad(stream, num_states, nullptr);
304 :
305 152 : std::stringstream ss;
306 152 : dataLoad(stream, ss, nullptr);
307 :
308 152 : if (records.count(name) && storage.getPropRecord(records[name].id).stateful())
309 369 : for (unsigned int state = 0; state < num_states; ++state)
310 : {
311 256 : auto it = storage._load_functions.find(props[state][name]->propertyType());
312 : mooseAssert(it != storage._load_functions.end(),
313 : "Load function was not properly registered.");
314 :
315 256 : it->second(ss, props[state][name].get());
316 : }
317 152 : }
318 33258 : }
|