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 "GriddedData.h"
11 : #include "MooseUtils.h"
12 : #include <fstream>
13 : #include <algorithm>
14 :
15 : /**
16 : * Creates a GriddedData object by reading info from file_name
17 : * A grid is defined in _grid.
18 : * For example, if grid[0] = {1, 2, 3} and grid[1] = {-1, 1}
19 : * this defines a 2D grid (_dim = 2), with points
20 : * (1,-1), (2,-1), (3,-1), (1,1), (2,1), (3,1)
21 : * The i_th axis of the grid corresponds to the axes[i] axis
22 : * of the simulation: see the function getAxes
23 : * Values at each grid point are stored in _fcn.
24 : * They are ordered as in the example above.
25 : * _step is just a quantity used in evaluateFcn
26 : * The file must have the following format:
27 : * All blank lines and lines starting with # are ignored
28 : * The first significant line (not blank or starting with #)
29 : * should be either
30 : * AXIS X
31 : * or
32 : * AXIS Y
33 : * or
34 : * AXIS Z
35 : * or
36 : * AXIS T
37 : * The next significant line should be a space-separated
38 : * array of real numbers defining the grid along that axis
39 : * direction.
40 : * Any number of AXIS and subsequent space-separated arrays
41 : * can be defined, but if using this in conjunction with
42 : * PiecewiseMultilinear, a maximum of 4 should be defined.
43 : * The AXIS lines define the grid in the MOOSE simulation reference
44 : * frame, and is used by PiecewiseMultilinear, for instance.
45 : * The next significant line should be DATA
46 : * All significant lines after DATA should be the function values
47 : * at each grid point, on any number of lines of the file, but
48 : * each line must be space separated. The ordering is such
49 : * that when the function is evaluated, f[i,j,k,l] corresponds
50 : * to the i + j*Ni + k*Ni*Nj + l*Ni*Nj*Nk data value. Here
51 : * i>=0 corresponds to the index along the first AXIS, and Ni is
52 : * the number of grid points along that axis, etc.
53 : * See the function parse for an example.
54 : */
55 261 : GriddedData::GriddedData(std::string file_name)
56 : {
57 264 : parse(_dim, _axes, _grid, _fcn, _step, file_name);
58 249 : }
59 :
60 : unsigned int
61 237 : GriddedData::getDim()
62 : {
63 237 : return _dim;
64 : }
65 :
66 : void
67 237 : GriddedData::getAxes(std::vector<int> & axes)
68 : {
69 237 : axes.resize(_dim);
70 237 : std::copy(_axes.begin(), _axes.end(), axes.begin());
71 237 : }
72 :
73 : void
74 237 : GriddedData::getGrid(std::vector<std::vector<Real>> & grid)
75 : {
76 237 : grid.resize(_dim);
77 576 : for (unsigned int i = 0; i < _dim; ++i)
78 : {
79 339 : grid[i].resize(_grid[i].size());
80 339 : std::copy(_grid[i].begin(), _grid[i].end(), grid[i].begin());
81 : }
82 237 : }
83 :
84 : void
85 2 : GriddedData::getFcn(std::vector<Real> & fcn)
86 : {
87 2 : fcn.resize(_fcn.size());
88 2 : std::copy(_fcn.begin(), _fcn.end(), fcn.begin());
89 2 : }
90 :
91 : Real
92 9609344 : GriddedData::evaluateFcn(const GridIndex & ijk)
93 : {
94 9609344 : if (ijk.size() != _dim)
95 0 : mooseError(
96 0 : "Gridded data evaluateFcn called with ", ijk.size(), " arguments, but expected ", _dim);
97 9609344 : unsigned int index = ijk[0];
98 28872384 : for (unsigned int i = 1; i < _dim; ++i)
99 19263040 : index += ijk[i] * _step[i];
100 9609344 : if (index >= _fcn.size())
101 0 : mooseError("Gridded data evaluateFcn attempted to access index ",
102 : index,
103 : " of function, but it contains only ",
104 0 : _fcn.size(),
105 : " entries");
106 9609344 : return _fcn[index];
107 : }
108 :
109 : void
110 261 : GriddedData::parse(unsigned int & dim,
111 : std::vector<int> & axes,
112 : std::vector<std::vector<Real>> & grid,
113 : std::vector<Real> & f,
114 : std::vector<unsigned int> & step,
115 : std::string file_name)
116 : {
117 : // initialize
118 261 : dim = 0;
119 261 : axes.resize(0);
120 261 : grid.resize(0);
121 261 : f.resize(0);
122 :
123 : // open file and initialize quantities
124 261 : std::ifstream file(file_name.c_str());
125 261 : if (!file.good())
126 7 : mooseError("Error opening file '" + file_name + "' from GriddedData.");
127 254 : std::string line;
128 254 : bool reading_grid_data = false;
129 254 : bool reading_value_data = false;
130 :
131 : // read file line-by-line extracting data
132 38911 : while (getSignificantLine(file, line))
133 : {
134 : // look for AXIS keywords
135 38657 : reading_grid_data = false;
136 38657 : if (line.compare("AXIS X") == 0)
137 : {
138 201 : dim += 1;
139 201 : reading_grid_data = true;
140 201 : axes.push_back(0);
141 : }
142 38456 : else if (line.compare("AXIS Y") == 0)
143 : {
144 69 : dim += 1;
145 69 : reading_grid_data = true;
146 69 : axes.push_back(1);
147 : }
148 38387 : else if (line.compare("AXIS Z") == 0)
149 : {
150 14 : dim += 1;
151 14 : reading_grid_data = true;
152 14 : axes.push_back(2);
153 : }
154 38373 : else if (line.compare("AXIS T") == 0)
155 : {
156 66 : dim += 1;
157 66 : reading_grid_data = true;
158 66 : axes.push_back(3);
159 : }
160 :
161 : // just found an AXIS keyword
162 38657 : if (reading_grid_data)
163 : {
164 350 : grid.resize(dim); // add another dimension to the grid
165 350 : grid[dim - 1].resize(0);
166 350 : if (getSignificantLine(file, line))
167 349 : splitToRealVec(line, grid[dim - 1]);
168 350 : continue; // read next line from file
169 : }
170 :
171 : // previous significant line must have been DATA
172 38307 : if (reading_value_data)
173 38026 : splitToRealVec(line, f);
174 :
175 : // look for DATA keyword
176 38307 : if (line.compare("DATA") == 0)
177 253 : reading_value_data = true;
178 :
179 : // ignore any other lines - if we get here probably the data file is corrupt
180 : }
181 :
182 : // check that some axes have been defined
183 254 : if (dim == 0)
184 8 : mooseError("No valid AXIS lines found by GriddedData");
185 :
186 : // step is useful in evaluateFcn
187 246 : step.resize(dim);
188 246 : step[0] = 1; // this is actually not used
189 350 : for (unsigned int i = 1; i < dim; ++i)
190 104 : step[i] = step[i - 1] * grid[i - 1].size();
191 :
192 : // perform some checks
193 246 : unsigned int num_data_points = 1;
194 595 : for (unsigned int i = 0; i < dim; ++i)
195 : {
196 350 : if (grid[i].size() == 0)
197 1 : mooseError("Axis ", i, " in your GriddedData has zero size");
198 349 : num_data_points *= grid[i].size();
199 : }
200 245 : if (num_data_points != f.size())
201 8 : mooseError("According to AXIS statements in GriddedData, number of data points is ",
202 : num_data_points,
203 : " but ",
204 8 : f.size(),
205 : " function values were read from file");
206 243 : }
207 :
208 : bool
209 39261 : GriddedData::getSignificantLine(std::ifstream & file_stream, std::string & line)
210 : {
211 39707 : while (std::getline(file_stream, line))
212 : {
213 39452 : if (line.size() == 0) // empty line: read next line from file
214 21 : continue;
215 39431 : if (line[0] == '#') // just a comment: read next line from file
216 425 : continue;
217 : // have got a significant line
218 39006 : return true;
219 : }
220 : // have run out of file
221 255 : return false;
222 : }
223 :
224 : void
225 38375 : GriddedData::splitToRealVec(const std::string & input_string, std::vector<Real> & output_vec)
226 : {
227 38375 : std::vector<Real> values;
228 38375 : bool status = MooseUtils::tokenizeAndConvert<Real>(input_string, values, " ");
229 :
230 38375 : if (!status)
231 0 : mooseError("GriddedData: Failed to convert string into Real when reading line ", input_string);
232 :
233 78469 : for (auto val : values)
234 40094 : output_vec.push_back(val);
235 38375 : }
|