PRISMS-PF  v2.1
inputFileReader.cc
Go to the documentation of this file.
1 // Methods for the inputFileReader class
2 #include "../../include/inputFileReader.h"
3 #include "../../include/sortIndexEntryPairList.h"
4 #include "../../include/EquationDependencyParser.h"
5 #include <deal.II/base/mpi.h>
6 #include <deal.II/base/utilities.h>
7 #include <iostream>
8 
9 // Constructor
10 inputFileReader::inputFileReader(std::string input_file_name, variableAttributeLoader variable_attributes){
11  // Extract an ordered vector of the variable types from variable_attributes
12  unsigned int number_of_variables = variable_attributes.var_name_list.size();
13  var_types = variable_attributes.var_type;
14  var_eq_types = variable_attributes.var_eq_type;
15  var_names = variable_attributes.var_name;
16 
17  var_nonlinear = variable_attributes.var_nonlinear;
18 
19  var_nucleates = sortIndexEntryPairList(variable_attributes.nucleating_variable_list,number_of_variables,false);
20 
21  num_pp_vars = variable_attributes.var_name_list_PP.size();
22 
23  num_constants = get_number_of_entries(input_file_name,"set","Model constant");
24 
25  model_constant_names = get_entry_name_ending_list(input_file_name,"set", "Model constant");
26 
27  if (dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0){
28  std::cout << "Number of constants: " << num_constants << std::endl;
29  std::cout << "Number of post-processing variables: " << num_pp_vars << std::endl;
30  }
31 
32  // Read in all of the parameters now
34  #if (DEAL_II_VERSION_MAJOR < 9 && DEAL_II_VERSION_MINOR < 5)
35  parameter_handler.read_input(input_file_name);
36  #else
37  parameter_handler.parse_input(input_file_name);
38  #endif
39  number_of_dimensions = parameter_handler.get_integer("Number of dimensions");
40 }
41 
42 
43 // Method to parse a single line to find a target key value pair
44 bool inputFileReader::parse_line(std::string line, const std::string keyword, const std::string entry_name,
45  std::string & out_string, const bool expect_equals_sign) const
46  {
47 
48  // Strip spaces at the front and back
49  while ((line.size() > 0) && (line[0] == ' ' || line[0] == '\t'))
50  line.erase(0, 1);
51  while ((line.size() > 0)
52  && (line[line.size() - 1] == ' ' || line[line.size() - 1] == '\t'))
53  line.erase(line.size() - 1, std::string::npos);
54 
55  // now see whether the line starts with 'keyword' followed by multiple spaces
56  // if not, try next line (if the entry is "", then zero spaces after the keyword is ok)
57  if (line.size() < keyword.size())
58  return false;
59 
60  for (unsigned int i=0; i<keyword.size(); i++){
61  if (line[i] != keyword[i])
62  return false;
63  }
64  if (entry_name.size() > 0){
65  if (!(line[keyword.size()] == ' ' || line[keyword.size()] == '\t'))
66  return false;
67  }
68 
69  // delete the "keyword" and then delete more spaces if present
70  line.erase(0, keyword.size());
71  while ((line.size() > 0) && (line[0] == ' ' || line[0] == '\t'))
72  line.erase(0, 1);
73  // now see whether the next word is the word we look for
74  if (line.find(entry_name) != 0)
75  return false;
76 
77  line.erase(0, entry_name.size());
78  while ((line.size() > 0) && (line[0] == ' ' || line[0] == '\t'))
79  line.erase(0, 1);
80 
81  // we'd expect an equals size here if expect_equals_sign is true
82  if (expect_equals_sign){
83  if ((line.size() < 1) || (line[0] != '='))
84  return false;
85  }
86 
87  // remove comment
88  std::string::size_type pos = line.find('#');
89  if (pos != std::string::npos)
90  line.erase (pos);
91 
92  // trim the equals sign at the beginning and possibly following spaces
93  // as well as spaces at the end
94  if (expect_equals_sign)
95  line.erase(0, 1);
96 
97  while ((line.size() > 0) && (line[0] == ' ' || line[0] == '\t'))
98  line.erase(0, 1);
99 
100  while ((line.size() > 0) && (line[line.size()-1] == ' ' || line[line.size()-1] == '\t'))
101  line.erase(line.size()-1, std::string::npos);
102 
103  out_string = line;
104  return true;
105 }
106 
107 // Method to parse an input file to get a list of variables from related subsections
108 std::vector<std::string> inputFileReader::get_subsection_entry_list(const std::string parameters_file_name,
109  const std::string subsec_name, const std::string entry_name, const std::string default_entry) const
110  {
111 
112  std::ifstream input_file;
113  input_file.open(parameters_file_name);
114 
115  std::string line, entry;
116  bool in_subsection = false;
117  bool found_entry, desired_entry_found;
118  unsigned int subsection_index;
119  std::vector<std::string> entry_list;
120  std::vector<unsigned int> index_list;
121 
122  // Loop through each line
123  while (std::getline(input_file, line))
124  {
125  // If the line is the start of a subsection, turn 'in_subsection' to true and store the subsection index
126  if (!in_subsection){
127  found_entry = parse_line(line, "subsection",subsec_name, entry, false);
128  if ( found_entry){
129  in_subsection = true;
130  subsection_index = dealii::Utilities::string_to_int(entry);
131  desired_entry_found = false;
132  }
133  }
134  // If in a subsection, look for the line setting the entry or for the end of the subsection
135  else {
136  found_entry = parse_line(line, "set", entry_name, entry, true);
137  if (found_entry) {
138  entry_list.push_back(entry);
139  index_list.push_back(subsection_index);
140  desired_entry_found = true;
141  }
142  found_entry = parse_line(line, "end", "", entry, false);
143  if (found_entry) {
144  if (!desired_entry_found){
145  entry_list.push_back(default_entry);
146  index_list.push_back(subsection_index);
147  }
148  in_subsection = false;
149  desired_entry_found = false;
150  }
151  }
152  }
153 
154  // Now sort the entry list vector so that it is in index order
155  std::vector<std::string> sorted_entry_list;
156  for (unsigned int i=0; i<entry_list.size(); i++){
157  for (unsigned int j=0; j<entry_list.size(); j++){
158  if (i == j){
159  sorted_entry_list.push_back(entry_list[index_list[j]]);
160  break;
161  }
162  }
163  }
164  return sorted_entry_list;
165 }
166 
167 // Method to parse an input file to get a list of variables from related subsections
168 unsigned int inputFileReader::get_number_of_entries(const std::string parameters_file_name,
169  const std::string keyword, const std::string entry_name) const
170  {
171 
172  std::ifstream input_file;
173  input_file.open(parameters_file_name);
174 
175  std::string line, entry;
176  bool found_entry;
177 
178  unsigned int count = 0;
179 
180  // Loop through each line
181  while (std::getline(input_file, line))
182  {
183 
184  found_entry = parse_line(line, keyword, entry_name, entry, false);
185  if (found_entry)
186  count++;
187  }
188  return count;
189 }
190 
191 // Method to parse an input file to get a list of variables from related subsections
192 std::vector<std::string> inputFileReader::get_entry_name_ending_list(const std::string parameters_file_name,
193  const std::string keyword, const std::string entry_name_begining) const
194  {
195 
196  std::ifstream input_file;
197  input_file.open(parameters_file_name);
198 
199  std::string line, entry;
200  bool found_entry;
201 
202  std::vector<std::string> entry_name_end_list;
203 
204  // Loop through each line
205  while (std::getline(input_file, line))
206  {
207 
208  found_entry = parse_line(line, keyword, entry_name_begining, entry, false);
209  if (found_entry){
210 
211  // Strip whitespace, the equals sign, and everything after the equals sign
212 
213  // Strip whitespace at the beginning
214  while ((entry.size() > 0) && (entry[0] == ' ' || entry[0] == '\t'))
215  entry.erase(0, 1);
216 
217  // Strip everything up to the equals sign
218  while ((entry.size() > 0) && (entry[entry.size() - 1] != '=' ))
219  entry.erase(entry.size() - 1, std::string::npos);
220 
221  //Strip the equals sign
222  entry.erase(entry.size() - 1, std::string::npos);
223 
224  // Strip whitespace between the entry name and the equals sign
225  while ((entry.size() > 0) && (entry[entry.size() - 1] == ' ' || entry[entry.size() - 1] == '\t'))
226  entry.erase(entry.size() - 1, std::string::npos);
227 
228  // Add it to the list
229  entry_name_end_list.push_back(entry);
230  }
231 
232  }
233  return entry_name_end_list;
234 }
235 
236 void inputFileReader::declare_parameters(dealii::ParameterHandler & parameter_handler,
237  const std::vector<fieldType> var_types,
238  const std::vector<PDEType> var_eq_types,
239  const unsigned int num_of_constants,
240  const std::vector<bool> var_nucleates) const {
241 
242  // Declare all of the entries
243  parameter_handler.declare_entry("Number of dimensions","-1",dealii::Patterns::Integer(),"The number of dimensions for the simulation.");
244 
245  parameter_handler.declare_entry("Domain size X","-1",dealii::Patterns::Double(),"The size of the domain in the x direction.");
246  parameter_handler.declare_entry("Domain size Y","-1",dealii::Patterns::Double(),"The size of the domain in the y direction.");
247  parameter_handler.declare_entry("Domain size Z","-1",dealii::Patterns::Double(),"The size of the domain in the z direction.");
248  parameter_handler.declare_entry("Element degree","1",dealii::Patterns::Integer(),"The polynomial order of the finte element.");
249  parameter_handler.declare_entry("Subdivisions X","1",dealii::Patterns::Integer(),"The number of mesh subdivisions in the x direction.");
250  parameter_handler.declare_entry("Subdivisions Y","1",dealii::Patterns::Integer(),"The number of mesh subdivisions in the y direction.");
251  parameter_handler.declare_entry("Subdivisions Z","1",dealii::Patterns::Integer(),"The number of mesh subdivisions in the z direction.");
252  parameter_handler.declare_entry("Refine factor","-1",dealii::Patterns::Integer(),"The number of initial refinements of the coarse mesh.");
253 
254  parameter_handler.declare_entry("Mesh adaptivity","false",dealii::Patterns::Bool(),"Whether to enable mesh adaptivity.");
255  parameter_handler.declare_entry("Max refinement level","-1",dealii::Patterns::Integer(),"The maximum level of refinement.");
256  parameter_handler.declare_entry("Min refinement level","-1",dealii::Patterns::Integer(),"The minimum level of refinement.");
257  parameter_handler.declare_entry("Refinement criteria fields","0",dealii::Patterns::List(dealii::Patterns::Anything()),"The list of fields used to determine mesh refinement.");
258  parameter_handler.declare_entry("Refinement window max","",dealii::Patterns::List(dealii::Patterns::Anything()),"The upper limit for refinement for each of the criteria fields.");
259  parameter_handler.declare_entry("Refinement window min","",dealii::Patterns::List(dealii::Patterns::Anything()),"The lower limit for refinement for each of the criteria fields.");
260  parameter_handler.declare_entry("Steps between remeshing operations","1",dealii::Patterns::Integer(),"The number of time steps between mesh refinement operations.");
261 
262  parameter_handler.declare_entry("Number of time steps","-1",dealii::Patterns::Integer(),"The time step size for the simulation.");
263  parameter_handler.declare_entry("Time step","-0.1",dealii::Patterns::Double(),"The time step size for the simulation.");
264  parameter_handler.declare_entry("Simulation end time","-0.1",dealii::Patterns::Double(),"The value of simulated time where the simulation ends.");
265 
266  for (unsigned int i=0; i<var_types.size(); i++){
268  std::string subsection_text = "Linear solver parameters: ";
269  subsection_text.append(var_names.at(i));
270  parameter_handler.enter_subsection(subsection_text);
271  {
272  parameter_handler.declare_entry("Tolerance type","RELATIVE_RESIDUAL_CHANGE",dealii::Patterns::Anything(),"The tolerance type for the linear solver.");
273  parameter_handler.declare_entry("Tolerance value","1.0e-10",dealii::Patterns::Double(),"The value of for the linear solver tolerance.");
274  parameter_handler.declare_entry("Maximum linear solver iterations","1000",dealii::Patterns::Integer(),"The maximum number of linear solver iterations before the loop is stopped.");
275  }
276  parameter_handler.leave_subsection();
277  }
278  }
279 
280 
281  parameter_handler.declare_entry("Maximum nonlinear solver iterations","100",dealii::Patterns::Integer(),"The maximum number of nonlinear solver iterations before the loop is stopped.");
282 
283  for (unsigned int i=0; i<var_types.size(); i++){
284  if (var_nonlinear.at(i)){
285  std::string subsection_text = "Nonlinear solver parameters: ";
286  subsection_text.append(var_names.at(i));
287  parameter_handler.enter_subsection(subsection_text);
288  {
289  parameter_handler.declare_entry("Tolerance type","ABSOLUTE_SOLUTION_CHANGE",dealii::Patterns::Anything(),"The tolerance type for the nonlinear solver.");
290  parameter_handler.declare_entry("Tolerance value","1.0e-10",dealii::Patterns::Double(),"The value of for the nonlinear solver tolerance.");
291  parameter_handler.declare_entry("Use backtracking line search damping","true",dealii::Patterns::Bool(),"Whether to use a backtracking line-search to find the best choice of the damping coefficient.");
292  parameter_handler.declare_entry("Backtracking step size modifier","0.5",dealii::Patterns::Double(),"The constant that determines how much the step size decreases per backtrack. The 'tau' parameter.");
293  parameter_handler.declare_entry("Backtracking residual decrease coefficient","1.0",dealii::Patterns::Double(),"The constant that determines how much the residual must decrease to be accepted as sufficient. The 'c' parameter.");
294  parameter_handler.declare_entry("Constant damping value","1.0",dealii::Patterns::Double(),"The constant damping value to be used if the backtrace line-search approach isn't used.");
295  parameter_handler.declare_entry("Use Laplace's equation to determine the initial guess","false",dealii::Patterns::Bool(),"Whether to use the solution of Laplace's equation instead of the IC in ICs_and_BCs.h as the initial guess for nonlinear, time independent equations. This guarantees smoothness and compliance with BCs.");
296  }
297  parameter_handler.leave_subsection();
298  }
299  }
300 
301  parameter_handler.declare_entry("Output file name (base)","solution",dealii::Patterns::Anything(),"The name for the output file, before the time step and processor info are added.");
302  parameter_handler.declare_entry("Output file type","vtu",dealii::Patterns::Anything(),"The output file type (either vtu or vtk).");
303  parameter_handler.declare_entry("Output separate files per process","false",dealii::Patterns::Bool(),"Whether to output separate vtu files for each process in a parallel calculation (automatically set to true for vtk files).");
304  parameter_handler.declare_entry("Output condition","EQUAL_SPACING",dealii::Patterns::Anything(),"The spacing type for outputing the solution fields.");
305  parameter_handler.declare_entry("List of time steps to output","0",dealii::Patterns::Anything(),"The list of time steps to output, used for the LIST type.");
306  parameter_handler.declare_entry("Number of outputs","10",dealii::Patterns::Integer(),"The number of outputs (or number of outputs per decade for the N_PER_DECADE type).");
307  parameter_handler.declare_entry("Skip print steps","1",dealii::Patterns::Integer(),"The number of time steps between updates to the screen.");
308 
309  // Declare entries for reading initial conditions from file
310  parameter_handler.declare_entry("Load initial conditions","void",dealii::Patterns::Anything(),"Whether to load the initial conditions for each variable from file.");
311  parameter_handler.declare_entry("Load parallel file","void",dealii::Patterns::Anything(),"Whether all processors should read from a single file (versus each reading from separate files).");
312  parameter_handler.declare_entry("File names","void",dealii::Patterns::Anything(),"The file name to load from for each variable.");
313  parameter_handler.declare_entry("Variable names in the files","void",dealii::Patterns::Anything(),"What each variable is named in the file being loaded.");
314 
315  // Checkpoint/restart
316  parameter_handler.declare_entry("Load from a checkpoint","false",dealii::Patterns::Bool(),"Whether to load from a checkpoint created during a previous simulation.");
317  parameter_handler.declare_entry("Checkpoint condition","EQUAL_SPACING",dealii::Patterns::Anything(),"The spacing type for saving checkpoints.");
318  parameter_handler.declare_entry("List of time steps to save checkpoints","0",dealii::Patterns::Anything(),"The list of time steps to save checkpoints, used for the LIST type.");
319  parameter_handler.declare_entry("Number of checkpoints","1",dealii::Patterns::Integer(),"The number of checkpoints (or number of checkpoints per decade for the N_PER_DECADE type).");
320 
321 
322  // Declare the boundary condition variables
323  for (unsigned int i=0; i<var_types.size(); i++){
324  if (var_types[i] == SCALAR){
325  std::string bc_text = "Boundary condition for variable ";
326  bc_text.append(var_names.at(i));
327  parameter_handler.declare_entry(bc_text,"",dealii::Patterns::Anything(),"The boundary conditions for one of the governing equations).");
328  }
329  else {
330  std::string bc_text = "Boundary condition for variable ";
331  bc_text.append(var_names.at(i));
332  bc_text.append(", x component");
333  parameter_handler.declare_entry(bc_text,"",dealii::Patterns::Anything(),"The boundary conditions for one of the governing equations).");
334 
335  bc_text = "Boundary condition for variable ";
336  bc_text.append(var_names.at(i));
337  bc_text.append(", y component");
338  parameter_handler.declare_entry(bc_text,"",dealii::Patterns::Anything(),"The boundary conditions for one of the governing equations).");
339 
340  bc_text = "Boundary condition for variable ";
341  bc_text.append(var_names.at(i));
342  bc_text.append(", z component");
343  parameter_handler.declare_entry(bc_text,"",dealii::Patterns::Anything(),"The boundary conditions for one of the governing equations).");
344  }
345 
346  }
347 
348  // Declare the nucleation parameters
349  parameter_handler.declare_entry("Minimum allowed distance between nuclei","-1",dealii::Patterns::Double(),"The minimum allowed distance between nuclei placed during the same time step.");
350  parameter_handler.declare_entry("Order parameter cutoff value","0.01",dealii::Patterns::Double(),"Order parameter cutoff value for nucleation (when the sum of all order parameters is above this value, no nucleation is attempted).");
351  parameter_handler.declare_entry("Time steps between nucleation attempts","100",dealii::Patterns::Integer(),"The number of time steps between nucleation attempts.");
352 
353  for (unsigned int i=0; i<var_types.size(); i++){
354  if (var_nucleates.at(i)){
355  std::string nucleation_text = "Nucleation parameters: ";
356  nucleation_text.append(var_names.at(i));
357  parameter_handler.enter_subsection(nucleation_text);
358  {
359  parameter_handler.declare_entry("Nucleus semiaxes (x, y, z)","0,0,0",dealii::Patterns::List(dealii::Patterns::Double()),"The semiaxes for nuclei placed with the explicit nucleation algorithm.");
360  parameter_handler.declare_entry("Nucleus rotation in degrees (x, y, z)","0,0,0",dealii::Patterns::List(dealii::Patterns::Double()),"The rotation of the nuclei placed with the explicit nucleation algorithm. The rotations are given with respect to the normal direction using intrinsic Tait-Bryan angles.");
361  parameter_handler.declare_entry("Freeze zone semiaxes (x, y, z)","0,0,0",dealii::Patterns::List(dealii::Patterns::Double()),"The semiaxes for region where the order parameter is frozen for a period of time after placement.");
362  parameter_handler.declare_entry("Freeze time following nucleation","0.0",dealii::Patterns::Double(),"Duration that the order parameter is frozen after placement.");
363  parameter_handler.declare_entry("Nucleation-free border thickness","0.0",dealii::Patterns::Double(),"The thickness of the nucleation-free region near the domain boundaries (ignored for periodic BCs).");
364  }
365  parameter_handler.leave_subsection();
366  }
367  }
368 
369  // Declare the grain remapping constants
370  parameter_handler.declare_entry("Activate grain reassignment","false",dealii::Patterns::Bool(),"Whether to enable the grain reassignment capabilities of PRISMS-PF where multiple grains are packed into a single order parameter.");
371 
372  parameter_handler.declare_entry("Time steps between grain reassignments","100",dealii::Patterns::Integer(),"The number of time steps between times when the grain reassignment algorithm is triggered.");
373 
374  parameter_handler.declare_entry("Order parameter cutoff for grain identification","1.0e-4",dealii::Patterns::Double(),"The threshold value of the order parameter where the element is considered to be in the grain or out of the grain.");
375 
376  parameter_handler.declare_entry("Buffer between grains before reassignment","-1.0",dealii::Patterns::Double(),"The buffer value added to the radius of all grains used to calculation whether grains should be reassigned.");
377 
378  parameter_handler.declare_entry("Order parameter fields for grain reassignment","",dealii::Patterns::List(dealii::Patterns::Anything()),"The list of field indices for the shared order parameters for grain reassignment.");
379 
380  parameter_handler.declare_entry("Load grain structure","false",dealii::Patterns::Bool(),"Whether to load a grain structure in from file.");
381 
382  parameter_handler.declare_entry("Grain structure filename","",dealii::Patterns::Anything(),"The filename (not including the '.vtk' extension) for the file holding the grain structure to be loaded.");
383 
384  parameter_handler.declare_entry("Grain structure variable name","",dealii::Patterns::Anything(),"The variable name in the file holding the grain structure to be loaded that contains the grain ids.");
385 
386  parameter_handler.declare_entry("Number of smoothing cycles after grain structure loading","10",dealii::Patterns::Integer(),"The number of times a diffusion smoother is run on the order parameters after the grains are loaded from file. The smoothing is necessary for the adaptive mesher to work properly.");
387 
388  parameter_handler.declare_entry("Minimum radius for loaded grains","0.0",dealii::Patterns::Double(),"The minimum radius for a body to be considered a grain instead of an artifact from the loading process.");
389 
390 
391  // Declare the user-defined constants
392  for (unsigned int i=0; i<num_of_constants; i++){
393  std::string constants_text = "Model constant ";
394  constants_text.append(model_constant_names[i]);
395  parameter_handler.declare_entry(constants_text,"0",dealii::Patterns::Anything(),"The value of a user-defined constant.");
396  }
397 
398 
399 
400 }
std::vector< std::string > var_name
std::vector< std::pair< unsigned int, bool > > nucleating_variable_list
std::vector< std::pair< unsigned int, std::string > > var_name_list
dealii::ParameterHandler parameter_handler
std::vector< PDEType > var_eq_type
std::vector< PDEType > var_eq_types
void declare_parameters(dealii::ParameterHandler &parameter_handler, const std::vector< fieldType > var_types, const std::vector< PDEType > var_eq_types, const unsigned int num_of_constants, const std::vector< bool >) const
std::vector< fieldType > var_types
std::vector< bool > var_nonlinear
unsigned int get_number_of_entries(const std::string parameters_file_name, const std::string keyword, const std::string entry_name) const
inputFileReader(std::string input_file_name, variableAttributeLoader variable_attributes)
unsigned int number_of_dimensions
std::vector< std::string > get_subsection_entry_list(const std::string parameters_file_name, const std::string subsec_name, const std::string entry_name, const std::string default_entry) const
std::vector< bool > var_nonlinear
std::vector< std::string > get_entry_name_ending_list(const std::string parameters_file_name, const std::string keyword, const std::string entry_name_begining) const
bool parse_line(std::string line, const std::string keyword, const std::string entry_name, std::string &out_string, bool expect_equals_sign) const
std::vector< std::string > var_names
unsigned int num_constants
std::vector< bool > sortIndexEntryPairList(const std::vector< std::pair< unsigned int, bool > > unsorted_pair_list, unsigned int number_of_variables, bool default_value)
std::vector< bool > var_nucleates
std::vector< std::string > model_constant_names
std::vector< fieldType > var_type
std::vector< std::pair< unsigned int, std::string > > var_name_list_PP
unsigned int num_pp_vars