1
2 #include "femparameters.h"
3
4 #include "libmesh/parsed_function.h"
5 #include "libmesh/zero_function.h"
6 #include "libmesh/auto_ptr.h" // libmesh_make_unique
7
8 #include <unordered_set>
9
10 using namespace libMesh;
11
12 #define GETPOT_INPUT(A) { A = input(#A, A); \
13 variable_names.insert(#A); \
14 const std::string stringval = input(#A, std::string()); \
15 variable_assignments.push_back(std::string(#A "=") + stringval); }
16 #define GETPOT_INT_INPUT(A) { A = input(#A, (int)A); \
17 variable_names.insert(#A); \
18 const std::string stringval = input(#A, std::string()); \
19 variable_assignments.push_back(std::string(#A "=") + stringval); }
20
21 #define GETPOT_REGISTER(A) { \
22 variable_names.insert(#A); \
23 std::string stringval = input(#A, std::string()); \
24 variable_assignments.push_back(std::string(#A "=") + stringval); }
25
FEMParameters(const Parallel::Communicator & comm_in)26 FEMParameters::FEMParameters(const Parallel::Communicator & comm_in) :
27 ParallelObject(comm_in),
28 initial_timestep(0), n_timesteps(100),
29 transient(true),
30 deltat_reductions(0),
31 timesolver_core("euler"),
32 solution_history_type("memory"),
33 end_time(std::numeric_limits<Real>::max()),
34 deltat(0.0001), timesolver_theta(0.5),
35 timesolver_maxgrowth(0.), timesolver_tolerance(0.),
36 timesolver_upper_tolerance(0.),
37 steadystate_tolerance(0.),
38 timesolver_norm(0, L2),
39
40 dimension(2),
41 domaintype("square"), domainfile("mesh.xda"), elementtype("quad"),
42 elementorder(2),
43 domain_xmin(0.0), domain_ymin(0.0), domain_zmin(0.0),
44 domain_edge_width(1.0), domain_edge_length(1.0), domain_edge_height(1.0),
45 coarsegridx(1), coarsegridy(1), coarsegridz(1),
46 coarserefinements(0), extrarefinements(0),
47 mesh_redistribute_func("0"),
48
49 mesh_partitioner_type("Default"),
50
51 nelem_target(8000), global_tolerance(0.0),
52 refine_fraction(0.3), coarsen_fraction(0.3), coarsen_threshold(10),
53 max_adaptivesteps(1),
54 initial_adaptivesteps(0),
55
56 write_interval(10),
57 write_gmv_error(false), write_tecplot_error(false),
58 write_exodus_error(false),
59 output_xda(false), output_xdr(false),
60 output_bz2(true), output_gz(true),
61 output_gmv(false), output_tecplot(false),
62 output_exodus(false), output_nemesis(false),
63
64 system_types(0),
65
66 #ifdef LIBMESH_ENABLE_PERIODIC
67 periodic_boundaries(0),
68 #endif
69
70 run_simulation(true), run_postprocess(false),
71
72 fe_family(1, "LAGRANGE"), fe_order(1, 1),
73 extra_quadrature_order(0),
74
75 analytic_jacobians(true), verify_analytic_jacobians(0.0),
76 numerical_jacobian_h(TOLERANCE),
77 print_solution_norms(false), print_solutions(false),
78 print_residual_norms(false), print_residuals(false),
79 print_jacobian_norms(false), print_jacobians(false),
80 print_element_solutions(false),
81 print_element_residuals(false),
82 print_element_jacobians(false),
83
84 use_petsc_snes(false),
85 time_solver_quiet(true), solver_quiet(true), solver_verbose(false),
86 reuse_preconditioner(true),
87 require_residual_reduction(true),
88 min_step_length(1e-5),
89 max_linear_iterations(200000), max_nonlinear_iterations(20),
90 relative_step_tolerance(1.e-7), relative_residual_tolerance(1.e-10),
91 absolute_residual_tolerance(1.e-10),
92 initial_linear_tolerance(1.e-3), minimum_linear_tolerance(TOLERANCE*TOLERANCE),
93 linear_tolerance_multiplier(1.e-3),
94
95 initial_sobolev_order(1),
96 initial_extra_quadrature(0),
97 refine_uniformly(false),
98 indicator_type("kelly"), patch_reuse(true), sobolev_order(1)
99 {
100 }
101
~FEMParameters()102 FEMParameters::~FEMParameters()
103 {
104 for (std::map<subdomain_id_type, FunctionBase<Number> *>::iterator
105 i = initial_conditions.begin(); i != initial_conditions.end();
106 ++i)
107 delete i->second;
108
109 for (std::map<boundary_id_type, FunctionBase<Number> *>::iterator
110 i = dirichlet_conditions.begin(); i != dirichlet_conditions.end();
111 ++i)
112 delete i->second;
113
114 for (std::map<boundary_id_type, FunctionBase<Number> *>::iterator
115 i = neumann_conditions.begin(); i != neumann_conditions.end();
116 ++i)
117 delete i->second;
118
119 for (std::map<int,
120 std::map<boundary_id_type, FunctionBase<Number> *>
121 >::iterator
122 i = other_boundary_functions.begin(); i != other_boundary_functions.end();
123 ++i)
124 for (std::map<boundary_id_type, FunctionBase<Number> *>::iterator
125 j = i->second.begin(); j != i->second.end();
126 ++j)
127 delete j->second;
128
129 for (std::map<int,
130 std::map<subdomain_id_type, FunctionBase<Number> *>
131 >::iterator
132 i = other_interior_functions.begin(); i != other_interior_functions.end();
133 ++i)
134 for (std::map<subdomain_id_type, FunctionBase<Number> *>::iterator
135 j = i->second.begin(); j != i->second.end();
136 ++j)
137 delete j->second;
138 }
139
140
new_function_base(const std::string & func_type,const std::string & func_value)141 std::unique_ptr<FunctionBase<Number>> new_function_base(const std::string & func_type,
142 const std::string & func_value)
143 {
144 if (func_type == "parsed")
145 return libmesh_make_unique<ParsedFunction<Number>>(func_value);
146 else if (func_type == "zero")
147 return libmesh_make_unique<ZeroFunction<Number>>();
148 else
149 libmesh_not_implemented();
150
151 return std::unique_ptr<FunctionBase<Number>>();
152 }
153
154
read(GetPot & input,const std::vector<std::string> * other_variable_names)155 void FEMParameters::read(GetPot & input,
156 const std::vector<std::string> * other_variable_names)
157 {
158 std::vector<std::string> variable_assignments;
159 std::unordered_set<std::string> variable_names;
160 if (other_variable_names)
161 for (std::size_t i=0; i != other_variable_names->size(); ++i)
162 {
163 const std::string & name = (*other_variable_names)[i];
164 const std::string stringval = input(name, std::string());
165 variable_assignments.push_back(name + "=" + stringval);
166 }
167
168 GETPOT_INT_INPUT(initial_timestep);
169 GETPOT_INT_INPUT(n_timesteps);
170 GETPOT_INPUT(transient);
171 GETPOT_INT_INPUT(deltat_reductions);
172 GETPOT_INPUT(timesolver_core);
173 GETPOT_INPUT(solution_history_type);
174 GETPOT_INPUT(end_time);
175 GETPOT_INPUT(deltat);
176 GETPOT_INPUT(timesolver_theta);
177 GETPOT_INPUT(timesolver_maxgrowth);
178 GETPOT_INPUT(timesolver_tolerance);
179 GETPOT_INPUT(timesolver_upper_tolerance);
180 GETPOT_INPUT(steadystate_tolerance);
181
182 GETPOT_REGISTER(timesolver_norm);
183 const unsigned int n_timesolver_norm = input.vector_variable_size("timesolver_norm");
184 timesolver_norm.resize(n_timesolver_norm, L2);
185 for (unsigned int i=0; i != n_timesolver_norm; ++i)
186 {
187 int current_norm = 0; // L2
188 if (timesolver_norm[i] == H1)
189 current_norm = 1;
190 if (timesolver_norm[i] == H2)
191 current_norm = 2;
192 current_norm = input("timesolver_norm", current_norm, i);
193 if (current_norm == 0)
194 timesolver_norm[i] = L2;
195 else if (current_norm == 1)
196 timesolver_norm[i] = H1;
197 else if (current_norm == 2)
198 timesolver_norm[i] = H2;
199 else
200 timesolver_norm[i] = DISCRETE_L2;
201 }
202
203
204 GETPOT_INT_INPUT(dimension);
205 GETPOT_INPUT(domaintype);
206 GETPOT_INPUT(domainfile);
207 GETPOT_INPUT(elementtype);
208 GETPOT_INPUT(elementorder);
209 GETPOT_INPUT(domain_xmin);
210 GETPOT_INPUT(domain_ymin);
211 GETPOT_INPUT(domain_zmin);
212 GETPOT_INPUT(domain_edge_width);
213 GETPOT_INPUT(domain_edge_length);
214 GETPOT_INPUT(domain_edge_height);
215 GETPOT_INT_INPUT(coarsegridx);
216 GETPOT_INT_INPUT(coarsegridy);
217 GETPOT_INT_INPUT(coarsegridz);
218 GETPOT_INT_INPUT(coarserefinements);
219 GETPOT_INT_INPUT(extrarefinements);
220 GETPOT_INPUT(mesh_redistribute_func);
221
222
223 GETPOT_INPUT(mesh_partitioner_type);
224
225
226 GETPOT_INT_INPUT(nelem_target);
227 GETPOT_INPUT(global_tolerance);
228 GETPOT_INPUT(refine_fraction);
229 GETPOT_INPUT(coarsen_fraction);
230 GETPOT_INPUT(coarsen_threshold);
231 GETPOT_INT_INPUT(max_adaptivesteps);
232 GETPOT_INT_INPUT(initial_adaptivesteps);
233
234
235 GETPOT_INT_INPUT(write_interval);
236 GETPOT_INPUT(output_xda);
237 GETPOT_INPUT(output_xdr);
238 GETPOT_INPUT(output_gz);
239 #ifndef LIBMESH_HAVE_GZSTREAM
240 output_gz = false;
241 #endif
242 GETPOT_INPUT(output_bz2);
243 #ifndef LIBMESH_HAVE_BZ2
244 output_bz2 = false;
245 #endif
246 GETPOT_INPUT(output_gmv);
247 GETPOT_INPUT(write_gmv_error);
248 #ifndef LIBMESH_HAVE_GMV
249 output_gmv = false;
250 write_gmv_error = false;
251 #endif
252 GETPOT_INPUT(output_tecplot);
253 GETPOT_INPUT(write_tecplot_error);
254 #ifndef LIBMESH_HAVE_TECPLOT_API
255 output_tecplot = false;
256 write_tecplot_error = false;
257 #endif
258 GETPOT_INPUT(output_exodus);
259 GETPOT_INPUT(write_exodus_error);
260 #ifndef LIBMESH_HAVE_EXODUS_API
261 output_exodus = false;
262 write_exodus_error = false;
263 #endif
264 GETPOT_INPUT(output_nemesis);
265 #ifndef LIBMESH_HAVE_NEMESIS_API
266 output_nemesis = false;
267 #endif
268
269
270 GETPOT_REGISTER(system_types);
271 const unsigned int n_system_types =
272 input.vector_variable_size("system_types");
273 if (n_system_types)
274 {
275 system_types.resize(n_system_types, "");
276 for (unsigned int i=0; i != n_system_types; ++i)
277 {
278 system_types[i] = input("system_types", system_types[i], i);
279 }
280 }
281
282
283 #ifdef LIBMESH_ENABLE_PERIODIC
284 GETPOT_REGISTER(periodic_boundaries);
285 const unsigned int n_periodic_bcs =
286 input.vector_variable_size("periodic_boundaries");
287
288 if (n_periodic_bcs)
289 {
290 if (domaintype != "square" &&
291 domaintype != "cylinder" &&
292 domaintype != "file" &&
293 domaintype != "od2")
294 {
295 libMesh::out << "Periodic boundaries need rectilinear domains" << std::endl;;
296 libmesh_error();
297 }
298 for (unsigned int i=0; i != n_periodic_bcs; ++i)
299 {
300 const unsigned int myboundary =
301 input("periodic_boundaries", -1, i);
302 boundary_id_type pairedboundary = 0;
303 RealVectorValue translation_vector;
304 if (dimension == 2)
305 switch (myboundary)
306 {
307 case 0:
308 pairedboundary = 2;
309 translation_vector = RealVectorValue(0., domain_edge_length);
310 break;
311 case 1:
312 pairedboundary = 3;
313 translation_vector = RealVectorValue(-domain_edge_width, 0);
314 break;
315 default:
316 libMesh::out << "Unrecognized periodic boundary id " <<
317 myboundary << std::endl;;
318 libmesh_error();
319 }
320 else if (dimension == 3)
321 switch (myboundary)
322 {
323 case 0:
324 pairedboundary = 5;
325 translation_vector = RealVectorValue(Real(0), Real(0), domain_edge_height);
326 break;
327 case 1:
328 pairedboundary = 3;
329 translation_vector = RealVectorValue(Real(0), domain_edge_length, Real(0));
330 break;
331 case 2:
332 pairedboundary = 4;
333 translation_vector = RealVectorValue(-domain_edge_width, Real(0), Real(0));
334 break;
335 default:
336 libMesh::out << "Unrecognized periodic boundary id " <<
337 myboundary << std::endl;;
338 libmesh_error();
339 }
340 periodic_boundaries.push_back(PeriodicBoundary(translation_vector));
341 periodic_boundaries[i].myboundary = cast_int<boundary_id_type>(myboundary);
342 periodic_boundaries[i].pairedboundary = pairedboundary;
343 }
344 }
345 #endif // LIBMESH_ENABLE_PERIODIC
346
347 // Use std::string inputs so GetPot doesn't have to make a bunch
348 // of internal C string copies
349 std::string zero_string = "zero";
350 std::string empty_string = "";
351
352 GETPOT_REGISTER(dirichlet_condition_types);
353 GETPOT_REGISTER(dirichlet_condition_values);
354 GETPOT_REGISTER(dirichlet_condition_boundaries);
355 GETPOT_REGISTER(dirichlet_condition_variables);
356
357 const unsigned int n_dirichlet_conditions=
358 input.vector_variable_size("dirichlet_condition_types");
359
360 if (n_dirichlet_conditions !=
361 input.vector_variable_size("dirichlet_condition_values"))
362 {
363 libMesh::out << "Error: " << n_dirichlet_conditions
364 << " Dirichlet condition types does not match "
365 << input.vector_variable_size("dirichlet_condition_values")
366 << " Dirichlet condition values." << std::endl;
367
368 libmesh_error();
369 }
370
371 if (n_dirichlet_conditions !=
372 input.vector_variable_size("dirichlet_condition_boundaries"))
373 {
374 libMesh::out << "Error: " << n_dirichlet_conditions
375 << " Dirichlet condition types does not match "
376 << input.vector_variable_size("dirichlet_condition_boundaries")
377 << " Dirichlet condition boundaries." << std::endl;
378
379 libmesh_error();
380 }
381
382 if (n_dirichlet_conditions !=
383 input.vector_variable_size("dirichlet_condition_variables"))
384 {
385 libMesh::out << "Error: " << n_dirichlet_conditions
386 << " Dirichlet condition types does not match "
387 << input.vector_variable_size("dirichlet_condition_variables")
388 << " Dirichlet condition variables sets." << std::endl;
389
390 libmesh_error();
391 }
392
393 for (unsigned int dc=0; dc != n_dirichlet_conditions; ++dc)
394 {
395 const std::string func_type =
396 input("dirichlet_condition_types", zero_string, dc);
397
398 const std::string func_value =
399 input("dirichlet_condition_values", empty_string, dc);
400
401 const boundary_id_type func_boundary =
402 input("dirichlet_condition_boundaries", boundary_id_type(0), dc);
403
404 dirichlet_conditions[func_boundary] =
405 (new_function_base(func_type, func_value).release());
406
407 const std::string variable_set =
408 input("dirichlet_condition_variables", empty_string, dc);
409
410 for (unsigned int i=0; i != variable_set.size(); ++i)
411 {
412 if (variable_set[i] == '1')
413 dirichlet_condition_variables[func_boundary].push_back(i);
414 else if (variable_set[i] != '0')
415 {
416 libMesh::out << "Unable to understand Dirichlet variable set"
417 << variable_set << std::endl;
418 libmesh_error();
419 }
420 }
421 }
422
423 GETPOT_REGISTER(neumann_condition_types);
424 GETPOT_REGISTER(neumann_condition_values);
425 GETPOT_REGISTER(neumann_condition_boundaries);
426 GETPOT_REGISTER(neumann_condition_variables);
427
428 const unsigned int n_neumann_conditions=
429 input.vector_variable_size("neumann_condition_types");
430
431 if (n_neumann_conditions !=
432 input.vector_variable_size("neumann_condition_values"))
433 {
434 libMesh::out << "Error: " << n_neumann_conditions
435 << " Neumann condition types does not match "
436 << input.vector_variable_size("neumann_condition_values")
437 << " Neumann condition values." << std::endl;
438
439 libmesh_error();
440 }
441
442 if (n_neumann_conditions !=
443 input.vector_variable_size("neumann_condition_boundaries"))
444 {
445 libMesh::out << "Error: " << n_neumann_conditions
446 << " Neumann condition types does not match "
447 << input.vector_variable_size("neumann_condition_boundaries")
448 << " Neumann condition boundaries." << std::endl;
449
450 libmesh_error();
451 }
452
453 if (n_neumann_conditions !=
454 input.vector_variable_size("neumann_condition_variables"))
455 {
456 libMesh::out << "Error: " << n_neumann_conditions
457 << " Neumann condition types does not match "
458 << input.vector_variable_size("neumann_condition_variables")
459 << " Neumann condition variables sets." << std::endl;
460
461 libmesh_error();
462 }
463
464 for (unsigned int nc=0; nc != n_neumann_conditions; ++nc)
465 {
466 const std::string func_type =
467 input("neumann_condition_types", zero_string, nc);
468
469 const std::string func_value =
470 input("neumann_condition_values", empty_string, nc);
471
472 const boundary_id_type func_boundary =
473 input("neumann_condition_boundaries", boundary_id_type(0), nc);
474
475 neumann_conditions[func_boundary] =
476 (new_function_base(func_type, func_value).release());
477
478 const std::string variable_set =
479 input("neumann_condition_variables", empty_string, nc);
480
481 for (unsigned int i=0; i != variable_set.size(); ++i)
482 {
483 if (variable_set[i] == '1')
484 neumann_condition_variables[func_boundary].push_back(i);
485 else if (variable_set[i] != '0')
486 {
487 libMesh::out << "Unable to understand Neumann variable set"
488 << variable_set << std::endl;
489 libmesh_error();
490 }
491 }
492 }
493
494 GETPOT_REGISTER(initial_condition_types);
495 GETPOT_REGISTER(initial_condition_values);
496 GETPOT_REGISTER(initial_condition_subdomains);
497
498 const unsigned int n_initial_conditions=
499 input.vector_variable_size("initial_condition_types");
500
501 if (n_initial_conditions !=
502 input.vector_variable_size("initial_condition_values"))
503 {
504 libMesh::out << "Error: " << n_initial_conditions
505 << " initial condition types does not match "
506 << input.vector_variable_size("initial_condition_values")
507 << " initial condition values." << std::endl;
508
509 libmesh_error();
510 }
511
512 if (n_initial_conditions !=
513 input.vector_variable_size("initial_condition_subdomains"))
514 {
515 libMesh::out << "Error: " << n_initial_conditions
516 << " initial condition types does not match "
517 << input.vector_variable_size("initial_condition_subdomains")
518 << " initial condition subdomains." << std::endl;
519
520 libmesh_error();
521 }
522
523 for (unsigned int i=0; i != n_initial_conditions; ++i)
524 {
525 const std::string func_type =
526 input("initial_condition_types", zero_string, i);
527
528 const std::string func_value =
529 input("initial_condition_values", empty_string, i);
530
531 const subdomain_id_type func_subdomain =
532 input("initial_condition_subdomains", subdomain_id_type(0), i);
533
534 initial_conditions[func_subdomain] =
535 (new_function_base(func_type, func_value).release());
536 }
537
538 GETPOT_REGISTER(other_interior_function_types);
539 GETPOT_REGISTER(other_interior_function_values);
540 GETPOT_REGISTER(other_interior_function_subdomains);
541 GETPOT_REGISTER(other_interior_function_ids);
542
543 const unsigned int n_other_interior_functions =
544 input.vector_variable_size("other_interior_function_types");
545
546 if (n_other_interior_functions !=
547 input.vector_variable_size("other_interior_function_values"))
548 {
549 libMesh::out << "Error: " << n_other_interior_functions
550 << " other interior function types does not match "
551 << input.vector_variable_size("other_interior_function_values")
552 << " other interior function values." << std::endl;
553
554 libmesh_error();
555 }
556
557 if (n_other_interior_functions !=
558 input.vector_variable_size("other_interior_function_subdomains"))
559 {
560 libMesh::out << "Error: " << n_other_interior_functions
561 << " other interior function types does not match "
562 << input.vector_variable_size("other_interior_function_subdomains")
563 << " other interior function subdomains." << std::endl;
564
565 libmesh_error();
566 }
567
568 if (n_other_interior_functions !=
569 input.vector_variable_size("other_interior_function_ids"))
570 {
571 libMesh::out << "Error: " << n_other_interior_functions
572 << " other interior function types does not match "
573 << input.vector_variable_size("other_interior_function_ids")
574 << " other interior function ids." << std::endl;
575
576 libmesh_error();
577 }
578
579 for (unsigned int i=0; i != n_other_interior_functions; ++i)
580 {
581 const std::string func_type =
582 input("other_interior_function_types", zero_string, i);
583
584 const std::string func_value =
585 input("other_interior_function_values", empty_string, i);
586
587 const subdomain_id_type func_subdomain =
588 input("other_interior_condition_subdomains", subdomain_id_type(0), i);
589
590 const int func_id =
591 input("other_interior_condition_ids", int(0), i);
592
593 other_interior_functions[func_id][func_subdomain] =
594 (new_function_base(func_type, func_value).release());
595 }
596
597 GETPOT_REGISTER(other_boundary_function_types);
598 GETPOT_REGISTER(other_boundary_function_values);
599 GETPOT_REGISTER(other_boundary_function_boundaries);
600 GETPOT_REGISTER(other_boundary_function_ids);
601
602 const unsigned int n_other_boundary_functions =
603 input.vector_variable_size("other_boundary_function_types");
604
605 if (n_other_boundary_functions !=
606 input.vector_variable_size("other_boundary_function_values"))
607 {
608 libMesh::out << "Error: " << n_other_boundary_functions
609 << " other boundary function types does not match "
610 << input.vector_variable_size("other_boundary_function_values")
611 << " other boundary function values." << std::endl;
612
613 libmesh_error();
614 }
615
616 if (n_other_boundary_functions !=
617 input.vector_variable_size("other_boundary_function_boundaries"))
618 {
619 libMesh::out << "Error: " << n_other_boundary_functions
620 << " other boundary function types does not match "
621 << input.vector_variable_size("other_boundary_function_boundaries")
622 << " other boundary function boundaries." << std::endl;
623
624 libmesh_error();
625 }
626
627 if (n_other_boundary_functions !=
628 input.vector_variable_size("other_boundary_function_ids"))
629 {
630 libMesh::out << "Error: " << n_other_boundary_functions
631 << " other boundary function types does not match "
632 << input.vector_variable_size("other_boundary_function_ids")
633 << " other boundary function ids." << std::endl;
634
635 libmesh_error();
636 }
637
638 for (unsigned int i=0; i != n_other_boundary_functions; ++i)
639 {
640 const std::string func_type =
641 input("other_boundary_function_types", zero_string, i);
642
643 const std::string func_value =
644 input("other_boundary_function_values", empty_string, i);
645
646 const boundary_id_type func_boundary =
647 input("other_boundary_function_boundaries", boundary_id_type(0), i);
648
649 const int func_id =
650 input("other_boundary_function_ids", int(0), i);
651
652 other_boundary_functions[func_id][func_boundary] =
653 (new_function_base(func_type, func_value).release());
654 }
655
656 GETPOT_INPUT(run_simulation);
657 GETPOT_INPUT(run_postprocess);
658
659
660 GETPOT_REGISTER(fe_family);
661 const unsigned int n_fe_family =
662 std::max(1u, input.vector_variable_size("fe_family"));
663 fe_family.resize(n_fe_family, "LAGRANGE");
664 for (unsigned int i=0; i != n_fe_family; ++i)
665 fe_family[i] = input("fe_family", fe_family[i].c_str(), i);
666 GETPOT_REGISTER(fe_order);
667 const unsigned int n_fe_order =
668 input.vector_variable_size("fe_order");
669 fe_order.resize(n_fe_order, 1);
670 for (unsigned int i=0; i != n_fe_order; ++i)
671 fe_order[i] = input("fe_order", (int)fe_order[i], i);
672 GETPOT_INPUT(extra_quadrature_order);
673
674
675 GETPOT_INPUT(analytic_jacobians);
676 GETPOT_INPUT(verify_analytic_jacobians);
677 GETPOT_INPUT(numerical_jacobian_h);
678 GETPOT_INPUT(print_solution_norms);
679 GETPOT_INPUT(print_solutions);
680 GETPOT_INPUT(print_residual_norms);
681 GETPOT_INPUT(print_residuals);
682 GETPOT_INPUT(print_jacobian_norms);
683 GETPOT_INPUT(print_jacobians);
684 GETPOT_INPUT(print_element_solutions);
685 GETPOT_INPUT(print_element_residuals);
686 GETPOT_INPUT(print_element_jacobians);
687
688
689 GETPOT_INPUT(use_petsc_snes);
690 GETPOT_INPUT(time_solver_quiet);
691 GETPOT_INPUT(solver_quiet);
692 GETPOT_INPUT(solver_verbose);
693 GETPOT_INPUT(reuse_preconditioner);
694 GETPOT_INPUT(require_residual_reduction);
695 GETPOT_INPUT(min_step_length);
696 GETPOT_INT_INPUT(max_linear_iterations);
697 GETPOT_INT_INPUT(max_nonlinear_iterations);
698 GETPOT_INPUT(relative_step_tolerance);
699 GETPOT_INPUT(relative_residual_tolerance);
700 GETPOT_INPUT(absolute_residual_tolerance);
701 GETPOT_INPUT(initial_linear_tolerance);
702 GETPOT_INPUT(minimum_linear_tolerance);
703 GETPOT_INPUT(linear_tolerance_multiplier);
704
705
706 GETPOT_INT_INPUT(initial_sobolev_order);
707 GETPOT_INT_INPUT(initial_extra_quadrature);
708 GETPOT_INPUT(refine_uniformly);
709 GETPOT_INPUT(indicator_type);
710 GETPOT_INPUT(patch_reuse);
711 GETPOT_INT_INPUT(sobolev_order);
712
713 GETPOT_INPUT(system_config_file);
714
715 std::vector<std::string> bad_variables =
716 input.unidentified_arguments(variable_assignments);
717
718 // The way unidentified_arguments() works can give us false
719 // positives from repeated (overridden) variable assignments or from
720 // other (e.g. PETSc) command line arguments.
721 std::vector<std::string> actually_bad_variables;
722 for (std::size_t i = 0; i < bad_variables.size(); ++i)
723 {
724 // If any of our ufo arguments start with a -, that's a false
725 // positive from an unrelated command line argument.
726 if (bad_variables[i].empty() || bad_variables[i][0] != '-')
727 {
728 std::string bad_variable_name =
729 bad_variables[i].substr(0, bad_variables[i].find('='));
730 if (!variable_names.count(bad_variable_name))
731 actually_bad_variables.push_back(bad_variables[i]);
732 }
733 // Skip any option variable and (to be safe from false
734 // positives, though it can create false negatives) any
735 // subsequent potential argument
736 else
737 if (bad_variables.size() > (i+1) &&
738 !bad_variables[i+1].empty() &&
739 bad_variables[i+1][0] != '-')
740 ++i;
741 }
742
743 if (this->comm().rank() == 0 && !actually_bad_variables.empty())
744 {
745 libMesh::err << "ERROR: Unrecognized variables:" << std::endl;
746 for (auto var : actually_bad_variables)
747 libMesh::err << var << std::endl;
748 libMesh::err << "Not found among recognized variables:" << std::endl;
749 for (std::size_t i = 0; i != variable_names.size(); ++i)
750 libMesh::err << variable_assignments[i] << std::endl;
751 libmesh_error();
752 }
753 }
754