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 >
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 old_es.print_info();
243
244 const unsigned int sysnum =
245 libMesh::command_line_next("--insys", 0);
246
247 libmesh_assert_less(sysnum, old_es.n_systems());
248
249 System & old_sys = old_es.get_system(sysnum);
250
251 current_sys_name = old_sys.name();
252
253 goal_function =
254 std::make_unique<ParsedFEMFunction<Number>>(old_sys, calcfunc);
255 }
256 else
257 {
258 current_sys_name = "bare_sys";
259
260 // FEMContext doesn't like seeing systems with no variables
261 System & dummy_sys = old_es.add_system<System>(current_sys_name);
262
263 // And if we're using an IsoGeometric Analysis mesh, we'd better
264 // make sure the user can specify order and family to make it
265 // iso.
266 dummy_sys.add_variable("dummy", static_cast<Order>(order),
267 Utility::string_to_enum<FEFamily>(family));
268
269 old_es.init();
270
271 old_es.print_info();
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 Mesh new_mesh(init.comm(), requested_dim);
298 new_mesh.read(meshname);
299
300 EquationSystems new_es(new_mesh);
301
302 HilbertSystem & new_sys = new_es.add_system<HilbertSystem>(current_sys_name);
303
304 new_sys.hilbert_order() = libMesh::command_line_next("--hilbert", 0u);
305
306 new_sys.subdomains_list() = std::move(subdomains_list);
307
308 new_sys.time_solver =
309 std::make_unique<SteadySolver>(new_sys);
310
311 new_sys.fe_family() = family;
312 new_sys.fe_order() = order;
313
314 new_sys.set_goal_func(*goal_function);
315
316 const Real fdm_eps = libMesh::command_line_next("--fdm_eps", Real(TOLERANCE));
317
318 new_sys.set_fdm_eps(fdm_eps);
319
320 if (solnname != "")
321 new_sys.input_system = &old_es.get_system(current_sys_name);
322
323 new_es.init();
324
325 DiffSolver & solver = *(new_sys.time_solver->diff_solver().get());
326 solver.quiet = false;
327 solver.verbose = true;
328 solver.relative_step_tolerance = 1e-10;
329
330 new_sys.solve();
331
332 // Integrate the error if requested
333 if (libMesh::on_command_line("--error_q"))
334 {
335 const unsigned int error_q =
336 libMesh::command_line_next("--error_q", 0u);
337
338 // We just add "u" now but maybe we'll change that
339 for (auto v : make_range(new_sys.n_vars()))
340 {
341 ExactSolution exact_sol(new_es);
342 exact_sol.attach_exact_value(0, goal_function.get());
343 FDMGradient<Gradient> fdm_gradient(*goal_function, fdm_eps);
344 exact_sol.attach_exact_deriv(0, &fdm_gradient);
345 exact_sol.extra_quadrature_order(error_q);
346
347 const std::string var_name = new_sys.variable_name(v);
348 exact_sol.compute_error(current_sys_name, var_name);
349
350 libMesh::out << "L2 norm of " << var_name << ": " <<
351 new_sys.calculate_norm(*new_sys.solution, v, L2) <<
352 std::endl;
353
354 libMesh::out << "L2 error in " << var_name << ": " <<
355 exact_sol.l2_error(current_sys_name, var_name) <<
356 std::endl;
357
358 if (new_sys.hilbert_order() > 0)
359 {
360 libMesh::out << "H1 norm of " << var_name << ": " <<
361 new_sys.calculate_norm(*new_sys.solution, v, H1) <<
362 std::endl;
363
364 libMesh::out << "H1 error in " << var_name << ": " <<
365 exact_sol.h1_error(current_sys_name, var_name) <<
366 std::endl;
367 }
368 }
369 }
370
371 // Calculate the jump error indicator if requested
372 if (libMesh::on_command_line("--jump_error"))
373 {
374 const unsigned int jump_error_hilbert =
375 libMesh::command_line_next("--jump_error", 0u);
376
377 for (auto v : make_range(new_sys.n_vars()))
378 {
379 std::unique_ptr<JumpErrorEstimator> error_estimator;
380 SystemNorm error_norm;
381 error_norm.set_weight(0,0);
382 error_norm.set_weight(v+1,0);
383 error_norm.set_weight(v,1.0);
384
385 if (jump_error_hilbert == 0)
386 {
387 error_estimator = std::make_unique<DiscontinuityMeasure>();
388 error_norm.set_type(v, L2);
389 }
390 else if (jump_error_hilbert == 1)
391 {
392 error_estimator = std::make_unique<KellyErrorEstimator>();
393 error_norm.set_type(v, H1_SEMINORM);
394 }
395 else if (jump_error_hilbert == 2)
396 {
397 error_estimator = std::make_unique<LaplacianErrorEstimator>();
398 error_norm.set_type(v, H2_SEMINORM);
399 }
400 else
401 libmesh_not_implemented();
402
403 if (libMesh::on_command_line("--jump_slits"))
404 error_estimator->integrate_slits = true;
405
406 ErrorVector error_per_cell;
407 error_estimator->error_norm = error_norm;
408 error_estimator->estimate_error(new_sys, error_per_cell);
409
410 const std::string var_name = new_sys.variable_name(v);
411
412 // I really want to just stop supporting libstdc++-8.
413 // const Real total_error = std::reduce(error_per_cell.begin(), error_per_cell.end());
414
415 ErrorVectorReal total_error = 0;
416 for (auto cell_error : error_per_cell)
417 total_error += cell_error;
418
419 if (jump_error_hilbert == 0)
420 libMesh::out << "L2";
421 else
422 libMesh::out << "H" << jump_error_hilbert;
423
424 libMesh::out << " error estimate for " << var_name << ": " <<
425 total_error << std::endl;
426 }
427 }
428
429 // Write out the new solution file
430 new_es.write(outsolnname.c_str(),
433 libMesh::out << "Wrote solution " << outsolnname << std::endl;
434 }
435 else
436 {
437 // If we aren't doing a projection, then we just do an integral
438 System & old_sys = old_es.get_system<System>(current_sys_name);
439
440 ConstElemRange active_local_elem_range
441 (old_mesh.active_local_elements_begin(),
442 old_mesh.active_local_elements_end());
443
444 Integrate integrate(old_sys, *goal_function);
445
446 Threads::parallel_reduce (active_local_elem_range,
447 integrate);
448
449 Number integral = integrate.integral();
450 old_mesh.comm().sum(integral);
451 libMesh::out << "Integral is " << integral << std::endl;
452 }
453
454 return 0;
455}
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...
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::EquationSystems::print_info(), libMesh::MeshBase::print_info(), 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().