www.mooseframework.org
DerivativeParsedMaterialHelper.C
Go to the documentation of this file.
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 
11 #include "Conversion.h"
12 
13 #include <deque>
14 
15 #include "libmesh/quadrature.h"
16 
17 template <>
20 {
22  params.addClassDescription("Parsed Function Material with automatic derivatives.");
23  params.addDeprecatedParam<bool>("third_derivatives",
24  "Flag to indicate if third derivatives are needed",
25  "Use derivative_order instead.");
26  params.addParam<unsigned int>("derivative_order", 3, "Maximum order of derivatives taken");
27 
28  return params;
29 }
30 
32  VariableNameMappingMode map_mode)
33  : ParsedMaterialHelper(parameters, map_mode),
34  //_derivative_order(getParam<unsigned int>("derivative_order"))
35  _dmatvar_base("matpropautoderiv"),
36  _dmatvar_index(0),
37  _derivative_order(isParamValid("third_derivatives")
38  ? (getParam<bool>("third_derivatives") ? 3 : 2)
39  : getParam<unsigned int>("derivative_order"))
40 {
41 }
42 
43 void
45 {
46  // optimize base function
48 
49  // generate derivatives
51 
52  // force a value update to get the property at least once and register it for the dependencies
53  for (auto & mpd : _mat_prop_descriptors)
54  mpd.value();
55 }
56 
57 ParsedMaterialHelper::MatPropDescriptorList::iterator
59 {
60  std::string name = m.getPropertyName();
61  for (MatPropDescriptorList::iterator i = _mat_prop_descriptors.begin();
62  i != _mat_prop_descriptors.end();
63  ++i)
64  if (i->getPropertyName() == name)
65  return i;
66 
67  return _mat_prop_descriptors.end();
68 }
69 
73 void
75 {
76  // need to check for zero derivatives here, otherwise at least one order is generated
77  if (_derivative_order < 1)
78  return;
79 
80  // if we are not on thread 0 we fetch all data from the thread 0 copy that already did all the
81  // work
82  if (_tid > 0)
83  {
84  // get the master object from thread 0
85  const MaterialWarehouse & material_warehouse = _fe_problem.getMaterialWarehouse();
86  const MooseObjectWarehouse<Material> & warehouse = material_warehouse[_material_data_type];
87 
88  MooseSharedPointer<DerivativeParsedMaterialHelper> master =
90  warehouse.getActiveObject(name()));
91 
92  // copy parsers and declare properties
93  for (MooseIndex(master->_derivatives) i = 0; i < master->_derivatives.size(); ++i)
94  {
95  Derivative newderivative;
96  newderivative.first =
97  &declarePropertyDerivative<Real>(_F_name, master->_derivatives[i].darg_names);
98  newderivative.second = ADFunctionPtr(new ADFunction(*master->_derivatives[i].second));
99  _derivatives.push_back(newderivative);
100  }
101 
102  // copy coupled material properties
103  auto start = _mat_prop_descriptors.size();
104  for (MooseIndex(master->_mat_prop_descriptors) i = start;
105  i < master->_mat_prop_descriptors.size();
106  ++i)
107  {
108  FunctionMaterialPropertyDescriptor newdescriptor(master->_mat_prop_descriptors[i], this);
109  _mat_prop_descriptors.push_back(newdescriptor);
110  }
111 
112  // size parameter buffer
113  _func_params.resize(master->_func_params.size());
114  return;
115  }
116 
117  // set up job queue. We need a deque here to be able to iterate over the currently queued items.
118  std::deque<QueueItem> queue;
119  queue.push_back(QueueItem(_func_F));
120 
121  // generate derivatives until the queue is exhausted
122  while (!queue.empty())
123  {
124  QueueItem current = queue.front();
125 
126  // Add necessary derivative steps. All permutations of one set of derivatives are equal, so we
127  // make sure to generate only one each.
128  for (auto i = current._dargs.empty() ? 0u : current._dargs.back(); i < _nargs; ++i)
129  {
130  // go through list of material properties and check if derivatives are needed
131  auto ndesc = _mat_prop_descriptors.size();
132  for (MooseIndex(_mat_prop_descriptors) jj = 0; jj < ndesc; ++jj)
133  {
135 
136  // take a property descriptor and check if it depends on the current derivative variable
137  if (j->dependsOn(_arg_names[i]))
138  {
139  FunctionMaterialPropertyDescriptor matderivative(*j);
140  matderivative.addDerivative(_arg_names[i]);
141 
142  // search if this new derivative is not yet in the list of material properties
143  MatPropDescriptorList::iterator m = findMatPropDerivative(matderivative);
144  if (m == _mat_prop_descriptors.end())
145  {
146  // construct new variable name for the material property derivative as base name +
147  // number
148  std::string newvarname = _dmatvar_base + Moose::stringify(_dmatvar_index++);
149  matderivative.setSymbolName(newvarname);
150 
151  // loop over all queue items to register the new dmatvar variable (includes 'current'
152  // which is popped below)
153  for (std::deque<QueueItem>::iterator k = queue.begin(); k != queue.end(); ++k)
154  {
155  k->_F->AddVariable(newvarname);
156  k->_F->RegisterDerivative(j->getSymbolName(), _arg_names[i], newvarname);
157  }
158 
159  _mat_prop_descriptors.push_back(matderivative);
160  }
161  }
162  }
163 
164  // construct new derivative
165  QueueItem newitem = current;
166  newitem._dargs.push_back(i);
167 
168  // build derivative
169  newitem._F = ADFunctionPtr(new ADFunction(*current._F));
170  if (newitem._F->AutoDiff(_variable_names[i]) != -1)
171  mooseError(
172  "Failed to take order ", newitem._dargs.size(), " derivative in material ", _name);
173 
174  // optimize and compile
176  newitem._F->Optimize();
177  if (_enable_jit && !newitem._F->JITCompile())
178  mooseInfo("Failed to JIT compile expression, falling back to byte code interpretation.");
179 
180  // generate material property argument vector
181  std::vector<VariableName> darg_names(0);
182  for (unsigned int j = 0; j < newitem._dargs.size(); ++j)
183  darg_names.push_back(_arg_names[newitem._dargs[j]]);
184 
185  // append to list of derivatives if the derivative is non-vanishing
186  if (!newitem._F->isZero())
187  {
188  Derivative newderivative;
189  newderivative.first = &declarePropertyDerivative<Real>(_F_name, darg_names);
190  newderivative.second = newitem._F;
191  newderivative.darg_names = darg_names;
192  _derivatives.push_back(newderivative);
193  }
194 
195  // push item to queue if further differentiation is required
196  if (newitem._dargs.size() < _derivative_order)
197  queue.push_back(newitem);
198  }
199 
200  // remove the 'current' element from the queue
201  queue.pop_front();
202  }
203 
204  // increase the parameter buffer to provide storage for the material property derivatives
205  _func_params.resize(_nargs + _mat_prop_descriptors.size());
206 }
207 
208 void
210 {
211  if (_prop_F)
212  (*_prop_F)[_qp] = 0.0;
213 
214  for (auto & D : _derivatives)
215  (*D.first)[_qp] = 0.0;
216 }
217 
218 void
220 {
221  // fill the parameter vector, apply tolerances
222  for (unsigned int i = 0; i < _nargs; ++i)
223  {
224  if (_tol[i] < 0.0)
225  _func_params[i] = (*_args[i])[_qp];
226  else
227  {
228  Real a = (*_args[i])[_qp];
229  _func_params[i] = a < _tol[i] ? _tol[i] : (a > 1.0 - _tol[i] ? 1.0 - _tol[i] : a);
230  }
231  }
232 
233  // insert material property values
234  auto nmat_props = _mat_prop_descriptors.size();
235  for (MooseIndex(_mat_prop_descriptors) i = 0; i < nmat_props; ++i)
236  _func_params[i + _nargs] = _mat_prop_descriptors[i].value()[_qp];
237 
238  // set function value
239  if (_prop_F)
240  (*_prop_F)[_qp] = evaluate(_func_F);
241 
242  // set derivatives
243  for (auto & D : _derivatives)
244  (*D.first)[_qp] = evaluate(D.second);
245 }
Helper class to perform the auto derivative taking.
bool dependsOn(const std::string &var) const
Check if a material property depends on a given variable.
Real evaluate(ADFunctionPtr &)
Evaluate FParser object and check EvalError.
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
FunctionParserADBase< Real > ADFunction
Shorthand for an autodiff function parser object.
std::vector< std::string > _variable_names
variable names used in the expression (depends on the map_mode)
Material properties get fully described using this structure, including their dependent variables and...
FEProblemBase & _fe_problem
Definition: Material.h:215
MatPropDescriptorList::iterator findMatPropDerivative(const FunctionMaterialPropertyDescriptor &)
std::vector< Real > _tol
Tolerance values for all arguments (to protect from log(0)).
Moose::MaterialDataType _material_data_type
The type of data.
const std::string _dmatvar_base
variable base name for the dynamically material property derivatives
void addDerivative(const VariableName &var)
take another derivative
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::shared_ptr< ADFunction > ADFunctionPtr
Shorthand for an smart pointer to an autodiff function parser object.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
Material objects are special in that they have additional objects created automatically (see FEProble...
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
const MaterialWarehouse & getMaterialWarehouse() const
unsigned int _derivative_order
maximum derivative order
virtual void computeQpProperties()
Users must override this method.
InputParameters validParams< ParsedMaterialHelper >()
MaterialProperty< Real > * _prop_F
Material property to store the function value.
unsigned int _qp
Definition: Material.h:222
DerivativeParsedMaterialHelper(const InputParameters &parameters, VariableNameMappingMode map_mode=USE_PARAM_NAMES)
const std::string & getSymbolName() const
get the fparser symbol name
void assembleDerivatives()
Perform a breadth first construction of all requested derivatives.
THREAD_ID _tid
Definition: Material.h:216
std::shared_ptr< T > getActiveObject(const std::string &name, THREAD_ID tid=0) const
PetscInt m
unsigned int _nargs
Number of coupled arguments.
InputParameters validParams< DerivativeParsedMaterialHelper >()
void setSymbolName(const std::string &n)
set the fparser symbol name
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:60
std::string _F_name
Name of the function value material property and used as a base name to concatenate the material prop...
const std::string & _name
The name of this object, reference to value stored in InputParameters.
Definition: MooseObject.h:183
unsigned int _dmatvar_index
next available variable number for automatically created material property derivative variables ...
std::vector< Derivative > _derivatives
The requested derivatives of the free energy.
Helper class to perform the parsing and optimization of the function expression.
MatPropDescriptorList _mat_prop_descriptors
Material property descriptors (obtained by parsing _mat_prop_expressions)
std::vector< Real > _func_params
Array to stage the parameters passed to the functions when calling Eval.
std::vector< const VariableValue * > _args
Coupled variables for function arguments.
const std::string & name() const
Get the name of the object.
Definition: MooseObject.h:59
virtual void functionsOptimize()
std::vector< std::string > _arg_names
String vector of all argument names.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
void mooseInfo(Args &&... args) const
Definition: MooseObject.h:167
ADFunctionPtr _func_F
The undiffed free energy function parser object.
virtual void initQpStatefulProperties()
Initialize stateful properties at quadrature points.