NEML2 1.4.0
Loading...
Searching...
No Matches
ImplicitUpdate.cxx
1// Copyright 2023, UChicago Argonne, LLC
2// All Rights Reserved
3// Software Name: NEML2 -- the New Engineering material Model Library, version 2
4// By: Argonne National Laboratory
5// OPEN SOURCE LICENSE (MIT)
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23// THE SOFTWARE.
24
25#include "neml2/models/ImplicitUpdate.h"
26#include "neml2/misc/math.h"
27
28namespace neml2
29{
30register_NEML2_object(ImplicitUpdate);
31
34{
36 options.doc() =
37 "Update an implicit model by solving the underlying implicit system of equations.";
38
39 options.set<std::string>("implicit_model");
40 options.set("implicit_model").doc() =
41 "The implicit model defining the implicit system of equations to be solved";
42
43 options.set<std::string>("solver");
44 options.set("solver").doc() = "Solver used to solve the implicit system";
45
46 return options;
47}
48
50 : Model(options),
51 _model(register_model<Model>(options.get<std::string>("implicit_model"),
52 /*extra_deriv_order=*/requires_grad() ? 0 : 1,
53 /*nonlinear=*/true)),
54 _solver(Factory::get_object<NonlinearSolver>("Solvers", options.get<std::string>("solver")))
55{
56 // Make sure the nonlinear system is square
58 "The implicit model's input should have a state subaxis. The input axis is\n",
61 "The implicit model's output should have a residual subaxis. The output axis is\n",
63 neml_assert(_model.input_axis().subaxis("state") == _model.output_axis().subaxis("residual"),
64 "The implicit model should have conformal trial state and residual. The input state "
65 "subaxis is\n",
66 _model.input_axis().subaxis("state"),
67 "\nThe output residual subaxis is\n",
68 _model.output_axis().subaxis("residual"));
69
70 // Take care of dependency registration:
71 // 1. Input variables of the "implicit_model" should be *consumed* by *this* model. This has
72 // already been taken care of by the `register_model` call.
73 // 2. Output variables of the "implicit_model" on the "residual" subaxis should be *provided* by
74 // *this* model.
75 for (auto var : _model.output_axis().subaxis("residual").variable_accessors(/*recursive=*/true))
76 declare_output_variable(_model.output_axis().subaxis("residual").storage_size(var),
77 var.on("state"));
78}
79
80void
82{
84 "ImplicitUpdate does not support AD because it uses in-place operations to "
85 "iteratively update the trial solution until convergence.");
86}
87
88void
90{
91 neml_assert_dbg(!d2out_din2, "This model does not define the second derivatives.");
93 !dout_din || out,
94 "ImplicitUpdate: requires the value and the first derivatives to be computed together.");
95
96 // Apply initial guess
97 LabeledVector sol0(_model.solution(), {&output_axis()});
99
100 // The trial state is used as the initial guess
101 // Perform automatic scaling
103
104 if (out || dout_din)
105 {
106 // Solve for the next state
108 auto sol = _model.solution().clone();
110 neml_assert(succeeded, "Nonlinear solve failed.");
112
113 if (out)
115
116 // Use the implicit function theorem (IFT) to calculate the other derivatives
117 if (dout_din)
118 {
119 // IFT requires dresidual/dinput evaluated at the solution:
121 const auto & partials = _model.derivative_storage();
122
123 // The actual IFT:
124 LabeledMatrix J = partials.slice(1, "state");
126 derivative_storage()("state", "old_state")
127 .copy_(-math::linalg::lu_solve(LU, pivot, partials.slice(1, "old_state")));
128 derivative_storage()("state", "forces")
129 .copy_(-math::linalg::lu_solve(LU, pivot, partials.slice(1, "forces")));
130 derivative_storage()("state", "old_forces")
131 .copy_(-math::linalg::lu_solve(LU, pivot, partials.slice(1, "old_forces")));
132 }
133 }
134}
135} // namespace neml2
The wrapper (decorator) for cross-referencing unresolved values at parse time.
Definition CrossRef.h:52
Definition Factory.h:39
Definition ImplicitUpdate.h:33
Model & _model
The implicit model to be updated.
Definition ImplicitUpdate.h:45
ImplicitUpdate(const OptionSet &name)
Definition ImplicitUpdate.cxx:49
virtual void check_AD_limitation() const override
Definition ImplicitUpdate.cxx:81
NonlinearSolver & _solver
The nonlinear solver used to solve the nonlinear system.
Definition ImplicitUpdate.h:48
static OptionSet expected_options()
Definition ImplicitUpdate.cxx:33
void set_value(bool out, bool dout_din, bool d2out_din2) override
The map between input -> output, and optionally its derivatives.
Definition ImplicitUpdate.cxx:89
const LabeledAxis & subaxis(const std::string &name) const
Get a sub-axis.
Definition LabeledAxis.cxx:365
bool has_subaxis(const LabeledAxisAccessor &s) const
Check the existence of a subaxis by its LabeledAxisAccessor.
Definition LabeledAxis.cxx:200
A single-batched, logically 2D LabeledTensor.
Definition LabeledMatrix.h:38
void copy_(const T &other)
Copy the value from another tensor.
Definition LabeledTensor.h:235
A single-batched, logically 1D LabeledTensor.
Definition LabeledVector.h:38
The base class for all constitutive models.
Definition Model.h:53
bool _AD_2nd_deriv
Whether to use AD to compute 2nd derivatives.
Definition Model.h:281
const torch::TensorOptions & options() const
This model's tensor options.
Definition Model.h:116
bool _AD_1st_deriv
Whether to use AD to compute 1st derivatives.
Definition Model.h:278
virtual std::tuple< LabeledVector, LabeledMatrix > value_and_dvalue(const LabeledVector &in)
Convenient shortcut to construct and return the model value and its derivative.
Definition Model.cxx:357
@ SOLVING
Definition Model.h:188
@ UPDATING
Definition Model.h:188
static OptionSet expected_options()
Definition Model.cxx:33
static enum neml2::Model::Stage stage
Definition Model.cxx:30
The nonlinear solver solves a nonlinear system of equations.
Definition NonlinearSolver.h:37
virtual std::tuple< bool, size_t > solve(NonlinearSystem &system, BatchTensor &sol)=0
Solve the given nonlinear system.
virtual void init_scaling(const bool verbose=false)
Compute algebraic Jacobian-based automatic scaling following https://cs.stanford.edu/people/paulliu/f...
Definition NonlinearSystem.cxx:78
virtual BatchTensor solution() const
Get the solution vector.
Definition NonlinearSystem.h:66
A custom map-like data structure. The keys are strings, and the values can be nonhomogeneously typed.
Definition OptionSet.h:59
const bool verbose
Whether to print additional (debugging) information during the solve.
Definition Solver.h:49
LabeledMatrix & derivative_storage()
Definition VariableStore.h:127
Variable< T > & declare_output_variable(S &&... name)
Declare an output variable.
Definition VariableStore.h:205
LabeledVector & output_storage()
Definition VariableStore.h:121
LabeledAxis & output_axis()
Definition VariableStore.h:97
LabeledVector & input_storage()
Definition VariableStore.h:115
LabeledAxis & input_axis()
Definition VariableStore.h:91
std::tuple< BatchTensor, BatchTensor > lu_factor(const BatchTensor &A, bool pivot)
Definition math.cxx:346
BatchTensor lu_solve(const BatchTensor &LU, const BatchTensor &pivots, const BatchTensor &B, bool left, bool adjoint)
Definition math.cxx:353
Definition CrossRef.cxx:32
void neml_assert_dbg(bool assertion, Args &&... args)
Definition error.h:85
void neml_assert(bool assertion, Args &&... args)
Definition error.h:73