libMesh
adjoints_ex4.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // <h1>Adjoints Example 4 - Laplace Equation in the L-Shaped Domain with AdjointRefinementErrorEstimator</h1>
21 // \author Vikram Garg
22 // \date 2012
23 //
24 // This example solves the Laplace equation on the classic "L-shaped"
25 // domain with adaptive mesh refinement. The exact
26 // solution is u(r,\theta) = r^{2/3} * \sin ( (2/3) * \theta). The kelly and
27 // adjoint residual error estimators are used to develop error indicators and
28 // guide mesh adaptation. Since we use the adjoint capabilities of libMesh in
29 // this example, we use the DiffSystem framework. This file (adjoints_ex1.C)
30 // contains the declaration of mesh and equation system objects, L-shaped.C
31 // contains the assembly of the system, element_qoi_derivative.C and
32 // side_qoi_derivative.C contain the RHS for the adjoint systems.
33 // Postprocessing to compute the QoIs is done in element_postprocess.C and
34 // side_postprocess.C.
35 
36 // The initial mesh contains three QUAD9 elements which represent the
37 // standard quadrants I, II, and III of the domain [-1,1]x[-1,1],
38 // i.e.
39 // Element 0: [-1,0]x[ 0,1]
40 // Element 1: [ 0,1]x[ 0,1]
41 // Element 2: [-1,0]x[-1,0]
42 // The mesh is provided in the standard libMesh ASCII format file
43 // named "lshaped.xda". In addition, an input file named "general.in"
44 // is provided which allows the user to set several parameters for
45 // the solution so that the problem can be re-run without a
46 // re-compile. The solution technique employed is to have a
47 // refinement loop with a linear (forward and adjoint) solve inside followed by a
48 // refinement of the grid and projection of the solution to the new grid
49 // In the final loop iteration, there is no additional
50 // refinement after the solve. In the input file "general.in", the variable
51 // "max_adaptivesteps" controls the number of refinement steps, and
52 // "refine_fraction" / "coarsen_fraction" determine the number of
53 // elements which will be refined / coarsened at each step.
54 
55 // C++ includes
56 #include <iostream>
57 #include <iomanip>
58 #include <memory>
59 
60 // General libMesh includes
61 #include "libmesh/equation_systems.h"
62 #include "libmesh/linear_solver.h"
63 #include "libmesh/error_vector.h"
64 #include "libmesh/mesh.h"
65 #include "libmesh/mesh_refinement.h"
66 #include "libmesh/newton_solver.h"
67 #include "libmesh/numeric_vector.h"
68 #include "libmesh/petsc_diff_solver.h"
69 #include "libmesh/steady_solver.h"
70 #include "libmesh/system_norm.h"
71 #include "libmesh/enum_solver_package.h"
72 
73 // Adjoint Related includes
74 #include "libmesh/qoi_set.h"
75 #include "libmesh/adjoint_refinement_estimator.h"
76 
77 // libMesh I/O includes
78 #include "libmesh/getpot.h"
79 #include "libmesh/gmv_io.h"
80 #include "libmesh/exodusII_io.h"
81 
82 // Local includes
83 #include "femparameters.h"
84 #include "L-shaped.h"
85 
86 // Bring in everything from the libMesh namespace
87 using namespace libMesh;
88 
89 // Local function declarations
90 
91 // Number output files, the files are give a prefix of primal or adjoint_i depending on
92 // whether the output is the primal solution or the dual solution for the ith QoI
93 
94 // Optionally write different types of output files.
96  unsigned int a_step, // The adaptive step count
97  std::string solution_type, // primal or adjoint solve
98  FEMParameters & param)
99 {
100  // Ignore parameters when there are no output formats available.
101  libmesh_ignore(es, a_step, solution_type, param);
102 
103 #ifdef LIBMESH_HAVE_GMV
104  if (param.output_gmv)
105  {
106  MeshBase & mesh = es.get_mesh();
107 
108  std::ostringstream file_name_gmv;
109  file_name_gmv << solution_type
110  << ".out.gmv."
111  << std::setw(2)
112  << std::setfill('0')
113  << std::right
114  << a_step;
115 
117  (file_name_gmv.str(), es);
118  }
119 #endif
120 
121 #ifdef LIBMESH_HAVE_EXODUS_API
122  if (param.output_exodus)
123  {
124  MeshBase & mesh = es.get_mesh();
125 
126  // We write out one file per adaptive step. The files are named in
127  // the following way:
128  // foo.e
129  // foo.e-s002
130  // foo.e-s003
131  // ...
132  // so that, if you open the first one with Paraview, it actually
133  // opens the entire sequence of adapted files.
134  std::ostringstream file_name_exodus;
135 
136  file_name_exodus << solution_type << ".e";
137  if (a_step > 0)
138  file_name_exodus << "-s"
139  << std::setw(3)
140  << std::setfill('0')
141  << std::right
142  << a_step + 1;
143 
144  // We write each adaptive step as a pseudo "time" step, where the
145  // time simply matches the (1-based) adaptive step we are on.
146  ExodusII_IO(mesh).write_timestep(file_name_exodus.str(),
147  es,
148  1,
149  /*time=*/a_step + 1);
150  }
151 #endif
152 }
153 
154 // Set the parameters for the nonlinear and linear solvers to be used during the simulation
155 
157  FEMParameters & param)
158 {
159  // Use analytical jacobians?
160  system.analytic_jacobians() = param.analytic_jacobians;
161 
162  // Verify analytic jacobians against numerical ones?
164 
165  // Use the prescribed FE type
166  system.fe_family() = param.fe_family[0];
167  system.fe_order() = param.fe_order[0];
168 
169  // More desperate debugging options
171  system.print_solutions = param.print_solutions;
173  system.print_residuals = param.print_residuals;
175  system.print_jacobians = param.print_jacobians;
176 
177  // No transient time solver
178  system.time_solver = std::make_unique<SteadySolver>(system);
179 
180  // Nonlinear solver options
181  if (param.use_petsc_snes)
182  {
183 #ifdef LIBMESH_HAVE_PETSC
184  system.time_solver->diff_solver() = std::make_unique<PetscDiffSolver>(system);
185 #else
186  libmesh_error_msg("This example requires libMesh to be compiled with PETSc support.");
187 #endif
188  }
189  else
190  {
191  system.time_solver->diff_solver() = std::make_unique<NewtonSolver>(system);
192  auto solver = cast_ptr<NewtonSolver*>(system.time_solver->diff_solver().get());
193 
194  solver->quiet = param.solver_quiet;
195  solver->max_nonlinear_iterations = param.max_nonlinear_iterations;
196  solver->minsteplength = param.min_step_length;
197  solver->relative_step_tolerance = param.relative_step_tolerance;
198  solver->relative_residual_tolerance = param.relative_residual_tolerance;
199  solver->require_residual_reduction = param.require_residual_reduction;
200  solver->linear_tolerance_multiplier = param.linear_tolerance_multiplier;
201  if (system.time_solver->reduce_deltat_on_diffsolver_failure)
202  {
203  solver->continue_after_max_iterations = true;
204  solver->continue_after_backtrack_failure = true;
205  }
207 
208  // And the linear solver options
209  solver->max_linear_iterations = param.max_linear_iterations;
210  solver->initial_linear_tolerance = param.initial_linear_tolerance;
211  solver->minimum_linear_tolerance = param.minimum_linear_tolerance;
212  }
213 }
214 
215 // Build the mesh refinement object and set parameters for refining/coarsening etc
216 
217 #ifdef LIBMESH_ENABLE_AMR
218 
219 std::unique_ptr<MeshRefinement> build_mesh_refinement(MeshBase & mesh,
220  FEMParameters & param)
221 {
222  auto mesh_refinement = std::make_unique<MeshRefinement>(mesh);
223  mesh_refinement->coarsen_by_parents() = true;
224  mesh_refinement->absolute_global_tolerance() = param.global_tolerance;
225  mesh_refinement->nelem_target() = param.nelem_target;
226  mesh_refinement->refine_fraction() = param.refine_fraction;
227  mesh_refinement->coarsen_fraction() = param.coarsen_fraction;
228  mesh_refinement->coarsen_threshold() = param.coarsen_threshold;
229 
230  return mesh_refinement;
231 }
232 
233 // This is where declare the adjoint refined error estimator. This estimator builds an error bound
234 // for Q(u) - Q(u_h), by solving the adjoint problem on a finer Finite Element space. For more details
235 // see the description of the Adjoint Refinement Error Estimator in adjoint_refinement_error_estimator.C
236 std::unique_ptr<AdjointRefinementEstimator> build_adjoint_refinement_error_estimator(QoISet & qois)
237 {
238  libMesh::out << "Computing the error estimate using the Adjoint Refinement Error Estimator" << std::endl << std::endl;
239 
240  auto adjoint_refinement_estimator = std::make_unique<AdjointRefinementEstimator>();
241 
242  adjoint_refinement_estimator->qoi_set() = qois;
243 
244  // We enrich the FE space for the dual problem by doing 2 uniform h refinements
245  adjoint_refinement_estimator->number_h_refinements = 2;
246 
247  return adjoint_refinement_estimator;
248 }
249 
250 #endif // LIBMESH_ENABLE_AMR
251 
252 
253 // The main program.
254 int main (int argc, char** argv)
255 {
256  // Initialize libMesh.
257  LibMeshInit init (argc, argv);
258 
259  // This example requires a linear solver package.
260  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
261  "--enable-petsc, --enable-trilinos, or --enable-eigen");
262 
263  // Skip adaptive examples on a non-adaptive libMesh build
264 #ifndef LIBMESH_ENABLE_AMR
265  libmesh_example_requires(false, "--enable-amr");
266 #else
267 
268  libMesh::out << "Started " << argv[0] << std::endl;
269 
270  // Make sure the general input file exists, and parse it
271  {
272  std::ifstream i("general.in");
273  libmesh_error_msg_if(!i, '[' << init.comm().rank() << "] Can't find general.in; exiting early.");
274  }
275 
276  // Read in parameters from the input file
277  GetPot infile("general.in");
278 
279  // But allow the command line to override it.
280  infile.parse_command_line(argc, argv);
281 
282  FEMParameters param(init.comm());
283  param.read(infile);
284 
285  // Skip this default-2D example if libMesh was compiled as 1D-only.
286  libmesh_example_requires(2 <= LIBMESH_DIM, "2D support");
287 
288  // Create a mesh, with dimension to be overridden later, distributed
289  // across the default MPI communicator.
290  Mesh mesh(init.comm());
291 
292  // And an object to refine it
293  std::unique_ptr<MeshRefinement> mesh_refinement =
294  build_mesh_refinement(mesh, param);
295 
296  // And an EquationSystems to run on it
297  EquationSystems equation_systems (mesh);
298 
299  libMesh::out << "Reading in and building the mesh" << std::endl;
300 
301  // Read in the mesh
302  mesh.read(param.domainfile.c_str());
303  // Make all the elements of the mesh second order so we can compute
304  // with a higher order basis
306 
307  // Create a mesh refinement object to do the initial uniform refinements
308  // on the coarse grid read in from lshaped.xda
309  MeshRefinement initial_uniform_refinements(mesh);
310  initial_uniform_refinements.uniformly_refine(param.coarserefinements);
311 
312  libMesh::out << "Building system" << std::endl;
313 
314  // Build the FEMSystem
315  LaplaceSystem & system = equation_systems.add_system<LaplaceSystem> ("LaplaceSystem");
316 
317  // Set its parameters
318  set_system_parameters(system, param);
319 
320  libMesh::out << "Initializing systems" << std::endl;
321 
322  equation_systems.init ();
323 
324  // Print information about the mesh and system to the screen.
325  mesh.print_info();
326  equation_systems.print_info();
327  LinearSolver<Number> *linear_solver = system.get_linear_solver();
328 
329  {
330  // Adaptively solve the timestep
331  unsigned int a_step = 0;
332  for (; a_step != param.max_adaptivesteps; ++a_step)
333  {
334  // We can't adapt to both a tolerance and a
335  // target mesh size
336  if (param.global_tolerance != 0.)
337  libmesh_assert_equal_to (param.nelem_target, 0);
338  // If we aren't adapting to a tolerance we need a
339  // target mesh size
340  else
341  libmesh_assert_greater (param.nelem_target, 0);
342 
343  linear_solver->reuse_preconditioner(false);
344 
345  // Solve the forward problem
346  system.solve();
347 
348  // Write out the computed primal solution
349  write_output(equation_systems, a_step, "primal", param);
350 
351  // Get a pointer to the primal solution vector
352  NumericVector<Number> & primal_solution = *system.solution;
353 
354  // Declare a QoISet object, we need this object to set weights for our QoI error contributions
355  QoISet qois;
356 
357  // Declare a qoi_indices vector, each index will correspond to a QoI
358  qois.add_indices({0,1});
359 
360  // Set weights for each index, these will weight the contribution of each QoI in the final error
361  // estimate to be used for flagging elements for refinement
362  qois.set_weight(0, 0.5);
363  qois.set_weight(1, 0.5);
364 
365  // Make sure we get the contributions to the adjoint RHS from the sides
366  system.assemble_qoi_sides = true;
367 
368  // We are about to solve the adjoint system, but before we do this we see the same preconditioner
369  // flag to reuse the preconditioner from the forward solver
370  linear_solver->reuse_preconditioner(param.reuse_preconditioner);
371 
372  // Solve the adjoint system. This takes the transpose of the stiffness matrix and then
373  // solves the resulting system
374  system.adjoint_solve();
375 
376  // Now that we have solved the adjoint, set the adjoint_already_solved boolean to true, so we dont solve unnecessarily in the error estimator
377  system.set_adjoint_already_solved(true);
378 
379  // Get a pointer to the solution vector of the adjoint problem for QoI 0
380  NumericVector<Number> & dual_solution_0 = system.get_adjoint_solution(0);
381 
382  // Swap the primal and dual solutions so we can write out the adjoint solution
383  primal_solution.swap(dual_solution_0);
384  write_output(equation_systems, a_step, "adjoint_0", param);
385 
386  // Swap back
387  primal_solution.swap(dual_solution_0);
388 
389  // Get a pointer to the solution vector of the adjoint problem for QoI 0
390  NumericVector<Number> & dual_solution_1 = system.get_adjoint_solution(1);
391 
392  // Swap again
393  primal_solution.swap(dual_solution_1);
394  write_output(equation_systems, a_step, "adjoint_1", param);
395 
396  // Swap back again
397  primal_solution.swap(dual_solution_1);
398 
399  libMesh::out << "Adaptive step "
400  << a_step
401  << ", we have "
402  << mesh.n_active_elem()
403  << " active elements and "
404  << equation_systems.n_active_dofs()
405  << " active dofs."
406  << std::endl;
407 
408  // Postprocess, compute the approximate QoIs and write them out to the console
409  libMesh::out << "Postprocessing: " << std::endl;
410  system.postprocess_sides = true;
411  system.postprocess();
412  Number QoI_0_computed = system.get_QoI_value("computed", 0);
413  Number QoI_0_exact = system.get_QoI_value("exact", 0);
414  Number QoI_1_computed = system.get_QoI_value("computed", 1);
415  Number QoI_1_exact = system.get_QoI_value("exact", 1);
416 
417  libMesh::out << "The relative error in QoI 0 is "
418  << std::setprecision(17)
419  << std::abs(QoI_0_computed - QoI_0_exact) / std::abs(QoI_0_exact)
420  << std::endl;
421 
422  libMesh::out << "The relative error in QoI 1 is "
423  << std::setprecision(17)
424  << std::abs(QoI_1_computed - QoI_1_exact) / std::abs(QoI_1_exact)
425  << std::endl
426  << std::endl;
427 
428  // We will declare an error vector for passing to the adjoint refinement error estimator
429  ErrorVector QoI_elementwise_error;
430 
431  // Build an adjoint refinement error estimator object
432  std::unique_ptr<AdjointRefinementEstimator> adjoint_refinement_error_estimator =
434 
435  // Estimate the error in each element using the Adjoint Refinement estimator
436  adjoint_refinement_error_estimator->estimate_error(system, QoI_elementwise_error);
437 
438  // Print out the computed error estimate, note that we access the global error estimates
439  // using an accessor function, right now sum(QoI_elementwise_error) != global_QoI_error_estimate
440  libMesh::out << "The computed relative error in QoI 0 is "
441  << std::setprecision(17)
442  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_exact)
443  << std::endl;
444 
445  libMesh::out << "The computed relative error in QoI 1 is "
446  << std::setprecision(17)
447  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_exact)
448  << std::endl
449  << std::endl;
450 
451  // Also print out effectivity indices (estimated error/true error)
452  libMesh::out << "The effectivity index for the computed error in QoI 0 is "
453  << std::setprecision(17)
454  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_computed - QoI_0_exact)
455  << std::endl;
456 
457  libMesh::out << "The effectivity index for the computed error in QoI 1 is "
458  << std::setprecision(17)
459  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_computed - QoI_1_exact)
460  << std::endl
461  << std::endl;
462 
463  // For refinement purposes we need to sort by error
464  // *magnitudes*, but AdjointRefinement gives us signed errors.
465  if (!param.refine_uniformly)
466  for (std::size_t i=0; i<QoI_elementwise_error.size(); i++)
467  if (QoI_elementwise_error[i] != 0.)
468  QoI_elementwise_error[i] = std::abs(QoI_elementwise_error[i]);
469 
470  // We have to refine either based on reaching an error tolerance or
471  // a number of elements target, which should be verified above
472  // Otherwise we flag elements by error tolerance or nelem target
473 
474  // Uniform refinement
475  if (param.refine_uniformly)
476  {
477  mesh_refinement->uniformly_refine(1);
478  }
479  // Adaptively refine based on reaching an error tolerance
480  else if (param.global_tolerance >= 0. && param.nelem_target == 0.)
481  {
482  mesh_refinement->flag_elements_by_error_tolerance (QoI_elementwise_error);
483 
484  mesh_refinement->refine_and_coarsen_elements();
485  }
486  // Adaptively refine based on reaching a target number of elements
487  else
488  {
489  if (mesh.n_active_elem() >= param.nelem_target)
490  {
491  libMesh::out << "We reached the target number of elements." << std::endl << std::endl;
492  break;
493  }
494 
495  mesh_refinement->flag_elements_by_nelem_target (QoI_elementwise_error);
496 
497  mesh_refinement->refine_and_coarsen_elements();
498  }
499 
500  // Dont forget to reinit the system after each adaptive refinement !
501  equation_systems.reinit();
502 
503  libMesh::out << "Refined mesh to "
504  << mesh.n_active_elem()
505  << " active elements and "
506  << equation_systems.n_active_dofs()
507  << " active dofs."
508  << std::endl;
509  }
510 
511  // Do one last solve if necessary
512  if (a_step == param.max_adaptivesteps)
513  {
514  linear_solver->reuse_preconditioner(false);
515  system.solve();
516 
517  write_output(equation_systems, a_step, "primal", param);
518 
519  NumericVector<Number> & primal_solution = *system.solution;
520 
521  QoISet qois;
522  qois.add_indices({0,1});
523 
524  qois.set_weight(0, 0.5);
525  qois.set_weight(1, 0.5);
526 
527  system.assemble_qoi_sides = true;
528  linear_solver->reuse_preconditioner(param.reuse_preconditioner);
529  system.adjoint_solve();
530 
531  // Now that we have solved the adjoint, set the adjoint_already_solved boolean to true, so we dont solve unnecessarily in the error estimator
532  system.set_adjoint_already_solved(true);
533 
534  NumericVector<Number> & dual_solution_0 = system.get_adjoint_solution(0);
535 
536  primal_solution.swap(dual_solution_0);
537  write_output(equation_systems, a_step, "adjoint_0", param);
538 
539  primal_solution.swap(dual_solution_0);
540 
541  NumericVector<Number> & dual_solution_1 = system.get_adjoint_solution(1);
542 
543  primal_solution.swap(dual_solution_1);
544  write_output(equation_systems, a_step, "adjoint_1", param);
545 
546  primal_solution.swap(dual_solution_1);
547 
548  libMesh::out << "Adaptive step "
549  << a_step
550  << ", we have "
551  << mesh.n_active_elem()
552  << " active elements and "
553  << equation_systems.n_active_dofs()
554  << " active dofs."
555  << std::endl;
556 
557  libMesh::out << "Postprocessing: " << std::endl;
558  system.postprocess_sides = true;
559  system.postprocess();
560 
561  Number QoI_0_computed = system.get_QoI_value("computed", 0);
562  Number QoI_0_exact = system.get_QoI_value("exact", 0);
563  Number QoI_1_computed = system.get_QoI_value("computed", 1);
564  Number QoI_1_exact = system.get_QoI_value("exact", 1);
565 
566  libMesh::out << "The relative error in QoI 0 is "
567  << std::setprecision(17)
568  << std::abs(QoI_0_computed - QoI_0_exact) / std::abs(QoI_0_exact)
569  << std::endl;
570 
571  libMesh::out << "The relative error in QoI 1 is "
572  << std::setprecision(17)
573  << std::abs(QoI_1_computed - QoI_1_exact) / std::abs(QoI_1_exact)
574  << std::endl
575  << std::endl;
576 
577  // We will declare an error vector for passing to the adjoint refinement error estimator
578  // Right now, only the first entry of this vector will be filled (with the global QoI error estimate)
579  // Later, each entry of the vector will contain elementwise error that the user can sum to get the total error
580  ErrorVector QoI_elementwise_error;
581 
582  // Build an adjoint refinement error estimator object
583  std::unique_ptr<AdjointRefinementEstimator> adjoint_refinement_error_estimator =
585 
586  // Estimate the error in each element using the Adjoint Refinement estimator
587  adjoint_refinement_error_estimator->estimate_error(system, QoI_elementwise_error);
588 
589  // Print out the computed error estimate, note that we access the global error estimates
590  // using an accessor function, right now sum(QoI_elementwise_error) != global_QoI_error_estimate
591  libMesh::out << "The computed relative error in QoI 0 is "
592  << std::setprecision(17)
593  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_exact)
594  << std::endl;
595 
596  libMesh::out << "The computed relative error in QoI 1 is "
597  << std::setprecision(17)
598  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_exact)
599  << std::endl
600  << std::endl;
601 
602  // Also print out effectivity indices (estimated error/true error)
603  libMesh::out << "The effectivity index for the computed error in QoI 0 is "
604  << std::setprecision(17)
605  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_computed - QoI_0_exact)
606  << std::endl;
607 
608  libMesh::out << "The effectivity index for the computed error in QoI 1 is "
609  << std::setprecision(17)
610  << std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_computed - QoI_1_exact)
611  << std::endl
612  << std::endl;
613 
614  // Hard coded assert to ensure that the actual numbers we are getting are what they should be
615 
616  // The effectivity index isn't exactly reproducible at single precision
617  // libmesh_assert_less(std::abs(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_computed - QoI_0_exact) - 0.84010976704434637), 1.e-5);
618  // libmesh_assert_less(std::abs(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_computed - QoI_1_exact) - 0.48294428289950514), 1.e-5);
619 
620  // But the effectivity indices should always be sane
621  libmesh_assert_less(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_computed - QoI_0_exact), 2.5);
622  libmesh_assert_greater(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(0)) / std::abs(QoI_0_computed - QoI_0_exact), .4);
623  libmesh_assert_less(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_computed - QoI_1_exact), 2.5);
624  libmesh_assert_greater(std::abs(adjoint_refinement_error_estimator->get_global_QoI_error_estimate(1)) / std::abs(QoI_1_computed - QoI_1_exact), .4);
625 
626  // And the computed errors should still be low
627  libmesh_assert_less(std::abs(QoI_0_computed - QoI_0_exact), 2e-4);
628  libmesh_assert_less(std::abs(QoI_1_computed - QoI_1_exact), 2e-4);
629  }
630  }
631 
632  libMesh::err << '[' << mesh.processor_id()
633  << "] Completing output."
634  << std::endl;
635 
636 #endif // #ifndef LIBMESH_ENABLE_AMR
637 
638  // All done.
639  return 0;
640 }
unsigned int nelem_target
Definition: femparameters.h:60
OStreamProxy err
bool print_solution_norms
This is the EquationSystems class.
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
void set_weight(std::size_t, Real)
Set the weight for this index.
Definition: qoi_set.h:232
virtual dof_id_type n_active_elem() const =0
Real verify_analytic_jacobians
If verify_analytic_jacobian is equal to zero (as it is by default), no numeric jacobians will be calc...
Definition: fem_system.h:215
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean.
Definition: system.h:415
bool analytic_jacobians
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition: mesh_output.C:31
virtual void set_constrain_in_solver(bool enable)
set_constrain_in_solver to false to apply constraints only via residual terms in the systems to be so...
Definition: diff_system.C:424
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
Definition: qoi_set.h:45
bool print_jacobian_norms
Set print_jacobian_norms to true to print |J| whenever it is assembled.
Definition: diff_system.h:361
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
Definition: error_vector.h:50
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:52
Number & get_QoI_value(std::string type, unsigned int QoI_index)
Definition: L-shaped.h:32
std::string & fe_family()
Definition: L-shaped.h:24
bool require_residual_reduction
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we&#39;re going to use.
Definition: diff_system.h:253
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
void write_output(EquationSystems &es, unsigned int a_step, std::string solution_type, FEMParameters &param)
Definition: adjoints_ex4.C:95
MeshBase & mesh
bool print_residual_norms
libMesh::Real relative_step_tolerance
bool & analytic_jacobians()
Definition: L-shaped.h:26
bool postprocess_sides
If postprocess_sides is true (it is false by default), the postprocessing loop will loop over all sid...
Definition: diff_system.h:334
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:90
The libMesh namespace provides an interface to certain functionality in the library.
This class implements writing meshes in the GMV format.
Definition: gmv_io.h:46
libMesh::Real refine_fraction
Definition: femparameters.h:62
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled.
Definition: diff_system.h:366
This is the MeshBase class.
Definition: mesh_base.h:75
std::vector< unsigned int > fe_order
std::unique_ptr< MeshRefinement > build_mesh_refinement(MeshBase &mesh, FEMParameters &param)
Definition: adjoints_ex4.C:219
SolverPackage default_solver_package()
Definition: libmesh.C:1117
libMesh::Real coarsen_threshold
Definition: femparameters.h:62
bool print_solution_norms
Set print_residual_norms to true to print |U| whenever it is used in an assembly() call...
Definition: diff_system.h:340
void libmesh_ignore(const Args &...)
Implements (adaptive) mesh refinement algorithms for a MeshBase.
unsigned int max_linear_iterations
bool constrain_in_solver
bool print_residual_norms
Set print_residual_norms to true to print |F| whenever it is assembled.
Definition: diff_system.h:351
double minimum_linear_tolerance
void set_system_parameters(LaplaceSystem &system, FEMParameters &param)
Definition: adjoints_ex4.C:156
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition: mesh_base.C:1562
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
std::vector< std::string > fe_family
libMesh::Real verify_analytic_jacobians
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
bool print_residuals
Set print_residuals to true to print F whenever it is assembled.
Definition: diff_system.h:356
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
double initial_linear_tolerance
libMesh::Real global_tolerance
Definition: femparameters.h:61
void read(GetPot &input, const std::vector< std::string > *other_variable_names=nullptr)
int main(int argc, char **argv)
Definition: adjoints_ex4.C:254
bool print_solutions
Set print_solutions to true to print U whenever it is used in an assembly() call. ...
Definition: diff_system.h:346
libMesh::Real relative_residual_tolerance
unsigned int & fe_order()
Definition: L-shaped.h:25
virtual LinearSolver< Number > * get_linear_solver() const override
Definition: diff_system.C:163
virtual void reuse_preconditioner(bool)
Set the same_preconditioner flag, which indicates if we reuse the same preconditioner for subsequent ...
bool print_jacobian_norms
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v.
bool assemble_qoi_sides
If assemble_qoi_sides is true (it is false by default), the assembly loop for a quantity of interest ...
Definition: diff_qoi.h:99
void write_timestep(const std::string &fname, const EquationSystems &es, const int timestep, const Real time, const std::set< std::string > *system_names=nullptr)
Writes out the solution at a specific timestep.
Definition: exodusII_io.C:2017
OStreamProxy out
void add_indices(const std::vector< unsigned int > &indices)
Add this indices to the set to be calculated.
Definition: qoi_set.C:46
const MeshBase & get_mesh() const
libMesh::Real min_step_length
std::size_t n_active_dofs() const
void all_second_order(const bool full_ordered=true)
Calls the range-based version of this function with a range consisting of all elements in the mesh...
Definition: mesh_base.C:1608
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
Definition: system.C:1245
unsigned int max_nonlinear_iterations
double linear_tolerance_multiplier
virtual void solve() override
Invokes the solver associated with the system.
Definition: fem_system.C:1076
virtual void init()
Initialize all the systems.
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
virtual std::pair< unsigned int, Real > adjoint_solve(const QoISet &qoi_indices=QoISet()) override
This function sets the _is_adjoint boolean member of TimeSolver to true and then calls the adjoint_so...
Definition: diff_system.C:150
virtual void postprocess()
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides...
Definition: L-shaped.C:168
libMesh::Real coarsen_fraction
Definition: femparameters.h:62
std::unique_ptr< AdjointRefinementEstimator > build_adjoint_refinement_error_estimator(QoISet &qois)
Definition: adjoints_ex4.C:236
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.