2 #include "../../include/userInputParameters.h" 3 #include <deal.II/base/mpi.h> 4 #include <deal.II/base/utilities.h> 9 loadVariableAttributes(variable_attributes);
14 domain_size.push_back(parameter_handler.get_double(
"Domain size X"));
16 domain_size.push_back(parameter_handler.get_double(
"Domain size Y"));
18 domain_size.push_back(parameter_handler.get_double(
"Domain size Z"));
22 subdivisions.push_back(parameter_handler.get_integer(
"Subdivisions X"));
24 subdivisions.push_back(parameter_handler.get_integer(
"Subdivisions Y"));
26 subdivisions.push_back(parameter_handler.get_integer(
"Subdivisions Z"));
30 refine_factor = parameter_handler.get_integer(
"Refine factor");
32 degree = parameter_handler.get_integer(
"Element degree");
35 h_adaptivity = parameter_handler.get_bool(
"Mesh adaptivity");
36 max_refinement_level = parameter_handler.get_integer(
"Max refinement level");
37 min_refinement_level = parameter_handler.get_integer(
"Min refinement level");
40 if (h_adaptivity && ((refine_factor < min_refinement_level) || (refine_factor > max_refinement_level))){
41 std::cerr <<
"PRISMS-PF Error: The initial refinement factor must be between the maximum and minimum refinement levels when adaptive meshing is enabled." << std::endl;
42 std::cerr <<
"Initial refinement level: " << refine_factor <<
" Maximum and minimum refinement levels: " << max_refinement_level <<
", " << min_refinement_level << std::endl;
47 std::vector<std::string> refine_criterion_fields_str = dealii::Utilities::split_string_list(parameter_handler.get(
"Refinement criteria fields"));
48 for (
unsigned int ref_field=0; ref_field<refine_criterion_fields_str.size(); ref_field++){
49 bool field_found =
false;
50 for (
unsigned int i=0; i<number_of_variables; i++ ){
51 if (boost::iequals(refine_criterion_fields_str[ref_field], variable_attributes.
var_name_list[i].second)){
52 refine_criterion_fields.push_back(variable_attributes.
var_name_list[i].first);
57 if (field_found ==
false && h_adaptivity ==
true){
58 std::cerr <<
"PRISMS-PF Error: Entries in the list of fields used for refinement must match the variable names in equations.h." << std::endl;
59 std::cerr << refine_criterion_fields_str[ref_field] << std::endl;
63 refine_window_max = dealii::Utilities::string_to_double(dealii::Utilities::split_string_list(parameter_handler.get(
"Refinement window max")));
64 refine_window_min = dealii::Utilities::string_to_double(dealii::Utilities::split_string_list(parameter_handler.get(
"Refinement window min")));
66 skip_remeshing_steps = parameter_handler.get_integer(
"Steps between remeshing operations");
69 dtValue = parameter_handler.get_double(
"Time step");
70 int totalIncrements_temp = parameter_handler.get_integer(
"Number of time steps");
71 finalTime = parameter_handler.get_double(
"Simulation end time");
74 for (
unsigned int i=0; i<number_of_variables; i++){
76 std::string subsection_text =
"Linear solver parameters: ";
77 subsection_text.append(input_file_reader.
var_names.at(i));
79 parameter_handler.enter_subsection(subsection_text);
83 std::string type_string = parameter_handler.get(
"Tolerance type");
84 if (boost::iequals(type_string,
"ABSOLUTE_RESIDUAL")){
87 else if (boost::iequals(type_string,
"RELATIVE_RESIDUAL_CHANGE")){
90 else if (boost::iequals(type_string,
"ABSOLUTE_SOLUTION_CHANGE")){
92 std::cerr <<
"PRISMS-PF Error: Linear solver tolerance type " << type_string <<
" is not currently implemented, please use either ABSOLUTE_RESIDUAL or RELATIVE_RESIDUAL_CHANGE" << std::endl;
96 std::cerr <<
"PRISMS-PF Error: Linear solver tolerance type " << type_string <<
" is not one of the allowed values (ABSOLUTE_RESIDUAL, RELATIVE_RESIDUAL_CHANGE, ABSOLUTE_SOLUTION_CHANGE)" << std::endl;
101 double temp_value = parameter_handler.get_double(
"Tolerance value");
104 unsigned int temp_max_iterations = parameter_handler.get_integer(
"Maximum linear solver iterations");
106 linear_solver_parameters.loadParameters(i,temp_type,temp_value,temp_max_iterations);
108 parameter_handler.leave_subsection();
114 std::vector<bool> var_nonlinear = variable_attributes.
var_nonlinear;
116 nonlinear_solver_parameters.setMaxIterations(parameter_handler.get_integer(
"Maximum nonlinear solver iterations"));
118 for (
unsigned int i=0; i<var_nonlinear.size(); i++){
119 if (var_nonlinear.at(i)){
120 std::string subsection_text =
"Nonlinear solver parameters: ";
121 subsection_text.append(input_file_reader.
var_names.at(i));
123 parameter_handler.enter_subsection(subsection_text);
127 std::string type_string = parameter_handler.get(
"Tolerance type");
128 if (boost::iequals(type_string,
"ABSOLUTE_RESIDUAL")){
131 else if (boost::iequals(type_string,
"RELATIVE_RESIDUAL_CHANGE")){
134 else if (boost::iequals(type_string,
"ABSOLUTE_SOLUTION_CHANGE")){
138 std::cerr <<
"PRISMS-PF Error: Nonlinear solver tolerance type " << type_string <<
" is not one of the allowed values (ABSOLUTE_RESIDUAL, RELATIVE_RESIDUAL_CHANGE, ABSOLUTE_SOLUTION_CHANGE)" << std::endl;
143 double temp_value = parameter_handler.get_double(
"Tolerance value");
146 bool temp_backtrack_damping = parameter_handler.get_bool(
"Use backtracking line search damping");
149 double temp_step_modifier = parameter_handler.get_double(
"Backtracking step size modifier");
152 double temp_residual_decrease_coeff = parameter_handler.get_double(
"Backtracking residual decrease coefficient");
155 double temp_damping_coefficient = parameter_handler.get_double(
"Constant damping value");
158 bool temp_laplace_for_initial_guess;
160 temp_laplace_for_initial_guess = parameter_handler.get_bool(
"Use Laplace's equation to determine the initial guess");
163 temp_laplace_for_initial_guess =
false;
164 if (dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0){
165 std::cout <<
"PRISMS-PF Warning: Laplace's equation is only used to generate the initial guess for time independent equations. The equation for variable " << var_name[i] <<
" is not a time independent equation. No initial guess is needed for this equation." << std::endl;
169 nonlinear_solver_parameters.loadParameters(i,temp_type,temp_value,temp_backtrack_damping,temp_step_modifier,temp_residual_decrease_coeff,temp_damping_coefficient,temp_laplace_for_initial_guess);
171 parameter_handler.leave_subsection();
176 if (var_nonlinear.size() == 0){
177 nonlinear_solver_parameters.setMaxIterations(0);
181 std::string output_condition = parameter_handler.get(
"Output condition");
182 unsigned int num_outputs = parameter_handler.get_integer(
"Number of outputs");
183 std::vector<int> user_given_time_step_list_temp = dealii::Utilities::string_to_int(dealii::Utilities::split_string_list(parameter_handler.get(
"List of time steps to output")));
184 std::vector<unsigned int> user_given_time_step_list;
185 for (
unsigned int i=0; i<user_given_time_step_list_temp.size(); i++) user_given_time_step_list.push_back(user_given_time_step_list_temp[i]);
187 skip_print_steps = parameter_handler.get_integer(
"Skip print steps");
188 output_file_type = parameter_handler.get(
"Output file type");
189 output_file_name = parameter_handler.get(
"Output file name (base)");
191 output_vtu_per_process = parameter_handler.get_bool(
"Output separate files per process");
192 if ((output_file_type ==
"vtk") && (!output_vtu_per_process)){
193 output_vtu_per_process =
true;
194 if (dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0){
195 std::cout <<
"PRISMS-PF Warning: 'Output file type' given as 'vtk' and 'Output separate files per process' given as 'false'. Shared output files are not supported for the vtk output format. Separate files per process will be created." << std::endl;
202 bool only_time_independent_pdes =
true;
203 for (
unsigned int i=0; i<var_eq_type.size(); i++){
205 only_time_independent_pdes =
false;
211 if (only_time_independent_pdes){
216 if ((totalIncrements_temp >= 0) && (finalTime >= 0.0)) {
217 if (std::ceil(finalTime/dtValue) > totalIncrements_temp) {
218 totalIncrements = totalIncrements_temp;
219 finalTime = totalIncrements*dtValue;
222 totalIncrements = std::ceil(finalTime/dtValue);
225 else if ((totalIncrements_temp >= 0) && (finalTime < 0.0)) {
226 totalIncrements = totalIncrements_temp;
227 finalTime = totalIncrements*dtValue;
229 else if ((totalIncrements_temp < 0) && (finalTime >= 0.0)) {
230 totalIncrements = std::ceil(finalTime/dtValue);
234 std::cerr <<
"Invalid selections for the final time and the number of increments. At least one should be given in the input file and should be positive." << std::endl;
235 std::cout << finalTime <<
" " << totalIncrements_temp << std::endl;
242 outputTimeStepList = setTimeStepList(output_condition, num_outputs,user_given_time_step_list);
245 std::vector<std::string> load_ICs_temp = dealii::Utilities::split_string_list(parameter_handler.get(
"Load initial conditions"));
246 std::vector<std::string> load_parallel_file_temp = dealii::Utilities::split_string_list(parameter_handler.get(
"Load parallel file"));
248 if (boost::iequals(load_ICs_temp.at(0),
"void")){
249 for (
unsigned int var=0; var<number_of_variables; var++){
250 load_ICs.push_back(
false);
251 load_parallel_file.push_back(
false);
255 for (
unsigned int var=0; var<number_of_variables; var++){
256 if (boost::iequals(load_ICs_temp.at(var),
"true")){
257 load_ICs.push_back(
true);
260 load_ICs.push_back(
false);
262 if (boost::iequals(load_parallel_file_temp.at(var),
"true")){
263 load_parallel_file.push_back(
true);
266 load_parallel_file.push_back(
false);
271 load_file_name = dealii::Utilities::split_string_list(parameter_handler.get(
"File names"));
272 load_field_name = dealii::Utilities::split_string_list(parameter_handler.get(
"Variable names in the files"));
275 resume_from_checkpoint = parameter_handler.get_bool(
"Load from a checkpoint");
276 std::string checkpoint_condition = parameter_handler.get(
"Checkpoint condition");
277 unsigned int num_checkpoints = parameter_handler.get_integer(
"Number of checkpoints");
279 std::vector<int> user_given_checkpoint_time_step_list_temp = dealii::Utilities::string_to_int(dealii::Utilities::split_string_list(parameter_handler.get(
"List of time steps to save checkpoints")));
280 std::vector<unsigned int> user_given_checkpoint_time_step_list;
281 for (
unsigned int i=0; i<user_given_checkpoint_time_step_list_temp.size(); i++) user_given_checkpoint_time_step_list.push_back(user_given_checkpoint_time_step_list_temp[i]);
283 checkpointTimeStepList = setTimeStepList(checkpoint_condition, num_checkpoints,user_given_checkpoint_time_step_list);
287 for (
unsigned int i=0; i<input_file_reader.
var_types.size(); i++){
289 std::string nucleation_text =
"Nucleation parameters: ";
290 nucleation_text.append(input_file_reader.
var_names.at(i));
292 parameter_handler.enter_subsection(nucleation_text);
294 unsigned int var_index = i;
295 std::vector<double> semiaxes = dealii::Utilities::string_to_double(dealii::Utilities::split_string_list(parameter_handler.get(
"Nucleus semiaxes (x, y, z)")));
296 std::vector<double> ellipsoid_rotation = dealii::Utilities::string_to_double(dealii::Utilities::split_string_list(parameter_handler.get(
"Nucleus rotation in degrees (x, y, z)")));
297 std::vector<double> freeze_semiaxes = dealii::Utilities::string_to_double(dealii::Utilities::split_string_list(parameter_handler.get(
"Freeze zone semiaxes (x, y, z)")));
298 double hold_time = parameter_handler.get_double(
"Freeze time following nucleation");
299 double no_nucleation_border_thickness = parameter_handler.get_double(
"Nucleation-free border thickness");
301 nucleationParameters<dim> temp(var_index,semiaxes,freeze_semiaxes,ellipsoid_rotation,hold_time,no_nucleation_border_thickness);
302 nucleation_parameters_list.push_back(temp);
305 if (semiaxes.size() < dim || semiaxes.size() > 3){
306 std::cerr <<
"PRISMS-PF Error: The number of nucleus semiaxes given in the 'parameters.in' file must be at least the number of dimensions and no more than 3." << std::endl;
309 if (freeze_semiaxes.size() < dim || freeze_semiaxes.size() > 3){
310 std::cerr <<
"PRISMS-PF Error: The number of nucleation freeze zone semiaxes given in the 'parameters.in' file must be at least the number of dimensions and no more than 3." << std::endl;
313 if (ellipsoid_rotation.size() != 3){
314 std::cerr <<
"PRISMS-PF Error: Exactly three nucleus rotation angles must be given in the 'parameters.in' file." << std::endl;
318 parameter_handler.leave_subsection();
322 for (
unsigned int i=0; i<nucleation_parameters_list.size(); i++){
323 nucleation_parameters_list_index[nucleation_parameters_list.at(i).var_index] = i;
327 if (parameter_handler.get(
"Minimum allowed distance between nuclei") !=
"-1"){
328 min_distance_between_nuclei = parameter_handler.get_double(
"Minimum allowed distance between nuclei");
330 else if (nucleation_parameters_list.size() > 1) {
331 min_distance_between_nuclei = 2.0 * (*(max_element(nucleation_parameters_list[0].semiaxes.begin(),nucleation_parameters_list[0].semiaxes.end())));
333 nucleation_order_parameter_cutoff = parameter_handler.get_double(
"Order parameter cutoff value");
334 steps_between_nucleation_attempts = parameter_handler.get_integer(
"Time steps between nucleation attempts");
337 grain_remapping_activated = parameter_handler.get_bool(
"Activate grain reassignment");
339 skip_grain_reassignment_steps = parameter_handler.get_integer(
"Time steps between grain reassignments");
341 order_parameter_threshold = parameter_handler.get_double(
"Order parameter cutoff for grain identification");
343 buffer_between_grains = parameter_handler.get_double(
"Buffer between grains before reassignment");
344 if (buffer_between_grains < 0.0 && grain_remapping_activated ==
true){
345 std::cerr <<
"PRISMS-PF Error: If grain reassignment is activated, a non-negative buffer distance must be given. See the 'Buffer between grains before reassignment' entry in parameters.in." << std::endl;
349 std::vector<std::string> variables_for_remapping_str = dealii::Utilities::split_string_list(parameter_handler.get(
"Order parameter fields for grain reassignment"));
350 for (
unsigned int field=0; field<variables_for_remapping_str.size(); field++){
351 bool field_found =
false;
352 for (
unsigned int i=0; i<number_of_variables; i++ ){
353 if (boost::iequals(variables_for_remapping_str[field], variable_attributes.
var_name_list[i].second)){
354 variables_for_remapping.push_back(variable_attributes.
var_name_list[i].first);
359 if (field_found ==
false && grain_remapping_activated ==
true){
360 std::cerr <<
"PRISMS-PF Error: Entries in the list of order parameter fields used for grain reassignment must match the variable names in equations.h." << std::endl;
361 std::cerr << variables_for_remapping_str[field] << std::endl;
366 load_grain_structure = parameter_handler.get_bool(
"Load grain structure");
367 grain_structure_filename = parameter_handler.get(
"Grain structure filename");
368 grain_structure_variable_name = parameter_handler.get(
"Grain structure variable name");
369 num_grain_smoothing_cycles = parameter_handler.get_integer(
"Number of smoothing cycles after grain structure loading");
370 min_radius_for_loading_grains = parameter_handler.get_double(
"Minimum radius for loaded grains");
373 std::vector<std::string> list_of_BCs;
374 for (
unsigned int i=0; i<number_of_variables; i++){
375 if (var_type[i] ==
SCALAR){
376 std::string bc_text =
"Boundary condition for variable ";
377 bc_text.append(var_name.at(i));
378 list_of_BCs.push_back(parameter_handler.get(bc_text));
381 std::string bc_text =
"Boundary condition for variable ";
382 bc_text.append(var_name.at(i));
383 bc_text.append(
", x component");
384 list_of_BCs.push_back(parameter_handler.get(bc_text));
386 bc_text =
"Boundary condition for variable ";
387 bc_text.append(var_name.at(i));
388 bc_text.append(
", y component");
389 list_of_BCs.push_back(parameter_handler.get(bc_text));
391 bc_text =
"Boundary condition for variable ";
392 bc_text.append(var_name.at(i));
393 bc_text.append(
", z component");
394 list_of_BCs.push_back(parameter_handler.get(bc_text));
399 load_BC_list(list_of_BCs);
402 load_user_constants(input_file_reader,parameter_handler);
407 #include "../../include/userInputParameters_template_instantiations.h"
std::vector< std::pair< unsigned int, std::string > > var_name_list
std::vector< bool > var_nonlinear