https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TimedSubdomainModifier.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
12#include "DelimitedFileReader.h"
13#include "MooseMesh.h"
14
16
19{
21
22 // parameters for direct input
23 params.addParam<std::vector<Real>>("times", "The times of the subdomain modifications.");
24 params.addParam<std::vector<SubdomainName>>("blocks_from",
25 "Names or ids of the 'old' block(s), to be renamed.");
26 params.addParam<std::vector<SubdomainName>>("blocks_to", "Names or ids of the 'new' block.");
27 params.addParamNamesToGroup("times blocks_from blocks_to", "Subdomain change data from input");
28
29 // parameters for file-based data supply
30 params.addParam<FileName>("data_file", "File holding CSV data");
31 params.addParam<bool>("header",
32 "Indicates whether the file contains a header with the column names");
33 params.addParam<std::string>("delimiter", ",", "Delimiter used to parse the file");
34 params.addParam<std::string>("comment", ";", "Comment character used to parse the file");
35 params.addParam<std::size_t>(
36 "time_column_index", 0, "Zero-based index of the time column. Default is '0'.");
37 params.addParam<std::size_t>(
38 "blocks_from_column_index", 1, "Zero-based index of the blocks_from column. Default is '1'.");
39 params.addParam<std::size_t>(
40 "blocks_to_column_index", 2, "Zero-based index of the blocks_to column. Default is '2'.");
41 params.addParam<std::string>("time_column_text", "Header text of the time column.");
42 params.addParam<std::string>("blocks_from_column_text", "Header text of the blocks_from column.");
43 params.addParam<std::string>("blocks_to_column_text", "Header text of the blocks_to column.");
45 "data_file header delimiter comment time_column_index blocks_from_column_index "
46 "blocks_to_column_index time_column_text blocks_from_column_text blocks_to_column_text",
47 "Subdomain change data from CSV file");
48
50 "Modify element subdomain ID of entire subdomains for given points "
51 "in time. This mesh modifier only runs on the undisplaced mesh, and it will "
52 "modify both the undisplaced and the displaced mesh.");
53
54 return params;
55}
56
59{
60 // determine function arguments
61
62 // helper variables for parameter consistency checks
63 const auto from_data_file =
64 isParamSetByUser("data_file") + isParamSetByUser("header") + isParamSetByUser("delimiter") +
65 isParamSetByUser("comment") + isParamSetByUser("time_column_index") +
66 isParamSetByUser("blocks_from_column_index") + isParamSetByUser("blocks_to_column_index") +
67 isParamSetByUser("time_column_text") + isParamSetByUser("blocks_from_column_text") +
68 isParamSetByUser("blocks_to_column_text");
69
70 const auto from_data_File_needs_header = isParamSetByUser("time_column_text") +
71 isParamSetByUser("blocks_from_column_text") +
72 isParamSetByUser("blocks_to_column_text");
73
74 const auto from_parameters =
75 isParamSetByUser("times") + isParamSetByUser("blocks_from") + isParamSetByUser("blocks_to");
76
77 // Check parameter set for inconsistencies
78 const auto from_source_count = ((from_data_file > 0) + (from_parameters > 0));
79 if (from_source_count != 1)
80 {
81 mooseError("Data on times and blocks must be provided either via a CSV file ('data_file' and "
82 "corresponding blocks), or via direct parameter input ('times', 'blocks_from', and "
83 "'blocks_to').");
84 }
85
86 if (from_parameters > 0)
87 {
88 if (from_parameters != 3)
89 mooseError("All parameters 'times', and 'blocks_from', and 'blocks_to' must be specified.");
91 }
92 else if (from_data_file > 0)
93 {
94 if ((isParamSetByUser("time_column_index") + isParamSetByUser("time_column_text")) > 1)
96 "The parameters 'time_column_index', and 'time_column_text' are mutual exclusive.");
97 if ((isParamSetByUser("blocks_from_column_index") +
98 isParamSetByUser("blocks_from_column_text")) > 1)
99 mooseError("The parameters 'blocks_from_column_index', and 'blocks_from_column_text' are "
100 "mutual exclusive.");
101 if ((isParamSetByUser("blocks_to_column_index") + isParamSetByUser("blocks_to_column_text")) >
102 1)
103 mooseError("The parameters 'blocks_to_column_index', and 'blocks_to_column_text' are mutual "
104 "exclusive.");
105 if ((from_data_File_needs_header > 0) && (isParamSetByUser("header") == 0))
106 mooseError("Header flag must be active if columns are to be found via header.");
107
109 }
110 else
111 mooseError("Unknown data source. Are you missing a parameter? Did you misspell one?");
112}
113
114void
116{
117 _times = getParam<std::vector<Real>>("times");
118 const auto n = _times.size();
119
120 const auto raw_from = getParam<std::vector<SubdomainName>>("blocks_from");
121 const auto raw_to = getParam<std::vector<SubdomainName>>("blocks_to");
122
123 if (raw_from.size() != n)
125 "Parameter 'blocks_from' must contain the same number of items as parameter 'times'.");
126 if (raw_to.size() != n)
127 mooseError("Parameter 'blocks_to' must contain the same number of items as parameter 'times'.");
128
129 _blocks_from.resize(n);
130 _blocks_to.resize(n);
131
132 for (const auto i : index_range(raw_from))
133 {
134 _blocks_from[i] = getSubdomainIDAndCheck(raw_from[i]);
135 _blocks_to[i] = getSubdomainIDAndCheck(raw_to[i]);
136 }
137}
138
139void
141{
142 const auto _file_name = getParam<FileName>("data_file");
143
146 if (isParamValid("header"))
147 {
148 _header_flag = getParam<bool>("header")
151 }
152
153 std::string _delimiter = ",";
154 if (isParamValid("delimiter"))
155 {
156 _delimiter = getParam<std::string>("delimiter");
157 }
158
159 std::string _comment = "#";
160 if (isParamValid("comment"))
161 {
162 _comment = getParam<std::string>("comment");
163 }
164
166
167 file.setHeaderFlag(_header_flag);
168 file.setDelimiter(_delimiter);
169 file.setComment(_comment);
170 file.read();
171
172 std::size_t _time_column = 0;
173 if (isParamValid("time_column_text"))
174 {
175 const auto s = getParam<std::string>("time_column_text");
176 const auto _names = file.getNames();
177 const auto it = find(_names.begin(), _names.end(), s);
178 if (it == _names.end())
179 mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
180 _time_column = std::distance(_names.begin(), it);
181 }
182 else if (isParamValid("time_column_index"))
183 {
184 _time_column = getParam<std::size_t>("time_column_index");
185 }
186
187 std::size_t _blocks_from_column = 1;
188 if (isParamValid("blocks_from_column_text"))
189 {
190 const auto s = getParam<std::string>("blocks_from_column_text");
191 const auto _names = file.getNames();
192 const auto it = find(_names.begin(), _names.end(), s);
193 if (it == _names.end())
194 mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
195 _blocks_from_column = std::distance(_names.begin(), it);
196 }
197 else if (isParamValid("blocks_from_column_index"))
198 {
199 _blocks_from_column = getParam<std::size_t>("blocks_from_column_index");
200 }
201
202 std::size_t _blocks_to_column = 2;
203 if (isParamValid("blocks_to_column_text"))
204 {
205 const auto s = getParam<std::string>("blocks_to_column_text");
206 const auto _names = file.getNames();
207 const auto it = find(_names.begin(), _names.end(), s);
208 if (it == _names.end())
209 mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
210 _blocks_to_column = std::distance(_names.begin(), it);
211 }
212 else if (isParamValid("blocks_to_column_index"))
213 _blocks_to_column = getParam<std::size_t>("blocks_to_column_index");
214
215 const auto max_needed_column_index =
216 std::max({_time_column, _blocks_from_column, _blocks_to_column});
217
218 const auto data = file.getData();
219
220 if (data.size() < max_needed_column_index)
221 mooseError("data must contain at least " + std::to_string(max_needed_column_index) +
222 " columns in file ",
223 _file_name);
224
225 const auto strTimes = data[_time_column];
226 const auto strBlockFrom = data[_blocks_from_column];
227 const auto strBlockTo = data[_blocks_to_column];
228
229 const auto n_rows = strTimes.size();
230
231 // some sanity checks
232 if (n_rows == 0)
233 mooseError("empty sequence in file ", _file_name);
234 if (n_rows != strBlockFrom.size())
235 mooseError("Inconsistent source block data size in ",
236 _file_name,
237 ". Expected ",
238 n_rows,
239 " and read ",
240 strBlockFrom.size());
241 if (n_rows != strBlockTo.size())
242 mooseError("Inconsistent target block data size in ",
243 _file_name,
244 ". Expected ",
245 n_rows,
246 " and read ",
247 strBlockTo.size());
248
249 // resize variables to fit the data
250 _blocks_from.resize(n_rows);
251 _blocks_to.resize(n_rows);
252
253 // fill the to and from blocks vectors
254 for (const auto & time_str : strTimes)
255 _times.push_back(std::stod(time_str));
256 std::transform(strBlockFrom.begin(),
257 strBlockFrom.end(),
258 _blocks_from.begin(),
259 [this](const std::string & x) { return getSubdomainIDAndCheck(x); });
260 std::transform(strBlockTo.begin(),
261 strBlockTo.end(),
262 _blocks_to.begin(),
263 [this](const std::string & x) { return getSubdomainIDAndCheck(x); });
264}
265
267TimedSubdomainModifier::getSubdomainIDAndCheck(const std::string & subdomain_name)
268{
269 const auto name = MooseUtils::trim(subdomain_name);
270 const auto id = _mesh.getSubdomainID(name);
271 if (id == Moose::INVALID_BLOCK_ID)
272 mooseError("block", "Subdomain \"" + name + "\" not found in mesh.");
273 return id;
274}
275
278{
279 // get the subdomain-id of the current element
280 SubdomainID resulting_subdomain_id = _current_elem->subdomain_id();
281
282 // check for all the subdomain changes that can have been requested between the previous and the
283 // current time
284 for (const auto & time_pair : _times_and_indices)
285 {
286 // time of the data point
287 const auto t = time_pair.time;
288
289 // original data point index
290 const auto j = time_pair.index;
291
292 // do we have to apply?
293 if (t > _t_old && t <= _t && resulting_subdomain_id == _blocks_from[j])
294 {
295 // we have to change the subdomain-id using the original index (stored in 'j')
296 resulting_subdomain_id = _blocks_to[j];
297 }
298 }
299
300 return resulting_subdomain_id;
301}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
registerMooseObject("MooseApp", TimedSubdomainModifier)
const Elem *const & _current_elem
The current element pointer (available during execute())
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
SubdomainID getSubdomainID(const SubdomainName &subdomain_name) const
Get the associated subdomain ID for the subdomain name.
Definition MooseMesh.C:1720
Utility class for reading delimited data (e.g., CSV data).
const std::vector< std::string > & getNames() const
Return the column/row names.
const std::vector< std::vector< T > > & getData() const
Return the rows/columns of data.
void setComment(const std::string &value)
void setDelimiter(const std::string &value)
void read()
Perform the actual data reading.
Modifies element subdomains only at a given list of times.
std::set< TimeIndexPair > _times_and_indices
Times and subdomain changes to make.
Modifies elements from entire subdomains based on user input or file input.
TimedSubdomainModifier(const InputParameters &parameters)
static InputParameters validParams()
virtual SubdomainID computeSubdomainID() override
Compute the subdomain ID of the current element.
std::vector< Real > _times
Times to change the subdomains on.
std::vector< SubdomainID > _blocks_to
Target subdomains to change the source subdomains to.
SubdomainID getSubdomainIDAndCheck(const std::string &subdomain_name)
std::vector< SubdomainID > _blocks_from
Source subdomains to change from.
const Real & _t_old
Old time.
std::string trim(const std::string &str, const std::string &white_space=" \t\n\v\f\r")
Standard scripting language trim function.
const SubdomainID INVALID_BLOCK_ID
Definition MooseTypes.C:20