libMesh
Loading...
Searching...
No Matches
adjoints_ex4.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
87using 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
219std::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
236std::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.
254int 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 =
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.
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 "
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 "
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 "
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}
void write_output(EquationSystems &es, unsigned int a_step, std::string solution_type, FEMParameters &param)
void set_system_parameters(LaplaceSystem &system, FEMParameters &param)
std::unique_ptr< AdjointRefinementEstimator > build_adjoint_refinement_error_estimator(QoISet &qois)
std::unique_ptr< MeshRefinement > build_mesh_refinement(MeshBase &mesh, FEMParameters &param)
double minimum_linear_tolerance
double initial_linear_tolerance
unsigned int max_adaptivesteps
double linear_tolerance_multiplier
libMesh::Real refine_fraction
unsigned int coarserefinements
libMesh::Real verify_analytic_jacobians
unsigned int max_nonlinear_iterations
std::string domainfile
libMesh::Real global_tolerance
libMesh::Real min_step_length
std::vector< std::string > fe_family
libMesh::Real relative_residual_tolerance
bool print_residual_norms
bool print_jacobian_norms
void read(GetPot &input, const std::vector< std::string > *other_variable_names=nullptr)
libMesh::Real relative_step_tolerance
unsigned int max_linear_iterations
bool require_residual_reduction
libMesh::Real coarsen_fraction
unsigned int nelem_target
std::vector< unsigned int > fe_order
libMesh::Real coarsen_threshold
bool print_solution_norms
bool reuse_preconditioner
virtual void postprocess()
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides.
Definition L-shaped.C:168
std::string & fe_family()
Definition L-shaped.h:24
Number & get_QoI_value(std::string type, unsigned int QoI_index)
Definition L-shaped.h:32
unsigned int & fe_order()
Definition L-shaped.h:25
bool & analytic_jacobians()
Definition L-shaped.h:26
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:85
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled.
bool postprocess_sides
If postprocess_sides is true (it is false by default), the postprocessing loop will loop over all sid...
bool print_residuals
Set print_residuals to true to print F whenever it is assembled.
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...
bool print_solution_norms
Set print_residual_norms to true to print |U| whenever it is used in an assembly() call.
virtual LinearSolver< Number > * get_linear_solver() const override
bool print_solutions
Set print_solutions to true to print U whenever it is used in an assembly() call.
bool print_residual_norms
Set print_residual_norms to true to print |F| whenever it is assembled.
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...
bool print_jacobian_norms
Set print_jacobian_norms to true to print |J| whenever it is assembled.
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
This is the EquationSystems class.
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
std::size_t n_active_dofs() const
const MeshBase & get_mesh() const
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 ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
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.
virtual void solve() override
Invokes the solver associated with the system.
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
This class implements writing meshes in the GMV format.
Definition gmv_io.h:48
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
This base class can be inherited from to provide interfaces to linear solvers from different packages...
virtual void reuse_preconditioner(bool)
Set the same_preconditioner flag, which indicates if we reuse the same preconditioner for subsequent ...
This is the MeshBase class.
Definition mesh_base.h:81
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:1803
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false, bool skip_detect_interior_parents=false)=0
Interfaces for reading/writing a mesh to/from a file.
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:1755
virtual dof_id_type n_active_elem() const =0
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
Implements (adaptive) mesh refinement algorithms for a MeshBase.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v.
processor_id_type processor_id() const
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
Definition qoi_set.h:46
void add_indices(const std::vector< unsigned int > &indices)
Add this indices to the set to be calculated.
Definition qoi_set.C:46
void set_weight(std::size_t, Real)
Set the weight for this index.
Definition qoi_set.h:232
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean.
Definition system.h:417
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
Definition system.C:1232
MeshBase & mesh
The libMesh namespace provides an interface to certain functionality in the library.
OStreamProxy err
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
Definition libmesh.C:1064
OStreamProxy out
int main()