https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LAROMANCEPartitionStressUpdateBase.C
Go to the documentation of this file.
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
11
12#include <libmesh/dense_matrix.h> // libMesh::cholesky_solve
13
14registerMooseObjectAliased("SolidMechanicsApp",
16 "LAROMANCEPartitionStressUpdate");
17registerMooseObjectAliased("SolidMechanicsApp",
19 "ADLAROMANCEPartitionStressUpdate");
20
21template <bool is_ad>
24{
26 params.addClassDescription("LAROMANCE base class for partitioned reduced order models");
27 params.addRangeCheckedParam<Real>(
28 "finite_difference_width",
29 1.0e-2,
30 "finite_difference_width > 0",
31 "Factor multiplied against the input stress to compute the finite "
32 "difference derivative of the parition weights.");
33
34 return params;
35}
36
37template <bool is_ad>
39 const InputParameters & parameters)
40 : LAROMANCEStressUpdateBaseTempl<is_ad>(parameters),
41 _finite_difference_width(this->template getParam<Real>("finite_difference_width"))
42{
43}
44
45template <bool is_ad>
46void
48{
50 _partition_Mmean = getClassificationMmean();
51 _partition_Mscale = getClassificationMscale();
52 _partition_Xu = getClassificationXu();
53 _partition_Ell = getClassificationEll();
54 _partition_Eta = getClassificationEta();
55 _partition_Luu = getClassificationLuu();
56 _partition_Vind = getClassificationVind();
57 _partition_difference.resize(_partition_Xu[0].size(),
58 std::vector<GenericReal<is_ad>>(_partition_Xu.size()));
59 _partition_distance.resize(_partition_difference.size());
60 _partition_covariance.resize(_partition_distance.size());
61 _partition_b.resize(_partition_covariance.size());
62 _partition_A.resize(_partition_Luu[0].size(), _partition_Luu.size());
63}
64
65template <bool is_ad>
66void
68{
70
71 this->_json["m_mean"] = getClassificationMmean();
72 this->_json["m_scale"] = getClassificationMscale();
73 this->_json["xu"] = getClassificationXu();
74 this->_json["ell"] = getClassificationEll();
75 this->_json["eta"] = getClassificationEta();
76 this->_json["luu"] = getClassificationLuu();
77 this->_json["vind"] = getClassificationVind().get_values();
78}
79
80template <bool is_ad>
81void
83 std::vector<GenericReal<is_ad>> & weights, std::vector<GenericReal<is_ad>> & dweights_dstress)
84{
85 std::vector<bool> in_partition(_num_partitions, false);
86 unsigned int num_partitions_active = 0;
87 for (unsigned int p = 0; p < _num_partitions; ++p)
88 {
89 for (unsigned int t = 0; t < this->_num_tiles[p]; ++t)
90 if (!in_partition[p] && this->checkInTile(p, t))
91 in_partition[p] = true;
92
93 num_partitions_active += in_partition[p];
94 }
95 mooseAssert(num_partitions_active <= _num_partitions,
96 "Number of paritions active must be less than total number of paritions");
97 if (!num_partitions_active)
98 mooseException("Number of active partitions (",
99 num_partitions_active,
100 ") out of total number of partitions (",
101 _num_partitions,
102 ") is zero. This may be because you are trying to sample outside the total "
103 "applicability of the model");
104
105 if (_num_partitions == 1) // If only one parition present, all weights are one
106 {
107 weights[0] = 1.0;
108 dweights_dstress[0] = 0.0;
109 }
110 else if (_num_partitions == 2)
111 {
112 if (num_partitions_active == 1) // If only present in one partition, math is easy
113 {
114 std::fill(dweights_dstress.begin(), dweights_dstress.end(), 0.0);
115
116 if (in_partition[0])
117 weights[1] = 0.0;
118 else if (in_partition[1])
119 weights[1] = 1.0;
120 else
121 mooseError("Internal error: Parition weight calculation incorrect when only one "
122 "partition is applicable");
123 }
124 else if (num_partitions_active == 2) // If present in two partitions, compute weights
125 {
126 weights[1] = computeSecondPartitionWeight();
127 computeDSecondPartitionWeightDStress(dweights_dstress[1]);
128 dweights_dstress[0] = -dweights_dstress[1];
129 }
130 weights[0] = 1.0 - weights[1];
131 }
132 else
133 mooseError("Internal error: number of partitions can only be 1 or 2");
134
135 if (_num_partitions == 2)
136 _second_partition_weight[_qp] = this->_partition_weights[1];
137 else
138 _second_partition_weight[_qp] = 0.0;
139
140 // Given the weight, compute the sigmoid transformed value to smoothly transition
141 for (unsigned int p = 0; p < _num_partitions; ++p)
142 {
143 weights[p] = (1.0 - sigmoid(0.0, 1.0, weights[p]));
144 dweights_dstress[p] *= -sigmoid(0.0, 1.0, weights[p], true);
145 }
146}
147
148template <bool is_ad>
151{
152 using std::sqrt, std::exp, std::min, std::max;
153
154 // extract and scale only the relevant inputs on which the GPR was trained (ignore
155 // _old_strain_input_index)
156 std::vector<GenericReal<is_ad>> scaled_input_values(_num_inputs - 1);
157 unsigned int inc = 0;
158 for (const auto i : index_range(_input_values))
159 {
160 if (i != _old_strain_input_index)
161 {
162 scaled_input_values[inc] =
163 (_input_values[i] - _partition_Mmean[inc]) / _partition_Mscale[inc];
164 inc++;
165 }
166 }
167
168 // compute the distance of the new point to ALL training points and sum the distance over all
169 // input variables first compute difference between points.
170 // for-loop to compute difference
171 for (const auto i : index_range(_partition_Xu))
172 for (const auto j : index_range(_partition_Xu[0]))
173 _partition_difference[j][i] =
174 Utility::pow<2>((_partition_Xu[i][j] - scaled_input_values[i]) / _partition_Ell);
175
176 // sum difference over input dimension and take square root
177 std::fill(_partition_distance.begin(), _partition_distance.end(), 0.0);
178 for (const auto i : index_range(_partition_difference))
179 {
180 for (const auto j : index_range(_partition_difference[0]))
181 _partition_distance[i] += _partition_difference[i][j];
182 _partition_distance[i] = sqrt(_partition_distance[i]);
183 }
184
185 // compute the covariance wrt ALL training points: the larger the distance, the smaller the
186 // covariance
187 for (const auto i : index_range(_partition_covariance))
188 _partition_covariance[i] = Utility::pow<2>(_partition_Eta) * exp(-0.5 * _partition_distance[i]);
189
190 // solve the system of equations: convert covariance to libMesh::DenseVector
191 for (const auto i : index_range(_partition_covariance))
192 _partition_b(i) = _partition_covariance[i];
193
194 // convert Luu to libMesh::DenseMatrix, first fill values of A with Luu-values
195 for (const auto i : index_range(_partition_Luu[0]))
196 for (const auto j : index_range(_partition_Luu))
197 _partition_A(i, j) = _partition_Luu[j][i];
198
199 // solve the linear system of equations (lu_solve)
200 DenseVector<GenericReal<is_ad>> ma(_partition_b.size());
201 _partition_A.lu_solve(_partition_b, ma);
202
203 // induce full array through sparse grid and summarize into mu
204 GenericReal<is_ad> partition_weight = 0.0;
205 for (const auto i : index_range(ma))
206 partition_weight += ma(i) * _partition_Vind(i);
207
208 // scale mu between 0 and 1: the weight of partition 2
209 partition_weight = -partition_weight + 1.0;
210 partition_weight = min(partition_weight, 1.0);
211 partition_weight = max(partition_weight, 0.0);
212 return partition_weight;
213}
214
215template <bool is_ad>
216void
218 GenericReal<is_ad> & dsecond_partition_weight_dstress)
219{
220 const auto fd_tol =
221 _input_values[_stress_input_index] * _finite_difference_width; // Finite difference width
222 _input_values[_stress_input_index] += fd_tol;
223 dsecond_partition_weight_dstress =
224 (computeSecondPartitionWeight() - _second_partition_weight[_qp]) / fd_tol;
225 _input_values[_stress_input_index] -= fd_tol;
226}
227
const Real p
registerMooseObjectAliased("SolidMechanicsApp", LAROMANCEPartitionStressUpdateBase, "LAROMANCEPartitionStressUpdate")
void mooseError(Args &&... args)
Moose::GenericType< Real, is_ad > GenericReal
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual void computeDSecondPartitionWeightDStress(GenericReal< is_ad > &dsecond_partition_weight_dstress)
Compute the derivative of the partition weight of the second partition w.r.t.
virtual GenericReal< is_ad > computeSecondPartitionWeight()
Compute the partition weight on the location in input-space, based on a calibrated Gaussian Process R...
LAROMANCEPartitionStressUpdateBaseTempl(const InputParameters &parameters)
virtual void computePartitionWeights(std::vector< GenericReal< is_ad > > &weights, std::vector< GenericReal< is_ad > > &dweights_dstress) override
Compute the weight of the different partitions.