libMesh
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.

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

Referenced by main().

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 }
OStreamProxy err
T command_line_next(std::string name, T default_value)
Use GetPot&#39;s search()/next() functions to get following arguments from the command line...
Definition: libmesh.C:1078
bool on_command_line(std::string arg)
Definition: libmesh.C:987
void usage_error(const char *progname)
Definition: calculator.C:61

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 163 of file calculator.C.

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::command_line_next(), libMesh::command_line_vector(), libMesh::ExactSolution::compute_error(), 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::TriangleWrapper::init(), libMesh::EquationSystems::init(), HilbertSystem::input_system, libMesh::L2, libMesh::ExactSolution::l2_error(), libMesh::make_range(), libMesh::MeshTools::n_connected_components(), libMesh::EquationSystems::n_systems(), libMesh::System::n_vars(), libMesh::on_command_line(), libMesh::out, libMesh::Threads::parallel_reduce(), libMesh::EquationSystems::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::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.

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,
237  EquationSystems::READ_HEADER |
238  EquationSystems::READ_DATA |
239  EquationSystems::READ_ADDITIONAL_DATA |
240  EquationSystems::READ_BASIC_ONLY);
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 << "L2 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  libMesh::out << "H" << jump_error_hilbert << " error estimate for " << var_name << ": " <<
420  total_error << std::endl;
421  }
422  }
423 
424  // Write out the new solution file
425  new_es.write(outsolnname.c_str(),
426  EquationSystems::WRITE_DATA |
427  EquationSystems::WRITE_ADDITIONAL_DATA);
428  libMesh::out << "Wrote solution " << outsolnname << std::endl;
429  }
430  else
431  {
432  // If we aren't doing a projection, then we just do an integral
433  System & old_sys = old_es.get_system<System>(current_sys_name);
434 
435  ConstElemRange active_local_elem_range
436  (old_mesh.active_local_elements_begin(),
437  old_mesh.active_local_elements_end());
438 
439  Integrate integrate(old_sys, *goal_function);
440 
441  Threads::parallel_reduce (active_local_elem_range,
442  integrate);
443 
444  Number integral = integrate.integral();
445  old_mesh.comm().sum(integral);
446  libMesh::out << "Integral is " << integral << std::endl;
447  }
448 
449  return 0;
450 }
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
T command_line_next(std::string name, T default_value)
Use GetPot&#39;s search()/next() functions to get following arguments from the command line...
Definition: libmesh.C:1078
std::set< libMesh::subdomain_id_type > & subdomains_list()
Definition: L2system.h:51
This is the EquationSystems class.
A Function generated (via FParser) by parsing a mathematical expression.
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
Definition: diff_solver.h:160
static constexpr Real TOLERANCE
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
Definition: error_vector.h:50
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we&#39;re going to use.
Definition: diff_system.h:253
This class defines a norm/seminorm to be applied to a NumericVector which contains coefficients in a ...
Definition: system_norm.h:49
The StoredRange class defines a contiguous, divisible set of objects.
Definition: stored_range.h:54
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:90
void init()
Initializes degrees of freedom on the current mesh.
Definition: system.C:197
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
Generic sparse matrix.
Definition: vector_fe_ex5.C:46
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
Definition: diff_solver.h:68
void set_goal_func(libMesh::FEMFunctionBase< libMesh::Number > &goal)
Definition: L2system.h:60
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...
Definition: system_norm.C:142
T assert_argument(const std::string &argname, const char *progname, const T &defaultarg)
Definition: calculator.C:91
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
Real calculate_norm(const NumericVector< Number > &v, unsigned int var, FEMNormType norm_type, std::set< unsigned int > *skip_dimensions=nullptr) const
Definition: system.C:1724
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
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:1357
const std::string & variable_name(const unsigned int i) const
Definition: system.h:2478
std::string & fe_family()
Definition: L2system.h:49
virtual void read(const std::string &filename)
Read the contents of the matrix from a file, with the file format inferred from the extension of file...
unsigned int & fe_order()
Definition: L2system.h:50
dof_id_type n_connected_components(const MeshBase &mesh, Real constraint_tol=0)
Definition: mesh_tools.C:840
bool verbose
The DiffSolver may print a lot more to libMesh::out if verbose is set to true; default is false...
Definition: diff_solver.h:166
unsigned int & hilbert_order()
Definition: L2system.h:53
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
libMesh::System * input_system
Definition: L2system.h:71
std::string current_sys_name
Definition: projection.C:76
void command_line_vector(const std::string &, std::vector< T > &)
Definition: libmesh.C:1097
OStreamProxy out
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:140
void parallel_reduce(const Range &range, Body &body)
Execute the provided reduction operation in parallel on the specified range.
Definition: threads_none.h:101
virtual void solve() override
Invokes the solver associated with the system.
Definition: fem_system.C:1076
bool on_command_line(std::string arg)
Definition: libmesh.C:987
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...
Definition: system_norm.C:123
unsigned int n_vars() const
Definition: system.h:2430
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false) override
Reads the file specified by name.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
void set_fdm_eps(libMesh::Real eps)
Definition: L2system.h:54
uint8_t dof_id_type
Definition: id_types.h:67

◆ usage_error()

void usage_error ( const char *  progname)

Definition at line 61 of file calculator.C.

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

Referenced by assert_argument().

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 }
static constexpr Real TOLERANCE
OStreamProxy out