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 "AuxiliarySystem.h"
13 : #include "BlockRestrictable.h"
14 : #include "BoundaryRestrictable.h"
15 : #include "DerivativeMaterialPropertyNameInterface.h"
16 : #include "KernelBase.h"
17 : #include "BoundaryCondition.h"
18 : #include "Material.h"
19 : #include "MooseVariableFE.h"
20 : #include "NonlinearSystem.h"
21 :
22 : // Forward declarations
23 : class FEProblemBase;
24 : template <typename>
25 : class MaterialProperty;
26 :
27 : /**
28 : * Interface class ("Veneer") to provide generator methods for derivative
29 : * material property names
30 : */
31 : template <class T>
32 : class DerivativeMaterialInterface : public T, public DerivativeMaterialPropertyNameInterface
33 : {
34 : public:
35 : typedef DerivativeMaterialPropertyNameInterface::SymbolName SymbolName;
36 :
37 : DerivativeMaterialInterface(const InputParameters & parameters);
38 :
39 : /**
40 : * Fetch a material property if it exists, otherwise return getZeroMaterialProperty.
41 : * @param name The input parameter key of type MaterialPropertyName
42 : */
43 : template <typename U, bool is_ad = false>
44 : const GenericMaterialProperty<U, is_ad> & getDefaultMaterialProperty(const std::string & name);
45 :
46 : /// Fetch a material property by name if it exists, otherwise return getZeroMaterialProperty
47 : template <typename U, bool is_ad = false>
48 : const GenericMaterialProperty<U, is_ad> &
49 : getDefaultMaterialPropertyByName(const std::string & name);
50 :
51 : ///@{
52 : /**
53 : * Methods for declaring derivative material properties
54 : * @tparam U The material property type
55 : * @param base The name of the property to take the derivative of
56 : * @param c The variable(s) to take the derivatives with respect to
57 : */
58 : template <typename U, bool is_ad = false>
59 : GenericMaterialProperty<U, is_ad> &
60 : declarePropertyDerivative(const std::string & base, const std::vector<VariableName> & c);
61 :
62 : template <typename U, bool is_ad = false>
63 : GenericMaterialProperty<U, is_ad> & declarePropertyDerivative(const std::string & base,
64 : const std::vector<SymbolName> & c);
65 :
66 : template <typename U, bool is_ad = false>
67 : GenericMaterialProperty<U, is_ad> & declarePropertyDerivative(const std::string & base,
68 : const SymbolName & c1,
69 : const SymbolName & c2 = "",
70 : const SymbolName & c3 = "");
71 : ///@}
72 :
73 : ///@{
74 : /**
75 : * Methods for retrieving derivative material properties
76 : * @tparam U The material property type
77 : * @param base The name of the property to take the derivative of
78 : * @param c The variable(s) to take the derivatives with respect to
79 : */
80 : template <typename U, bool is_ad = false>
81 : const GenericMaterialProperty<U, is_ad> &
82 : getMaterialPropertyDerivative(const std::string & base, const std::vector<VariableName> & c);
83 :
84 : template <typename U, bool is_ad = false>
85 : const GenericMaterialProperty<U, is_ad> &
86 : getMaterialPropertyDerivative(const std::string & base, const std::vector<SymbolName> & c);
87 :
88 : template <typename U, bool is_ad = false>
89 : const GenericMaterialProperty<U, is_ad> &
90 : getMaterialPropertyDerivative(const std::string & base,
91 : const SymbolName & c1,
92 : const SymbolName & c2 = "",
93 : const SymbolName & c3 = "");
94 : ///@}
95 :
96 : /**
97 : *@{ Convenience methods for retrieving derivative material properties based
98 : * on a mix of variable names `c` and indices `v` into the
99 : * _coupled_standard_moose_vars vector.
100 : */
101 : template <typename U, bool is_ad = false>
102 : const GenericMaterialProperty<U, is_ad> &
103 : getMaterialPropertyDerivative(const std::string & base,
104 : const SymbolName & c1,
105 : unsigned int v2,
106 : unsigned int v3 = libMesh::invalid_uint);
107 :
108 : template <typename U, bool is_ad = false>
109 : const GenericMaterialProperty<U, is_ad> &
110 : getMaterialPropertyDerivative(const std::string & base,
111 : unsigned int v1,
112 : unsigned int v2 = libMesh::invalid_uint,
113 : unsigned int v3 = libMesh::invalid_uint);
114 : ///@}
115 :
116 : ///@{
117 : /**
118 : * Methods for retrieving derivative material properties
119 : * @tparam U The material property type
120 : * @param base The name of the property to take the derivative of
121 : * @param c The variable(s) to take the derivatives with respect to
122 : */
123 : template <typename U, bool is_ad = false>
124 : const GenericMaterialProperty<U, is_ad> &
125 : getMaterialPropertyDerivativeByName(const MaterialPropertyName & base,
126 : const std::vector<VariableName> & c);
127 :
128 : template <typename U, bool is_ad = false>
129 : const GenericMaterialProperty<U, is_ad> &
130 : getMaterialPropertyDerivativeByName(const MaterialPropertyName & base,
131 : const std::vector<SymbolName> & c);
132 :
133 : template <typename U, bool is_ad = false>
134 : const GenericMaterialProperty<U, is_ad> &
135 : getMaterialPropertyDerivativeByName(const MaterialPropertyName & base,
136 : const SymbolName & c1,
137 : const SymbolName & c2 = "",
138 : const SymbolName & c3 = "");
139 : ///@}
140 :
141 : ///@{
142 : /**
143 : * check if derivatives of the passed in material property exist w.r.t a variable
144 : * that is _not_ coupled in to the current object
145 : */
146 : template <typename U, bool is_ad = false>
147 : void validateCoupling(const MaterialPropertyName & base,
148 : const std::vector<VariableName> & c,
149 : bool validate_aux = true);
150 :
151 : template <typename U, bool is_ad = false>
152 : void validateCoupling(const MaterialPropertyName & base,
153 : const VariableName & c1 = "",
154 : const VariableName & c2 = "",
155 : const VariableName & c3 = "");
156 :
157 : template <typename U, bool is_ad = false>
158 : void validateNonlinearCoupling(const MaterialPropertyName & base,
159 : const VariableName & c1 = "",
160 : const VariableName & c2 = "",
161 : const VariableName & c3 = "");
162 : ///@}
163 :
164 : /**
165 : * Check if the material property base exists. Print a warning if it doesn't. This is
166 : * useful in materials that pull in only _derivative_ properties, which are optional.
167 : * If the base property name has a typo all derivatives will be set to zero without the
168 : * user ever knowing.
169 : */
170 : template <typename U, bool is_ad = false>
171 : void validateDerivativeMaterialPropertyBase(const std::string & base);
172 :
173 : private:
174 : /// Check if a material property is present with the applicable restrictions
175 : template <typename U, bool is_ad = false>
176 : bool haveMaterialProperty(const std::string & prop_name);
177 :
178 : /// helper method to combine multiple VariableNames into a vector (if they are != "")
179 : std::vector<VariableName>
180 : buildVariableVector(const VariableName & c1, const VariableName & c2, const VariableName & c3);
181 :
182 : /// helper method to compile list of missing coupled variables for a given system
183 : template <typename U, bool is_ad = false>
184 : void validateCouplingHelper(const MaterialPropertyName & base,
185 : const std::vector<VariableName> & c,
186 : const System & system,
187 : std::vector<VariableName> & missing);
188 :
189 : // check if the specified variable name is not the variable this kernel is acting on (always true
190 : // for any other type of object)
191 : bool isNotObjectVariable(const VariableName & name);
192 :
193 : /// Reference to FEProblemBase
194 : FEProblemBase & _dmi_fe_problem;
195 : };
196 :
197 : template <class T>
198 7585 : DerivativeMaterialInterface<T>::DerivativeMaterialInterface(const InputParameters & parameters)
199 : : T(parameters),
200 7585 : _dmi_fe_problem(*parameters.getCheckedPointerParam<FEProblemBase *>("_fe_problem_base"))
201 : {
202 7585 : }
203 :
204 : template <>
205 : template <typename U, bool is_ad>
206 : bool
207 11330 : DerivativeMaterialInterface<Material>::haveMaterialProperty(const std::string & prop_name)
208 : {
209 11330 : return ((this->boundaryRestricted() &&
210 22660 : this->template hasBoundaryMaterialProperty<U, is_ad>(prop_name)) ||
211 22660 : (this->template hasBlockMaterialProperty<U, is_ad>(prop_name)));
212 : }
213 :
214 : template <class T>
215 : template <typename U, bool is_ad>
216 : bool
217 2139 : DerivativeMaterialInterface<T>::haveMaterialProperty(const std::string & prop_name)
218 : {
219 : // Call the correct method to test for material property declarations
220 2139 : BlockRestrictable * blk = dynamic_cast<BlockRestrictable *>(this);
221 2139 : BoundaryRestrictable * bnd = dynamic_cast<BoundaryRestrictable *>(this);
222 0 : return ((bnd && bnd->boundaryRestricted() &&
223 2139 : bnd->template hasBoundaryMaterialProperty<U, is_ad>(prop_name)) ||
224 6381 : (blk && blk->template hasBlockMaterialProperty<U, is_ad>(prop_name)) ||
225 4242 : (this->template hasGenericMaterialProperty<U, is_ad>(prop_name)));
226 : }
227 :
228 : template <class T>
229 : template <typename U, bool is_ad>
230 : const GenericMaterialProperty<U, is_ad> &
231 1544 : DerivativeMaterialInterface<T>::getDefaultMaterialProperty(const std::string & name)
232 : {
233 : // get the base property name
234 1544 : std::string prop_name = this->getMaterialPropertyName(name);
235 :
236 : // Check if it's just a constant
237 : const auto * default_property =
238 1544 : this->template defaultGenericMaterialProperty<U, is_ad>(prop_name);
239 1544 : if (default_property)
240 0 : return *default_property;
241 :
242 : // if found return the requested property
243 1544 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(prop_name);
244 1544 : }
245 :
246 : template <class T>
247 : template <typename U, bool is_ad>
248 : const GenericMaterialProperty<U, is_ad> &
249 : DerivativeMaterialInterface<T>::getDefaultMaterialPropertyByName(const std::string & prop_name)
250 : {
251 : // TODO: deprecate this
252 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(prop_name);
253 : }
254 :
255 : template <class T>
256 : template <typename U, bool is_ad>
257 : GenericMaterialProperty<U, is_ad> &
258 741 : DerivativeMaterialInterface<T>::declarePropertyDerivative(const std::string & base,
259 : const std::vector<VariableName> & c)
260 : {
261 741 : std::vector<SymbolName> symbol_vector(c.begin(), c.end());
262 1482 : return declarePropertyDerivative<U, is_ad>(base, symbol_vector);
263 741 : }
264 :
265 : template <class T>
266 : template <typename U, bool is_ad>
267 : GenericMaterialProperty<U, is_ad> &
268 7128 : DerivativeMaterialInterface<T>::declarePropertyDerivative(const std::string & base,
269 : const std::vector<SymbolName> & c)
270 : {
271 7128 : return this->template declareGenericProperty<U, is_ad>(derivativePropertyName(base, c));
272 : }
273 :
274 : template <class T>
275 : template <typename U, bool is_ad>
276 : GenericMaterialProperty<U, is_ad> &
277 2701 : DerivativeMaterialInterface<T>::declarePropertyDerivative(const std::string & base,
278 : const SymbolName & c1,
279 : const SymbolName & c2,
280 : const SymbolName & c3)
281 : {
282 2701 : if (c3 != "")
283 720 : return this->template declareGenericProperty<U, is_ad>(
284 360 : derivativePropertyNameThird(base, c1, c2, c3));
285 2341 : if (c2 != "")
286 1956 : return this->template declareGenericProperty<U, is_ad>(
287 978 : derivativePropertyNameSecond(base, c1, c2));
288 1363 : return this->template declareGenericProperty<U, is_ad>(derivativePropertyNameFirst(base, c1));
289 : }
290 :
291 : template <class T>
292 : template <typename U, bool is_ad>
293 : const GenericMaterialProperty<U, is_ad> &
294 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivative(const std::string & base,
295 : const std::vector<VariableName> & c)
296 : {
297 : std::vector<SymbolName> symbol_vector(c.begin(), c.end());
298 : return getMaterialPropertyDerivative(base, symbol_vector);
299 : }
300 :
301 : template <class T>
302 : template <typename U, bool is_ad>
303 : const GenericMaterialProperty<U, is_ad> &
304 44 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivative(const std::string & base,
305 : const std::vector<SymbolName> & c)
306 : {
307 : // get the base property name
308 44 : std::string prop_name = this->getMaterialPropertyName(base);
309 :
310 : /**
311 : * Check if base is a default property and shortcut to returning zero, as
312 : * derivatives of constants are zero.
313 : */
314 44 : if (this->template defaultGenericMaterialProperty<U, is_ad>(prop_name))
315 0 : return this->template getGenericZeroMaterialProperty<U, is_ad>();
316 :
317 88 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
318 44 : derivativePropertyName(prop_name, c));
319 44 : }
320 :
321 : template <class T>
322 : template <typename U, bool is_ad>
323 : const GenericMaterialProperty<U, is_ad> &
324 5911 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivative(const std::string & base,
325 : const SymbolName & c1,
326 : const SymbolName & c2,
327 : const SymbolName & c3)
328 : {
329 : // get the base property name
330 5911 : std::string prop_name = this->getMaterialPropertyName(base);
331 :
332 : /**
333 : * Check if base is a default property and shortcut to returning zero, as
334 : * derivatives of constants are zero.
335 : */
336 5911 : if (this->template defaultGenericMaterialProperty<Real, is_ad>(prop_name))
337 1481 : return this->template getGenericZeroMaterialProperty<U, is_ad>();
338 :
339 4430 : if (c3 != "")
340 984 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
341 492 : derivativePropertyNameThird(prop_name, c1, c2, c3));
342 3938 : if (c2 != "")
343 1974 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
344 987 : derivativePropertyNameSecond(prop_name, c1, c2));
345 5902 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
346 2951 : derivativePropertyNameFirst(prop_name, c1));
347 5911 : }
348 :
349 : template <class T>
350 : template <typename U, bool is_ad>
351 : const GenericMaterialProperty<U, is_ad> &
352 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivative(const std::string & base,
353 : const SymbolName & c1,
354 : unsigned int v2,
355 : unsigned int v3)
356 : {
357 : return getMaterialPropertyDerivative<U, is_ad>(
358 : base,
359 : c1,
360 : this->_coupled_standard_moose_vars[v2]->name(),
361 : v3 == libMesh::invalid_uint ? "" : this->_coupled_standard_moose_vars[v3]->name());
362 : }
363 :
364 : template <class T>
365 : template <typename U, bool is_ad>
366 : const GenericMaterialProperty<U, is_ad> &
367 13 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivative(const std::string & base,
368 : unsigned int v1,
369 : unsigned int v2,
370 : unsigned int v3)
371 : {
372 39 : return getMaterialPropertyDerivative<U, is_ad>(
373 : base,
374 13 : this->_coupled_standard_moose_vars[v1]->name(),
375 26 : v2 == libMesh::invalid_uint ? "" : this->_coupled_standard_moose_vars[v2]->name(),
376 39 : v3 == libMesh::invalid_uint ? "" : this->_coupled_standard_moose_vars[v3]->name());
377 : }
378 :
379 : template <class T>
380 : template <typename U, bool is_ad>
381 : const GenericMaterialProperty<U, is_ad> &
382 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivativeByName(
383 : const MaterialPropertyName & base, const std::vector<VariableName> & c)
384 : {
385 : std::vector<SymbolName> symbol_vector(c.begin(), c.end());
386 : return getMaterialPropertyDerivativeByName(base, symbol_vector);
387 : }
388 :
389 : template <class T>
390 : template <typename U, bool is_ad>
391 : const GenericMaterialProperty<U, is_ad> &
392 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivativeByName(
393 : const MaterialPropertyName & base, const std::vector<SymbolName> & c)
394 : {
395 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
396 : derivativePropertyName(base, c));
397 : }
398 :
399 : template <class T>
400 : template <typename U, bool is_ad>
401 : const GenericMaterialProperty<U, is_ad> &
402 792 : DerivativeMaterialInterface<T>::getMaterialPropertyDerivativeByName(
403 : const MaterialPropertyName & base,
404 : const SymbolName & c1,
405 : const SymbolName & c2,
406 : const SymbolName & c3)
407 : {
408 792 : if (c3 != "")
409 264 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
410 132 : derivativePropertyNameThird(base, c1, c2, c3));
411 660 : if (c2 != "")
412 528 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
413 264 : derivativePropertyNameSecond(base, c1, c2));
414 792 : return this->template getGenericZeroMaterialPropertyByName<U, is_ad>(
415 396 : derivativePropertyNameFirst(base, c1));
416 : }
417 :
418 : template <class T>
419 : template <typename U, bool is_ad>
420 : void
421 2506 : DerivativeMaterialInterface<T>::validateCouplingHelper(const MaterialPropertyName & base,
422 : const std::vector<VariableName> & c,
423 : const System & system,
424 : std::vector<VariableName> & missing)
425 : {
426 2506 : unsigned int ncoupled = this->_coupled_standard_moose_vars.size();
427 :
428 : // iterate over all variables in the current system (in groups)
429 5667 : for (unsigned int i = 0; i < system.n_variable_groups(); ++i)
430 : {
431 3161 : const libMesh::VariableGroup & vg = system.variable_group(i);
432 16490 : for (unsigned int j = 0; j < vg.n_variables(); ++j)
433 : {
434 13329 : std::vector<SymbolName> cj(c.begin(), c.end());
435 13329 : SymbolName jname = vg.name(j);
436 13329 : cj.push_back(jname);
437 :
438 : // if the derivative exists make sure the variable is coupled
439 13329 : if (haveMaterialProperty<U, is_ad>(derivativePropertyName(base, cj)))
440 : {
441 : // kernels and BCs to not have the variable they are acting on in coupled_moose_vars
442 291 : bool is_missing = isNotObjectVariable(jname);
443 :
444 291 : for (unsigned int k = 0; k < ncoupled; ++k)
445 268 : if (this->_coupled_standard_moose_vars[k]->name() == jname)
446 : {
447 268 : is_missing = false;
448 268 : break;
449 : }
450 :
451 291 : if (is_missing)
452 0 : missing.push_back(jname);
453 : }
454 : }
455 : }
456 2506 : }
457 :
458 : template <class T>
459 : template <typename U, bool is_ad>
460 : void
461 1910 : DerivativeMaterialInterface<T>::validateCoupling(const MaterialPropertyName & base,
462 : const std::vector<VariableName> & c,
463 : bool validate_aux)
464 : {
465 : // get the base property name
466 1910 : std::string prop_name = this->getMaterialPropertyName(base);
467 : // list of potentially missing coupled variables
468 1910 : std::vector<VariableName> missing;
469 :
470 : // iterate over all variables in the both the non-linear and auxiliary system (optional)
471 1910 : validateCouplingHelper<U, is_ad>(
472 1910 : prop_name, c, _dmi_fe_problem.getNonlinearSystemBase(/*nl_sys=*/0).system(), missing);
473 1910 : if (validate_aux)
474 596 : validateCouplingHelper<U, is_ad>(
475 596 : prop_name, c, _dmi_fe_problem.getAuxiliarySystem().system(), missing);
476 :
477 1910 : if (missing.size() > 0)
478 : {
479 : // join list of missing variable names
480 0 : std::string list = missing[0];
481 0 : for (unsigned int i = 1; i < missing.size(); ++i)
482 0 : list += ", " + missing[i];
483 :
484 0 : mooseWarning("Missing coupled variables {",
485 : list,
486 : "} (add them to coupled_variables parameter of ",
487 0 : this->name(),
488 : ")");
489 0 : }
490 1910 : }
491 :
492 : template <class T>
493 : std::vector<VariableName>
494 1902 : DerivativeMaterialInterface<T>::buildVariableVector(const VariableName & c1,
495 : const VariableName & c2,
496 : const VariableName & c3)
497 : {
498 1902 : std::vector<VariableName> c;
499 1902 : if (c1 != "")
500 : {
501 0 : c.push_back(c1);
502 0 : if (c2 != "")
503 : {
504 0 : c.push_back(c2);
505 0 : if (c3 != "")
506 0 : c.push_back(c3);
507 : }
508 : }
509 1902 : return c;
510 0 : }
511 :
512 : template <class T>
513 : template <typename U, bool is_ad>
514 : void
515 588 : DerivativeMaterialInterface<T>::validateCoupling(const MaterialPropertyName & base,
516 : const VariableName & c1,
517 : const VariableName & c2,
518 : const VariableName & c3)
519 : {
520 588 : validateCoupling<U, is_ad>(base, buildVariableVector(c1, c2, c3), true);
521 588 : }
522 :
523 : template <class T>
524 : template <typename U, bool is_ad>
525 : void
526 1314 : DerivativeMaterialInterface<T>::validateNonlinearCoupling(const MaterialPropertyName & base,
527 : const VariableName & c1,
528 : const VariableName & c2,
529 : const VariableName & c3)
530 : {
531 1314 : validateCoupling<U, is_ad>(base, buildVariableVector(c1, c2, c3), false);
532 1314 : }
533 :
534 : template <class T>
535 : template <typename U, bool is_ad>
536 : void
537 140 : DerivativeMaterialInterface<T>::validateDerivativeMaterialPropertyBase(const std::string & base)
538 : {
539 : // resolve the input parameter name base to the actual material property name
540 140 : const MaterialPropertyName prop_name = this->template getParam<MaterialPropertyName>(base);
541 :
542 : // check if the material property does not exist on the blocks of the current object,
543 : // and check if it is not a plain number in the input file
544 214 : if (!haveMaterialProperty<U, is_ad>(prop_name) &&
545 74 : this->template defaultGenericMaterialProperty<U, is_ad>(prop_name) == 0)
546 16 : mooseWarning("The material property '",
547 : prop_name,
548 : "' does not exist. The kernel '",
549 8 : this->name(),
550 : "' only needs its derivatives, but this may indicate a typo in the input file.");
551 132 : }
552 :
553 : template <class T>
554 : inline bool
555 291 : DerivativeMaterialInterface<T>::isNotObjectVariable(const VariableName & name)
556 : {
557 : // try to cast this to a Kernel pointer
558 291 : KernelBase * kernel_ptr = dynamic_cast<KernelBase *>(this);
559 291 : if (kernel_ptr != nullptr)
560 36 : return kernel_ptr->variable().name() != name;
561 :
562 : // try to cast this to a BoundaryCondition pointer
563 255 : BoundaryCondition * bc_ptr = dynamic_cast<BoundaryCondition *>(this);
564 255 : if (bc_ptr != nullptr)
565 0 : return bc_ptr->variable().name() != name;
566 :
567 : // This interface is not templated on a class derived from either Kernel or BC
568 255 : return true;
569 : }
|