Line data Source code
1 : // Copyright 2024, 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/solid_mechanics/MixedControlSetup.h"
26 : #include "neml2/tensors/SR2.h"
27 : #include "neml2/tensors/SSR4.h"
28 : #include "neml2/tensors/functions/diag_embed.h"
29 :
30 : namespace neml2
31 : {
32 : register_NEML2_object(MixedControlSetup);
33 :
34 : OptionSet
35 2 : MixedControlSetup::expected_options()
36 : {
37 2 : OptionSet options = Model::expected_options();
38 2 : options.doc() =
39 : "Object to setup a model for mixed stress/strain control. Copies the values of the "
40 : "fixed_values (the input strain or stress) and the mixed_state (the conjugate stress or "
41 2 : "strain values) into the stress and strain tensors used by the model.";
42 :
43 6 : options.set_input("control") = VariableName(FORCES, "control");
44 6 : options.set("control").doc() =
45 : "The name of the control signal. Values less than the threshold are "
46 2 : "strain control, greater are stress control";
47 :
48 8 : options.set<TensorName<Tensor>>("threshold") = TensorName<Tensor>("0.5");
49 2 : options.set("threshold").doc() = "The threshold to switch between strain and stress control";
50 :
51 6 : options.set_input("mixed_state") = VariableName(STATE, "mixed_state");
52 4 : options.set("mixed_state").doc() = "The name of the mixed state tensor. This holds the conjugate "
53 2 : "values to those being controlled";
54 :
55 6 : options.set_input("fixed_values") = VariableName(FORCES, "fixed_values");
56 4 : options.set("fixed_values").doc() = "The name of the fixed values, i.e. the actual strain or "
57 2 : "stress values being imposed on the model";
58 :
59 6 : options.set_output("cauchy_stress") = VariableName(STATE, "S");
60 2 : options.set("cauchy_stress").doc() = "The name of the Cauchy stress tensor";
61 :
62 6 : options.set_output("strain") = VariableName(STATE, "E");
63 2 : options.set("strain").doc() = "The name of the strain tensor";
64 :
65 2 : return options;
66 0 : }
67 :
68 3 : MixedControlSetup::MixedControlSetup(const OptionSet & options)
69 : : Model(options),
70 9 : _threshold(declare_buffer<Tensor>("c", "threshold")),
71 3 : _control(declare_input_variable<SR2>("control")),
72 3 : _fixed_values(declare_input_variable<SR2>("fixed_values")),
73 3 : _mixed_state(declare_input_variable<SR2>("mixed_state")),
74 3 : _stress(declare_output_variable<SR2>("cauchy_stress")),
75 6 : _strain(declare_output_variable<SR2>("strain"))
76 : {
77 3 : }
78 :
79 : void
80 5 : MixedControlSetup::set_value(bool out, bool dout_din, bool d2out_din2)
81 : {
82 5 : auto [dstrain, dstress] = make_operators(_control);
83 :
84 5 : if (out)
85 : {
86 : // Even benign in place operations get errors
87 4 : _stress = dstress * _fixed_values + dstrain * _mixed_state;
88 4 : _strain = dstrain * _fixed_values + dstress * _mixed_state;
89 : }
90 :
91 5 : if (dout_din)
92 : {
93 2 : if (_fixed_values.is_dependent())
94 : {
95 1 : _stress.d(_fixed_values) = dstress;
96 1 : _strain.d(_fixed_values) = dstrain;
97 : }
98 :
99 2 : if (_mixed_state.is_dependent())
100 : {
101 2 : _stress.d(_mixed_state) = dstrain;
102 2 : _strain.d(_mixed_state) = dstress;
103 : }
104 : }
105 :
106 : // All zero
107 : (void)(d2out_din2);
108 5 : }
109 :
110 : std::pair<SSR4, SSR4>
111 5 : MixedControlSetup::make_operators(const SR2 & control) const
112 : {
113 5 : auto strain_select = control <= _threshold;
114 5 : auto stress_select = control > _threshold;
115 :
116 : // This also converts these to floats
117 5 : auto ones_stress = Tensor(strain_select.to(control.options()), control.batch_sizes());
118 5 : auto ones_strain = Tensor::ones_like(control) - ones_stress;
119 :
120 5 : auto dstrain = base_diag_embed(ones_stress);
121 5 : auto dstress = base_diag_embed(ones_strain);
122 :
123 10 : return {dstrain, dstress};
124 5 : }
125 :
126 : } // namespace neml2
|