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 <iostream>
26 :
27 : #include "neml2/base/LabeledAxisAccessor.h"
28 : #include "neml2/misc/assertions.h"
29 : #include "neml2/misc/string_utils.h"
30 :
31 : namespace neml2
32 : {
33 : std::vector<std::string>
34 0 : reserved_subaxis_names()
35 : {
36 0 : return {STATE, OLD_STATE, FORCES, OLD_FORCES, RESIDUAL, PARAMETERS};
37 0 : }
38 :
39 1 : LabeledAxisAccessor::operator std::vector<std::string>() const
40 : {
41 1 : std::vector<std::string> v(_item_names.begin(), _item_names.end());
42 1 : return v;
43 : }
44 :
45 : std::string
46 472 : LabeledAxisAccessor::str() const
47 : {
48 472 : return utils::stringify(*this);
49 : }
50 :
51 : bool
52 29395 : LabeledAxisAccessor::empty() const
53 : {
54 29395 : return _item_names.empty();
55 : }
56 :
57 : size_t
58 19881 : LabeledAxisAccessor::size() const
59 : {
60 19881 : return _item_names.size();
61 : }
62 :
63 : const std::string &
64 18590 : LabeledAxisAccessor::operator[](size_t i) const
65 : {
66 18590 : return _item_names[i];
67 : }
68 :
69 : LabeledAxisAccessor
70 167 : LabeledAxisAccessor::with_suffix(const std::string & suffix) const
71 : {
72 167 : auto new_names = _item_names;
73 167 : new_names.back() += suffix;
74 334 : return new_names;
75 167 : }
76 :
77 : LabeledAxisAccessor
78 2369 : LabeledAxisAccessor::append(const LabeledAxisAccessor & axis) const
79 : {
80 2369 : return axis.prepend(*this);
81 : }
82 :
83 : LabeledAxisAccessor
84 30478 : LabeledAxisAccessor::prepend(const LabeledAxisAccessor & axis) const
85 : {
86 30478 : auto new_names = axis._item_names;
87 30478 : new_names.insert(new_names.end(), _item_names.begin(), _item_names.end());
88 60956 : return new_names;
89 30478 : }
90 :
91 : LabeledAxisAccessor
92 2872 : LabeledAxisAccessor::slice(int64_t n) const
93 : {
94 2872 : n = n < 0 ? int64_t(size()) + n : n;
95 2872 : neml_assert(size() >= std::size_t(n), "cannot apply slice");
96 2872 : std::vector<std::string> new_names(_item_names.begin() + n, _item_names.end());
97 5744 : return new_names;
98 2872 : }
99 :
100 : LabeledAxisAccessor
101 1603 : LabeledAxisAccessor::slice(int64_t n1, int64_t n2) const
102 : {
103 1603 : n1 = n1 < 0 ? int64_t(size()) + n1 : n1;
104 1603 : n2 = n2 < 0 ? int64_t(size()) + n2 : n2;
105 1603 : neml_assert(size() >= std::size_t(n1), "cannot apply slice");
106 1603 : neml_assert(size() >= std::size_t(n2), "cannot apply slice");
107 1603 : std::vector<std::string> new_names(_item_names.begin() + n1, _item_names.begin() + n2);
108 3206 : return new_names;
109 1603 : }
110 :
111 : LabeledAxisAccessor
112 145 : LabeledAxisAccessor::remount(const LabeledAxisAccessor & axis, int64_t n) const
113 : {
114 145 : return slice(n).prepend(axis);
115 : }
116 :
117 : bool
118 1601 : LabeledAxisAccessor::start_with(const LabeledAxisAccessor & axis) const
119 : {
120 1601 : return slice(0, int64_t(axis.size())) == axis;
121 : }
122 :
123 : bool
124 846 : LabeledAxisAccessor::is_state() const
125 : {
126 846 : return start_with(STATE);
127 : }
128 :
129 : bool
130 166 : LabeledAxisAccessor::is_old_state() const
131 : {
132 166 : return start_with(OLD_STATE);
133 : }
134 :
135 : bool
136 171 : LabeledAxisAccessor::is_force() const
137 : {
138 171 : return start_with(FORCES);
139 : }
140 :
141 : bool
142 48 : LabeledAxisAccessor::is_old_force() const
143 : {
144 48 : return start_with(OLD_FORCES);
145 : }
146 :
147 : bool
148 136 : LabeledAxisAccessor::is_residual() const
149 : {
150 136 : return start_with(RESIDUAL);
151 : }
152 :
153 : bool
154 90 : LabeledAxisAccessor::is_parameter() const
155 : {
156 90 : return start_with(PARAMETERS);
157 : }
158 :
159 : LabeledAxisAccessor
160 0 : LabeledAxisAccessor::current() const
161 : {
162 0 : neml_assert(_item_names.size() >= 1, "variable name length must be at least 1");
163 0 : if (start_with(OLD_STATE))
164 0 : return remount(STATE);
165 0 : if (start_with(OLD_FORCES))
166 0 : return remount(FORCES);
167 0 : throw NEMLException("Unable to find current counterpart of variable named '" +
168 0 : utils::stringify(*this) + "'");
169 : }
170 :
171 : LabeledAxisAccessor
172 91 : LabeledAxisAccessor::old() const
173 : {
174 91 : neml_assert(_item_names.size() >= 1, "variable name length must be at least 1");
175 91 : if (start_with(STATE))
176 38 : return remount(OLD_STATE);
177 53 : if (start_with(FORCES))
178 53 : return remount(OLD_FORCES);
179 0 : throw NEMLException("Unable to find old counterpart of variable named '" +
180 0 : utils::stringify(*this) + "'");
181 : }
182 :
183 : void
184 90407 : LabeledAxisAccessor::validate_item_name(const std::string & name) const
185 : {
186 90407 : neml_assert(!name.empty(), "Empty item variable name");
187 90407 : const auto x = name.find_first_of(" .,;/\t\n\v\f\r");
188 90407 : neml_assert(x == std::string::npos,
189 : "Invalid item name: ",
190 : name,
191 : ". The item names cannot contain whitespace, '.', ',', ';', or '/'.");
192 90406 : }
193 :
194 : bool
195 7785 : operator!=(const LabeledAxisAccessor & a, const LabeledAxisAccessor & b)
196 : {
197 7785 : return a.vec() != b.vec();
198 : }
199 :
200 : bool
201 70724 : operator==(const LabeledAxisAccessor & a, const LabeledAxisAccessor & b)
202 : {
203 70724 : return a.vec() == b.vec();
204 : }
205 :
206 : bool
207 512635 : operator<(const LabeledAxisAccessor & a, const LabeledAxisAccessor & b)
208 : {
209 512635 : return a.vec() < b.vec();
210 : }
211 :
212 : std::ostream &
213 2966 : operator<<(std::ostream & os, const LabeledAxisAccessor & accessor)
214 : {
215 9754 : for (size_t i = 0; i < accessor.vec().size(); i++)
216 : {
217 6788 : if (i != 0)
218 3822 : os << "/";
219 6788 : os << accessor.vec()[i];
220 : }
221 2966 : return os;
222 : }
223 : } // namespace neml2
|