|
NEML2 2.0.0
|
In a previous tutorial, we briefly explained the usage of model parameters and their retrieval and update. In this tutorial, we will introduce other ways of specifying model parameters in the input file and how they facilitate model composition.
Consider the following equations describing the stress-strain relation accounting for a thermal eigenstrain:
\begin{align} \boldsymbol{\varepsilon}^g & = \alpha (T - T_0) \boldsymbol{I}, \label{1} \\ \boldsymbol{\varepsilon}^e & = \boldsymbol{\varepsilon} - \boldsymbol{\varepsilon}^g, \label{2} \\ \boldsymbol{\sigma} & = 3 K \operatorname{vol} \boldsymbol{\varepsilon}^e + 2 G \operatorname{dev} \boldsymbol{\varepsilon}^e, \label{3} \end{align}
where \( \alpha \) is the coefficient of thermal expansion, and \( T_0 \) is the reference temperature at which the thermal eigenstrain is zero.
In NEML2 input files, model parameters can be specified in one of three ways:
In this mode, parameter values are directly specified by plain numbers. The corresponding input file looks like
As usual, we can inspect the structure of the composed model using the following code.
C++
Output: @list-output:ex1
Python
Output: @list-output:ex2
The composed model has two input variables (strain and temperature), one output variable (stress), and three parameters:
eq1_alpha: Coefficient of thermal expansion defined in eq1.eq3_G: Shear modulus defined in eq3.eq3_K: Bulk modulus defined in eq3.Note that the parameters of the composed model is defined by the union of the sub-model parameters, and that their names are prefixed by the name of the sub-model.
While specifying parameter values as plain numeric literals is convenient and expressive, it is however not always possible to do so. For example, when the parameter value is batched, it is not possible to fully define it using one number. In such scenario, a tensor can be created under the [Tensors] section, and the name of that tensor can be used in place of the parameter value.
The following example input file shows how to specify the coefficient of thermal expansion as a batched scalar: @list-input/model_parameters_revisited/input2.i
In this input file, a tensor named "alpha" with batch shape (2, 2) is created under the "[Tensors]" section. The coefficient of thermal expansion in model "eq1" then references that tensor using its name, i.e., "CTE = 'alpha'". Note that this approach does not alter the model structure, i.e., eq1_alpha is still a model parameter, albeit initialized with the tensor value.
C++
Output: @list-output:ex3
Python
Output: @list-output:ex4
While specifying parameters using tensor names is significantly more flexible than using plain numeric literals, the parameter values still remain "static", i.e., the parameter values remain the same during model evaluation unless explicitly updated by the user. In practice, especially when dealing with multiple physics phenomena such as thermo-mechanical coupling, this limitation makes it difficult to specify temperature-dependent parameters.
To remove this limitation, NEML2 allows the use of variable specifiers to define model parameters. Suppose the original problem is modified to account for temperature-dependent parameters, e.g.,
\begin{align*} \boldsymbol{\varepsilon}^g & = \textcolor{blue}{\alpha(T)} (T - T_0) \boldsymbol{I}, \\ \boldsymbol{\varepsilon}^e & = \boldsymbol{\varepsilon} - \boldsymbol{\varepsilon}^g, \\ \boldsymbol{\sigma} & = 3 \textcolor{blue}{K(T)} \operatorname{vol} \boldsymbol{\varepsilon}^e + 2 \textcolor{blue}{G(T)} \operatorname{dev} \boldsymbol{\varepsilon}^e, \end{align*}
where \( \alpha(T) \), \( K(T) \), and \( G(T) \) are linearly interpolated from given data. The input file can be modified accordingly:
Here, the three temperature-dependent model parameters are defined using ScalarLinearInterpolation, and their corresponding model names are used to specify model parameters in "eq1" and "eq3". It is important to understand that specifying model parameters by variable coupling alters the model structure. Mathematically, this corresponds to changing
\[ \boldsymbol{\sigma} = f(\boldsymbol{\varepsilon}, T; \alpha, K, G) \]
to
\[ \boldsymbol{\sigma} = f(\boldsymbol{\varepsilon}, T; \mathcal{P}_\alpha, \mathcal{P}_K, \mathcal{P}_G) \]
where \( \mathcal{P}_\alpha \), \( \mathcal{P}_K \), and \( \mathcal{P}_G \) denote the parametrizations of \( \alpha \), \( K \), and \( G \), respectively. In our example, these parametrizations are the abscissa and ordinate of the interpolant.
The composed model automatically reflects such restructuring:
C++
Output: @list-output:ex5
Python
Output: @list-output:ex6
When the referenced model has more than one output variable, the variable specification becomes ambiguous. A more precise variable specifier in the form of <model-name>.<variable-name> can be used to remove such ambiguity. For example, although unncessary (as ScalarLinearInterpolation defines one and only one output variable), the above example input is equivalent to
Finally, a special form of variable specifier can be used to effectively transform a model parameter into an input variable. For example, the following input file converts the coefficient of thermal expansion into an input variable.
Again, NEML2 automatically reflects such change in model structure:
C++
Output: @list-output:ex7
Python
Output: @list-output:ex8