libMesh
Loading...
Searching...
No Matches
Classes | Functions
calculator.C File Reference

Go to the source code of this file.

Classes

struct  Integrate
 

Functions

void usage_error (const char *progname)
 
template<typename T >
T assert_argument (const std::string &argname, const char *progname, const T &defaultarg)
 
int main (int argc, char **argv)
 

Function Documentation

◆ assert_argument()

template<typename T >
T assert_argument ( const std::string &  argname,
const char *  progname,
const T &  defaultarg 
)

Definition at line 91 of file calculator.C.

94{
95 if (!libMesh::on_command_line(argname))
96 {
97 libMesh::err << ("No " + argname + " argument found!") << std::endl;
98 usage_error(progname);
99 }
100 return libMesh::command_line_next(argname, defaultarg);
101}
void usage_error(const char *progname)
Definition calculator.C:61
OStreamProxy err
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line.
Definition libmesh.C:1025
bool on_command_line(std::string arg)
Definition libmesh.C:934

References libMesh::command_line_next(), libMesh::err, libMesh::on_command_line(), and usage_error().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 163 of file calculator.C.

164{
165 LibMeshInit init(argc, argv);
166
167 // In case the mesh file doesn't let us auto-infer dimension, we let
168 // the user specify it on the command line
169 const unsigned char requested_dim =
170 cast_int<unsigned char>(libMesh::command_line_next("--dim", 3));
171
172 // Load the old mesh from --inmesh filename.
173 // Keep it serialized; we don't want elements on the new mesh to be
174 // looking for data on old mesh elements that live off-processor.
175 Mesh old_mesh(init.comm(), requested_dim);
176
177 const std::string meshname =
178 assert_argument("--inmesh", argv[0], std::string(""));
179
180 libMesh::out << "Reading mesh " << meshname << std::endl;
181 old_mesh.read(meshname);
182
183 const std::string matname =
184 libMesh::command_line_next("--inmat", std::string(""));
185
186 if (matname != "")
187 {
188 libMesh::out << "Reading matrix " << matname << std::endl;
189
190 // For extraction matrices Coreform has been experimenting with
191 // PETSc solvers which take the transpose of what we expect, so
192 // we'll un-transpose here.
193 auto matrix = SparseMatrix<Number>::build (old_mesh.comm());
194 matrix->read(matname);
195 matrix->get_transpose(*matrix);
196
197 old_mesh.copy_constraint_rows(*matrix);
198 }
199
200 libMesh::out << "Mesh:" << std::endl;
201 old_mesh.print_info();
202
203 // If we're not using a distributed mesh, this is cheap info to add
204 if (old_mesh.is_serial_on_zero())
205 {
206 const Real mat_tol =
207 libMesh::command_line_next("--mattol", Real(0));
208
209 const dof_id_type n_components =
210 MeshTools::n_connected_components(old_mesh, mat_tol);
211 libMesh::out << "Mesh has " << n_components << " connected components." << std::endl;
212 }
213
214 const std::string solnname =
215 libMesh::command_line_next("--insoln", std::string(""));
216
217 // Load the old solution from --insoln filename, if that's been
218 // specified.
219 EquationSystems old_es(old_mesh);
220 std::string current_sys_name = "new_sys";
221
222 const std::string calcfunc =
223 assert_argument("--calc", argv[0], std::string(""));
224
225 const std::string family =
226 libMesh::command_line_next("--family", std::string("LAGRANGE"));
227
228 const unsigned int order = libMesh::command_line_next("--order", 1u);
229
230 std::unique_ptr<FEMFunctionBase<Number>> goal_function;
231
232 if (solnname != "")
233 {
234 libMesh::out << "Reading solution " << solnname << std::endl;
235
236 old_es.read(solnname,
241
242 libMesh::out << "Input system:\n\n";
243
244 old_es.print_info();
245
246 const unsigned int sysnum =
247 libMesh::command_line_next("--insys", 0);
248
249 libmesh_assert_less(sysnum, old_es.n_systems());
250
251 System & old_sys = old_es.get_system(sysnum);
252
253 current_sys_name = old_sys.name();
254
255 goal_function =
256 std::make_unique<ParsedFEMFunction<Number>>(old_sys, calcfunc);
257 }
258 else
259 {
260 current_sys_name = "bare_sys";
261
262 // FEMContext doesn't like seeing systems with no variables
263 System & dummy_sys = old_es.add_system<System>(current_sys_name);
264
265 // And if we're using an IsoGeometric Analysis mesh, we'd better
266 // make sure the user can specify order and family to make it
267 // iso.
268 dummy_sys.add_variable("dummy", static_cast<Order>(order),
269 Utility::string_to_enum<FEFamily>(family));
270
271 old_es.init();
272
273 goal_function =
274 std::make_unique<WrappedFunctor<Number>>(ParsedFunction<Number>(calcfunc));
275 }
276
277 libMesh::out << "Calculating with system " << current_sys_name << std::endl;
278
279 // Subdomains to integrate on
280 std::vector<libMesh::subdomain_id_type> subdomain_vec;
281 libMesh::command_line_vector("--subdomain", subdomain_vec);
282 std::set<libMesh::subdomain_id_type> subdomains_list(subdomain_vec.begin(),
283 subdomain_vec.end());
284
285 std::string default_outsolnname = "out_soln.xda";
286 if (solnname != "")
287 default_outsolnname = "out_"+solnname;
288 const std::string outsolnname =
289 libMesh::command_line_next("--outsoln", default_outsolnname);
290
291 // Output results in high precision
292 libMesh::out << std::setprecision(std::numeric_limits<Real>::max_digits10);
293
294 if (!libMesh::on_command_line("--integral"))
295 {
296 // Create a new mesh and a new EquationSystems.
297 // Copying the old mesh is faster than rereading it, and gets us
298 // any constraint rows from an input extraction operator matrix.
299 Mesh new_mesh(old_mesh);
300
301 EquationSystems new_es(new_mesh);
302
303 HilbertSystem & new_sys = new_es.add_system<HilbertSystem>(current_sys_name);
304
305 if (libMesh::on_command_line("--print_solutions"))
306 new_sys.print_solutions = true;
307
308 if (libMesh::on_command_line("--print_residuals"))
309 new_sys.print_residuals = true;
310
311 if (libMesh::on_command_line("--print_jacobians"))
312 new_sys.print_jacobians = true;
313
314 if (libMesh::on_command_line("--print_element_solutions"))
315 new_sys.print_element_solutions = true;
316
317 if (libMesh::on_command_line("--print_element_residuals"))
318 new_sys.print_element_residuals = true;
319
320 if (libMesh::on_command_line("--print_element_jacobians"))
321 new_sys.print_element_jacobians = true;
322
323 new_sys.hilbert_order() = libMesh::command_line_next("--hilbert", 0u);
324
325 new_sys.subdomains_list() = std::move(subdomains_list);
326
327 new_sys.time_solver =
328 std::make_unique<SteadySolver>(new_sys);
329
330 new_sys.fe_family() = family;
331 new_sys.fe_order() = order;
332
333 new_sys.set_goal_func(*goal_function);
334
335 const Real fdm_eps = libMesh::command_line_next("--fdm_eps", Real(TOLERANCE));
336
337 new_sys.set_fdm_eps(fdm_eps);
338
339 if (solnname != "")
340 new_sys.input_system = &old_es.get_system(current_sys_name);
341
342 new_es.init();
343
344 libMesh::out << "New system:\n\n";
345
346 new_es.print_info();
347
348 DiffSolver & solver = *(new_sys.time_solver->diff_solver().get());
349 solver.quiet = false;
350 solver.verbose = true;
351 solver.relative_step_tolerance = 1e-10;
352
353 new_sys.solve();
354
355 // Integrate the error if requested
356 if (libMesh::on_command_line("--error_q"))
357 {
358 const unsigned int error_q =
359 libMesh::command_line_next("--error_q", 0u);
360
361 // We just add "u" now but maybe we'll change that
362 for (auto v : make_range(new_sys.n_vars()))
363 {
364 ExactSolution exact_sol(new_es);
365 exact_sol.attach_exact_value(0, goal_function.get());
366 FDMGradient<Gradient> fdm_gradient(*goal_function, fdm_eps);
367 exact_sol.attach_exact_deriv(0, &fdm_gradient);
368 exact_sol.extra_quadrature_order(error_q);
369
370 const std::string var_name = new_sys.variable_name(v);
371 exact_sol.compute_error(current_sys_name, var_name);
372
373 libMesh::out << "L2 norm of " << var_name << ": " <<
374 new_sys.calculate_norm(*new_sys.solution, v, L2) <<
375 std::endl;
376
377 libMesh::out << "L2 error in " << var_name << ": " <<
378 exact_sol.l2_error(current_sys_name, var_name) <<
379 std::endl;
380
381 if (new_sys.hilbert_order() > 0)
382 {
383 libMesh::out << "H1 norm of " << var_name << ": " <<
384 new_sys.calculate_norm(*new_sys.solution, v, H1) <<
385 std::endl;
386
387 libMesh::out << "H1 error in " << var_name << ": " <<
388 exact_sol.h1_error(current_sys_name, var_name) <<
389 std::endl;
390 }
391 }
392 }
393
394 // Calculate the jump error indicator if requested
395 if (libMesh::on_command_line("--jump_error"))
396 {
397 const unsigned int jump_error_hilbert =
398 libMesh::command_line_next("--jump_error", 0u);
399
400 for (auto v : make_range(new_sys.n_vars()))
401 {
402 std::unique_ptr<JumpErrorEstimator> error_estimator;
403 SystemNorm error_norm;
404 error_norm.set_weight(0,0);
405 error_norm.set_weight(v+1,0);
406 error_norm.set_weight(v,1.0);
407
408 if (jump_error_hilbert == 0)
409 {
410 error_estimator = std::make_unique<DiscontinuityMeasure>();
411 error_norm.set_type(v, L2);
412 }
413 else if (jump_error_hilbert == 1)
414 {
415 error_estimator = std::make_unique<KellyErrorEstimator>();
416 error_norm.set_type(v, H1_SEMINORM);
417 }
418 else if (jump_error_hilbert == 2)
419 {
420 error_estimator = std::make_unique<LaplacianErrorEstimator>();
421 error_norm.set_type(v, H2_SEMINORM);
422 }
423 else
424 libmesh_not_implemented();
425
426 if (libMesh::on_command_line("--jump_slits"))
427 error_estimator->integrate_slits = true;
428
429 ErrorVector error_per_cell;
430 error_estimator->error_norm = error_norm;
431 error_estimator->estimate_error(new_sys, error_per_cell);
432
433 const std::string var_name = new_sys.variable_name(v);
434
435 // I really want to just stop supporting libstdc++-8.
436 // const Real total_error = std::reduce(error_per_cell.begin(), error_per_cell.end());
437
438 ErrorVectorReal total_error = 0;
439 for (auto cell_error : error_per_cell)
440 total_error += cell_error;
441
442 if (jump_error_hilbert == 0)
443 libMesh::out << "L2";
444 else
445 libMesh::out << "H" << jump_error_hilbert;
446
447 libMesh::out << " error estimate for " << var_name << ": " <<
448 total_error << std::endl;
449 }
450 }
451
452 // Write out the new solution file
453 new_es.write(outsolnname.c_str(),
456 libMesh::out << "Wrote solution " << outsolnname << std::endl;
457 }
458 else
459 {
460 // If we aren't doing a projection, then we just do an integral
461 System & old_sys = old_es.get_system<System>(current_sys_name);
462
463 ConstElemRange active_local_elem_range
464 (old_mesh.active_local_elements_begin(),
465 old_mesh.active_local_elements_end());
466
467 Integrate integrate(old_sys, *goal_function);
468
469 Threads::parallel_reduce (active_local_elem_range,
470 integrate);
471
472 Number integral = integrate.integral();
473 old_mesh.comm().sum(integral);
474 libMesh::out << "Integral is " << integral << std::endl;
475 }
476
477 return 0;
478}
unsigned int n_vars
T assert_argument(const std::string &argname, const char *progname, const T &defaultarg)
Definition calculator.C:91
std::set< libMesh::subdomain_id_type > & subdomains_list()
Definition L2system.h:51
libMesh::System * input_system
Definition L2system.h:71
void set_fdm_eps(libMesh::Real eps)
Definition L2system.h:54
void set_goal_func(libMesh::FEMFunctionBase< libMesh::Number > &goal)
Definition L2system.h:60
unsigned int & fe_order()
Definition L2system.h:50
std::string & fe_family()
Definition L2system.h:49
unsigned int & hilbert_order()
Definition L2system.h:53
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
Definition diff_solver.h:70
bool verbose
The DiffSolver may print a lot more to libMesh::out if verbose is set to true; default is false.
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled.
bool print_residuals
Set print_residuals to true to print F whenever it is assembled.
bool print_element_jacobians
Set print_element_jacobians to true to print each J_elem contribution.
bool print_solutions
Set print_solutions to true to print U whenever it is used in an assembly() call.
bool print_element_solutions
Set print_element_solutions to true to print each U_elem input.
bool print_element_residuals
Set print_element_residuals to true to print each R_elem contribution.
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
This is the EquationSystems class.
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
virtual void solve() override
Invokes the solver associated with the system.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
A Function generated (via FParser) by parsing a mathematical expression.
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
The StoredRange class defines a contiguous, divisible set of objects.
This class defines a norm/seminorm to be applied to a NumericVector which contains coefficients in a ...
Definition system_norm.h:50
void set_type(unsigned int var, const FEMNormType &t)
Sets the type of the norm in variable var, as well as for any unset variables with index less than va...
void set_weight(unsigned int var, Real w)
Sets the weight corresponding to the norm in variable var, as well as for any unset variables with in...
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition system.h:100
const std::string & name() const
Definition system.h:2385
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition system.C:1344
void init()
Initializes degrees of freedom on the current mesh.
Definition system.C:196
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
const std::string & variable_name(const unsigned int i) const
Definition system.C:2679
Real calculate_norm(const NumericVector< Number > &v, unsigned int var, FEMNormType norm_type, std::set< unsigned int > *skip_dimensions=nullptr) const
Definition system.C:1511
dof_id_type n_connected_components(const MeshBase &mesh, Real constraint_tol=0)
Definition mesh_tools.C:864
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided reduction operation in parallel on the specified range.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
void command_line_vector(const std::string &, std::vector< T > &)
Definition libmesh.C:1044
OStreamProxy out
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
std::string current_sys_name
Definition projection.C:77

References libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), assert_argument(), libMesh::ExactSolution::attach_exact_deriv(), libMesh::ExactSolution::attach_exact_value(), libMesh::SparseMatrix< T >::build(), libMesh::System::calculate_norm(), libMesh::ParallelObject::comm(), libMesh::command_line_next(), libMesh::command_line_vector(), libMesh::ExactSolution::compute_error(), libMesh::MeshBase::copy_constraint_rows(), current_sys_name, libMesh::ErrorVectorReal, libMesh::ExactSolution::extra_quadrature_order(), HilbertSystem::fe_family(), HilbertSystem::fe_order(), libMesh::EquationSystems::get_system(), libMesh::H1, libMesh::ExactSolution::h1_error(), libMesh::H1_SEMINORM, libMesh::H2_SEMINORM, HilbertSystem::hilbert_order(), libMesh::EquationSystems::init(), HilbertSystem::input_system, Integrate::integral(), libMesh::DistributedMesh::is_serial_on_zero(), libMesh::L2, libMesh::ExactSolution::l2_error(), main(), libMesh::make_range(), libMesh::MeshTools::n_connected_components(), libMesh::EquationSystems::n_systems(), libMesh::System::n_vars(), libMesh::System::name(), libMesh::on_command_line(), libMesh::out, libMesh::Threads::parallel_reduce(), libMesh::DifferentiableSystem::print_element_jacobians, libMesh::DifferentiableSystem::print_element_residuals, libMesh::DifferentiableSystem::print_element_solutions, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::DifferentiableSystem::print_jacobians, libMesh::DifferentiableSystem::print_residuals, libMesh::DifferentiableSystem::print_solutions, libMesh::DiffSolver::quiet, libMesh::UnstructuredMesh::read(), libMesh::EquationSystems::read(), libMesh::EquationSystems::READ_ADDITIONAL_DATA, libMesh::EquationSystems::READ_BASIC_ONLY, libMesh::EquationSystems::READ_DATA, libMesh::EquationSystems::READ_HEADER, libMesh::Real, libMesh::DiffSolver::relative_step_tolerance, HilbertSystem::set_fdm_eps(), HilbertSystem::set_goal_func(), libMesh::SystemNorm::set_type(), libMesh::SystemNorm::set_weight(), libMesh::System::solution, libMesh::FEMSystem::solve(), HilbertSystem::subdomains_list(), libMesh::Parallel::Communicator::sum(), libMesh::DifferentiableSystem::time_solver, libMesh::TOLERANCE, libMesh::System::variable_name(), libMesh::DiffSolver::verbose, libMesh::EquationSystems::write(), libMesh::EquationSystems::WRITE_ADDITIONAL_DATA, and libMesh::EquationSystems::WRITE_DATA.

◆ usage_error()

void usage_error ( const char *  progname)

Definition at line 61 of file calculator.C.

62{
63 libMesh::out << "Options: " << progname << '\n'
64 << " --dim d mesh dimension [default: autodetect]\n"
65 << " --inmesh filename input mesh file\n"
66 << " --inmat filename input constraint matrix [default: none]\n"
67 << " --mattol filename constraint tolerance when testing mesh connectivity\n"
68 << " [default: 0]\n"
69 << " --insoln filename input solution file\n"
70 << " --calc func function to calculate\n"
71 << " --insys sysnum input system number [default: 0]\n"
72 << " --outsoln filename output solution file [default: out_<insoln>]\n"
73 << " --family famname output FEM family [default: LAGRANGE]\n"
74 << " --order p output FEM order [default: 1]\n"
75 << " --subdomain \"sbd_ids\" each subdomain to check [default: all subdomains]\n"
76 << " --hilbert order Hilbert space to project in [default: 0 => H0]\n"
77 << " --fdm_eps eps Central diff for dfunc/dx [default: " << TOLERANCE << "]\n"
78 << " --error_q extra_q integrate projection error, with adjusted\n"
79 << " (extra) quadrature order [default: off, suggested: 0]\n"
80 << " --jump_error order calculate jump error indicator, for specified\n"
81 << " Hilbert order [default: off]\n"
82 << " --jump_slits calculate jumps across slits [default: off]\n"
83 << " --integral only calculate func integral, not projection\n"
84 << std::endl;
85
86 exit(1);
87}

References libMesh::out, and libMesh::TOLERANCE.

Referenced by assert_argument().