Line data Source code
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 :
10 : #include "TimedSubdomainModifier.h"
11 : #include "TimedElementSubdomainModifier.h"
12 : #include "DelimitedFileReader.h"
13 : #include "MooseMesh.h"
14 :
15 : registerMooseObject("MooseApp", TimedSubdomainModifier);
16 :
17 : InputParameters
18 14390 : TimedSubdomainModifier::validParams()
19 : {
20 14390 : InputParameters params = TimedElementSubdomainModifier::validParams();
21 :
22 : // parameters for direct input
23 14390 : params.addParam<std::vector<Real>>("times", "The times of the subdomain modifications.");
24 14390 : params.addParam<std::vector<SubdomainName>>("blocks_from",
25 : "Names or ids of the 'old' block(s), to be renamed.");
26 14390 : params.addParam<std::vector<SubdomainName>>("blocks_to", "Names or ids of the 'new' block.");
27 14390 : params.addParamNamesToGroup("times blocks_from blocks_to", "Subdomain change data from input");
28 :
29 : // parameters for file-based data supply
30 14390 : params.addParam<FileName>("data_file", "File holding CSV data");
31 14390 : params.addParam<bool>("header",
32 : "Indicates whether the file contains a header with the column names");
33 14390 : params.addParam<std::string>("delimiter", ",", "Delimiter used to parse the file");
34 14390 : params.addParam<std::string>("comment", ";", "Comment character used to parse the file");
35 43170 : params.addParam<std::size_t>(
36 28780 : "time_column_index", 0, "Zero-based index of the time column. Default is '0'.");
37 43170 : params.addParam<std::size_t>(
38 28780 : "blocks_from_column_index", 1, "Zero-based index of the blocks_from column. Default is '1'.");
39 43170 : params.addParam<std::size_t>(
40 28780 : "blocks_to_column_index", 2, "Zero-based index of the blocks_to column. Default is '2'.");
41 14390 : params.addParam<std::string>("time_column_text", "Header text of the time column.");
42 14390 : params.addParam<std::string>("blocks_from_column_text", "Header text of the blocks_from column.");
43 14390 : params.addParam<std::string>("blocks_to_column_text", "Header text of the blocks_to column.");
44 14390 : params.addParamNamesToGroup(
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 :
49 14390 : params.addClassDescription(
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 14390 : return params;
55 0 : }
56 :
57 65 : TimedSubdomainModifier::TimedSubdomainModifier(const InputParameters & parameters)
58 65 : : TimedElementSubdomainModifier(parameters)
59 : {
60 : // determine function arguments
61 :
62 : // helper variables for parameter consistency checks
63 : const auto from_data_file =
64 130 : isParamSetByUser("data_file") + isParamSetByUser("header") + isParamSetByUser("delimiter") +
65 130 : isParamSetByUser("comment") + isParamSetByUser("time_column_index") +
66 130 : isParamSetByUser("blocks_from_column_index") + isParamSetByUser("blocks_to_column_index") +
67 130 : isParamSetByUser("time_column_text") + isParamSetByUser("blocks_from_column_text") +
68 65 : isParamSetByUser("blocks_to_column_text");
69 :
70 130 : const auto from_data_File_needs_header = isParamSetByUser("time_column_text") +
71 130 : isParamSetByUser("blocks_from_column_text") +
72 65 : isParamSetByUser("blocks_to_column_text");
73 :
74 : const auto from_parameters =
75 65 : isParamSetByUser("times") + isParamSetByUser("blocks_from") + isParamSetByUser("blocks_to");
76 :
77 : // Check parameter set for inconsistencies
78 65 : const auto from_source_count = ((from_data_file > 0) + (from_parameters > 0));
79 65 : if (from_source_count != 1)
80 : {
81 0 : 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 65 : if (from_parameters > 0)
87 : {
88 52 : if (from_parameters != 3)
89 0 : mooseError("All parameters 'times', and 'blocks_from', and 'blocks_to' must be specified.");
90 52 : buildFromParameters();
91 : }
92 13 : else if (from_data_file > 0)
93 : {
94 13 : if ((isParamSetByUser("time_column_index") + isParamSetByUser("time_column_text")) > 1)
95 0 : mooseError(
96 : "The parameters 'time_column_index', and 'time_column_text' are mutual exclusive.");
97 26 : if ((isParamSetByUser("blocks_from_column_index") +
98 13 : isParamSetByUser("blocks_from_column_text")) > 1)
99 0 : mooseError("The parameters 'blocks_from_column_index', and 'blocks_from_column_text' are "
100 : "mutual exclusive.");
101 13 : if ((isParamSetByUser("blocks_to_column_index") + isParamSetByUser("blocks_to_column_text")) >
102 : 1)
103 0 : mooseError("The parameters 'blocks_to_column_index', and 'blocks_to_column_text' are mutual "
104 : "exclusive.");
105 13 : if ((from_data_File_needs_header > 0) && (isParamSetByUser("header") == 0))
106 0 : mooseError("Header flag must be active if columns are to be found via header.");
107 :
108 13 : buildFromFile();
109 : }
110 : else
111 0 : mooseError("Unknown data source. Are you missing a parameter? Did you misspell one?");
112 65 : }
113 :
114 : void
115 52 : TimedSubdomainModifier::buildFromParameters()
116 : {
117 52 : _times = getParam<std::vector<Real>>("times");
118 52 : const auto n = _times.size();
119 :
120 52 : const auto raw_from = getParam<std::vector<SubdomainName>>("blocks_from");
121 52 : const auto raw_to = getParam<std::vector<SubdomainName>>("blocks_to");
122 :
123 52 : if (raw_from.size() != n)
124 0 : mooseError(
125 : "Parameter 'blocks_from' must contain the same number of items as parameter 'times'.");
126 52 : if (raw_to.size() != n)
127 0 : mooseError("Parameter 'blocks_to' must contain the same number of items as parameter 'times'.");
128 :
129 52 : _blocks_from.resize(n);
130 52 : _blocks_to.resize(n);
131 :
132 169 : for (const auto i : index_range(raw_from))
133 : {
134 117 : _blocks_from[i] = getSubdomainIDAndCheck(raw_from[i]);
135 117 : _blocks_to[i] = getSubdomainIDAndCheck(raw_to[i]);
136 : }
137 52 : }
138 :
139 : void
140 13 : TimedSubdomainModifier::buildFromFile()
141 : {
142 13 : const auto _file_name = getParam<FileName>("data_file");
143 :
144 : /// Flag indicating if the file contains a header.
145 13 : auto _header_flag = MooseUtils::DelimitedFileOfStringReader::HeaderFlag::OFF;
146 13 : if (isParamValid("header"))
147 : {
148 26 : _header_flag = getParam<bool>("header")
149 13 : ? MooseUtils::DelimitedFileOfStringReader::HeaderFlag::ON
150 : : MooseUtils::DelimitedFileOfStringReader::HeaderFlag::OFF;
151 : }
152 :
153 13 : std::string _delimiter = ",";
154 13 : if (isParamValid("delimiter"))
155 : {
156 13 : _delimiter = getParam<std::string>("delimiter");
157 : }
158 :
159 13 : std::string _comment = "#";
160 13 : if (isParamValid("comment"))
161 : {
162 13 : _comment = getParam<std::string>("comment");
163 : }
164 :
165 13 : MooseUtils::DelimitedFileOfStringReader file(_file_name);
166 :
167 13 : file.setHeaderFlag(_header_flag);
168 13 : file.setDelimiter(_delimiter);
169 13 : file.setComment(_comment);
170 13 : file.read();
171 :
172 13 : std::size_t _time_column = 0;
173 13 : if (isParamValid("time_column_text"))
174 : {
175 0 : const auto s = getParam<std::string>("time_column_text");
176 0 : const auto _names = file.getNames();
177 0 : const auto it = find(_names.begin(), _names.end(), s);
178 0 : if (it == _names.end())
179 0 : mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
180 0 : _time_column = std::distance(_names.begin(), it);
181 0 : }
182 13 : else if (isParamValid("time_column_index"))
183 : {
184 13 : _time_column = getParam<std::size_t>("time_column_index");
185 : }
186 :
187 13 : std::size_t _blocks_from_column = 1;
188 13 : if (isParamValid("blocks_from_column_text"))
189 : {
190 0 : const auto s = getParam<std::string>("blocks_from_column_text");
191 0 : const auto _names = file.getNames();
192 0 : const auto it = find(_names.begin(), _names.end(), s);
193 0 : if (it == _names.end())
194 0 : mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
195 0 : _blocks_from_column = std::distance(_names.begin(), it);
196 0 : }
197 13 : else if (isParamValid("blocks_from_column_index"))
198 : {
199 13 : _blocks_from_column = getParam<std::size_t>("blocks_from_column_index");
200 : }
201 :
202 13 : std::size_t _blocks_to_column = 2;
203 13 : if (isParamValid("blocks_to_column_text"))
204 : {
205 0 : const auto s = getParam<std::string>("blocks_to_column_text");
206 0 : const auto _names = file.getNames();
207 0 : const auto it = find(_names.begin(), _names.end(), s);
208 0 : if (it == _names.end())
209 0 : mooseError("Could not find '", s, "' in header of file ", _file_name, ".");
210 0 : _blocks_to_column = std::distance(_names.begin(), it);
211 0 : }
212 13 : else if (isParamValid("blocks_to_column_index"))
213 13 : _blocks_to_column = getParam<std::size_t>("blocks_to_column_index");
214 :
215 : const auto max_needed_column_index =
216 13 : std::max({_time_column, _blocks_from_column, _blocks_to_column});
217 :
218 13 : const auto data = file.getData();
219 :
220 13 : if (data.size() < max_needed_column_index)
221 0 : mooseError("data must contain at least " + std::to_string(max_needed_column_index) +
222 : " columns in file ",
223 : _file_name);
224 :
225 13 : const auto strTimes = data[_time_column];
226 13 : const auto strBlockFrom = data[_blocks_from_column];
227 13 : const auto strBlockTo = data[_blocks_to_column];
228 :
229 13 : const auto n_rows = strTimes.size();
230 :
231 : // some sanity checks
232 13 : if (n_rows == 0)
233 0 : mooseError("empty sequence in file ", _file_name);
234 13 : if (n_rows != strBlockFrom.size())
235 0 : mooseError("Inconsistent source block data size in ",
236 : _file_name,
237 : ". Expected ",
238 : n_rows,
239 : " and read ",
240 0 : strBlockFrom.size());
241 13 : if (n_rows != strBlockTo.size())
242 0 : mooseError("Inconsistent target block data size in ",
243 : _file_name,
244 : ". Expected ",
245 : n_rows,
246 : " and read ",
247 0 : strBlockTo.size());
248 :
249 : // resize variables to fit the data
250 13 : _blocks_from.resize(n_rows);
251 13 : _blocks_to.resize(n_rows);
252 :
253 : // fill the to and from blocks vectors
254 39 : for (const auto & time_str : strTimes)
255 26 : _times.push_back(std::stod(time_str));
256 13 : std::transform(strBlockFrom.begin(),
257 : strBlockFrom.end(),
258 : _blocks_from.begin(),
259 26 : [this](const std::string & x) { return getSubdomainIDAndCheck(x); });
260 13 : std::transform(strBlockTo.begin(),
261 : strBlockTo.end(),
262 : _blocks_to.begin(),
263 26 : [this](const std::string & x) { return getSubdomainIDAndCheck(x); });
264 13 : }
265 :
266 : SubdomainID
267 286 : TimedSubdomainModifier::getSubdomainIDAndCheck(const std::string & subdomain_name)
268 : {
269 286 : const auto id = _mesh.getSubdomainID(subdomain_name);
270 286 : if (id == Moose::INVALID_BLOCK_ID)
271 0 : mooseError("block", "Subdomain \"" + subdomain_name + "\" not found in mesh.");
272 286 : return id;
273 : }
274 :
275 : SubdomainID
276 150016 : TimedSubdomainModifier::computeSubdomainID()
277 : {
278 : // get the subdomain-id of the current element
279 150016 : SubdomainID resulting_subdomain_id = _current_elem->subdomain_id();
280 :
281 : // check for all the subdomain changes that can have been requested between the previous and the
282 : // current time
283 528256 : for (const auto & time_pair : _times_and_indices)
284 : {
285 : // time of the data point
286 378240 : const auto t = time_pair.time;
287 :
288 : // original data point index
289 378240 : const auto j = time_pair.index;
290 :
291 : // do we have to apply?
292 378240 : if (t > _t_old && t <= _t && resulting_subdomain_id == _blocks_from[j])
293 : {
294 : // we have to change the subdomain-id using the original index (stored in 'j')
295 2256 : resulting_subdomain_id = _blocks_to[j];
296 : }
297 : }
298 :
299 150016 : return resulting_subdomain_id;
300 : }
|