libMesh
Loading...
Searching...
No Matches
adjoints_ex3.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// <h1>Adjoints Example 3 - Stokes flow and Convection-Diffusion</h1>
20// \author Vikram Garg
21// \date 2012
22//
23// We solve a coupled Stokes + Convection Diffusion system in an H channel geometry
24// with 2 inlets and 2 outlets. The QoI is the species
25// flux from left outlet
26
27// Channel Geometry:
28// Wall
29// ----------------------------------------------------------------
30// 0 1
31// ---------------------------- -------------------------------
32// | |
33// Wall | | Wall
34// | |
35// ----------------------------- -------------------------------
36// 2 2
37// -----------------------------------------------------------------
38// Wall
39
40// The equations governing this flow are:
41// Stokes: -VectorLaplacian(velocity) + grad(pressure) = vector(0)
42// Convection-Diffusion: - dot(velocity, grad(concentration) ) + Laplacian(concentration) = 0
43
44// The boundary conditions are:
45// u_1(0) = -(y-2)*(y-3), u_2(0) = 0 ; u_1(1) = (y-2)*(y-3), u_2(1) = 0 ;
46// u_1(walls) = 0, u_2(walls) = 0;
47// C(0) = 1 ; C(1) = 0;
48// grad(C) dot n (walls) = 0 ;
49// grad(C) dot n (2) = 0 ; grad(C) dot n (3) = 0
50
51// The QoI is:
52// Q((u,v), C) = integral_{left_outlet} - u * C ds
53
54// The complete equal order adjoint QoI error estimate is: (Notation for derivatives: grad(C) = C,1 + C,2)
55// Q(u) - Q(u_h) \leq
56// |e(u_1)|_{H1} |e(u_1^*)|_{H1} + |e(u_2)|_{H1} |e(u_2^*)|_{H1} + (1/Pe) * |e(C)|_{H1} |e(C^*)|_{H1} +
57// ||e(u_1,1)||_{L2} ||e(p^*)||_{L2} + ||e(u_2,2)||_{L2} ||e(p^*)||_{L2} + ||e(u_1,1^*)||_{L2} ||e(p)||_{L2} + ||e(u_2,2^*)||_{L2} ||e(p)||_{L2} +
58// ||e((u_1)_h C,1)||_{L2} ||e(C^*)||_{L2} + ||e(u1 C,1_h)||_{L2} ||e(C^*)||_{L2}
59// ||e((u_2)_h C,2)||_{L2} ||e(C^*)||_{L2} + ||e(u2 C,2_h)||_{L2} ||e(C^*)||_{L2}
60// = error_non_pressure + error_with_pressure + error_convection_diffusion_x + error_convection_diffusion_y
61
62// C++ includes
63#include <iostream>
64#include <sys/time.h>
65#include <iomanip>
66#include <memory>
67
68// Libmesh includes
69#include "libmesh/equation_systems.h"
70#include "libmesh/twostep_time_solver.h"
71#include "libmesh/euler_solver.h"
72#include "libmesh/euler2_solver.h"
73#include "libmesh/steady_solver.h"
74#include "libmesh/newton_solver.h"
75#include "libmesh/numeric_vector.h"
76#include "libmesh/petsc_diff_solver.h"
77#include "libmesh/mesh.h"
78#include "libmesh/mesh_tools.h"
79#include "libmesh/mesh_base.h"
80#include "libmesh/mesh_refinement.h"
81#include "libmesh/system.h"
82#include "libmesh/system_norm.h"
83#include "libmesh/adjoint_residual_error_estimator.h"
84#include "libmesh/const_fem_function.h"
85#include "libmesh/error_vector.h"
86#include "libmesh/fem_function_base.h"
87#include "libmesh/getpot.h"
88#include "libmesh/gmv_io.h"
89#include "libmesh/exodusII_io.h"
90#include "libmesh/kelly_error_estimator.h"
91#include "libmesh/parameter_vector.h"
92#include "libmesh/patch_recovery_error_estimator.h"
93#include "libmesh/petsc_vector.h"
94#include "libmesh/sensitivity_data.h"
95#include "libmesh/tecplot_io.h"
96#include "libmesh/uniform_refinement_estimator.h"
97#include "libmesh/qoi_set.h"
98#include "libmesh/weighted_patch_recovery_error_estimator.h"
99#include "libmesh/enum_solver_package.h"
100#include "libmesh/enum_xdr_mode.h"
101
102// Local includes
103#include "coupled_system.h"
104#include "domain.h"
105#include "initial.h"
106#include "femparameters.h"
107#include "mysystems.h"
108#include "output.h"
109#include "H-qoi.h"
110
111
112// Bring in everything from the libMesh namespace
113using namespace libMesh;
114
115// Number output files
116
117std::string numbered_filename(unsigned int t_step, // The timestep count
118 unsigned int a_step, // The adaptive step count
119 std::string solution_type, // primal or adjoint solve
120 std::string type,
121 std::string extension,
122 FEMParameters & param)
123{
124 std::ostringstream file_name;
125 file_name << solution_type
126 << ".out."
127 << type
128 << '.'
129 << std::setw(3)
130 << std::setfill('0')
131 << std::right
132 << t_step
133 << '.'
134 << std::setw(2)
135 << std::setfill('0')
136 << std::right
137 << a_step
138 << '.'
139 << extension;
140
141 if (param.output_bz2)
142 file_name << ".bz2";
143 else if (param.output_gz)
144 file_name << ".gz";
145 return file_name.str();
146}
147
148// Possibly write tecplot, gmv, xda/xdr, and exodus output files.
150 unsigned int t_step, // The timestep count
151 unsigned int a_step, // The adaptive step count
152 std::string solution_type, // primal or adjoint solve
153 FEMParameters & param)
154{
155 MeshBase & mesh = es.get_mesh();
156
157#ifdef LIBMESH_HAVE_GMV
158 if (param.output_gmv)
159 {
160 std::ostringstream file_name_gmv;
161 file_name_gmv << solution_type
162 << ".out.gmv."
163 << std::setw(3)
164 << std::setfill('0')
165 << std::right
166 << t_step
167 << '.'
168 << std::setw(2)
169 << std::setfill('0')
170 << std::right
171 << a_step;
172
174 (file_name_gmv.str(), es);
175 }
176#endif
177
178#ifdef LIBMESH_HAVE_TECPLOT_API
179 if (param.output_tecplot)
180 {
181 std::ostringstream file_name_tecplot;
182 file_name_tecplot << solution_type
183 << ".out."
184 << std::setw(3)
185 << std::setfill('0')
186 << std::right
187 << t_step
188 << '.'
189 << std::setw(2)
190 << std::setfill('0')
191 << std::right
192 << a_step
193 << ".plt";
194
196 (file_name_tecplot.str(), es);
197 }
198#endif
199
200 if (param.output_xda || param.output_xdr)
202 if (param.output_xda)
203 {
204 mesh.write(numbered_filename(t_step, a_step, solution_type, "mesh", "xda", param));
205 es.write(numbered_filename(t_step, a_step, solution_type, "soln", "xda", param),
208 }
209 if (param.output_xdr)
210 {
211 mesh.write(numbered_filename(t_step, a_step, solution_type, "mesh", "xdr", param));
212 es.write(numbered_filename(t_step, a_step, solution_type, "soln", "xdr", param),
215 }
216
217#ifdef LIBMESH_HAVE_EXODUS_API
218 if (param.output_exodus)
219 {
220 // We write out one file per adaptive step. The files are named in
221 // the following way:
222 // foo.e
223 // foo.e-s002
224 // foo.e-s003
225 // ...
226 // so that, if you open the first one with Paraview, it actually
227 // opens the entire sequence of adapted files.
228 std::ostringstream file_name_exodus;
229
230 file_name_exodus << solution_type << ".e";
231 if (a_step > 0)
232 file_name_exodus << "-s"
233 << std::setw(3)
234 << std::setfill('0')
235 << std::right
236 << a_step + 1;
237
238 // We write each adaptive step as a pseudo "time" step, where the
239 // time simply matches the (1-based) adaptive step we are on.
240 ExodusII_IO(mesh).write_timestep(file_name_exodus.str(),
241 es,
242 1,
243 /*time=*/a_step + 1);
244 }
245#endif
246}
247
249{
250 // Only one processor needs to take care of headers.
252 return;
253
254 start_output(param.initial_timestep, "out_clocktime.m", "vector_clocktime");
255
256 if (param.run_simulation)
257 {
258 start_output(param.initial_timestep, "out_activemesh.m", "table_activemesh");
259 start_output(param.initial_timestep, "out_solvesteps.m", "table_solvesteps");
260
261 if (param.timesolver_tolerance)
262 {
263 start_output(param.initial_timestep, "out_time.m", "vector_time");
264 start_output(param.initial_timestep, "out_timesteps.m", "vector_timesteps");
265 }
266 if (param.steadystate_tolerance)
267 start_output(param.initial_timestep, "out_changerate.m", "vector_changerate");
268 }
269}
270
272 unsigned int a_step,
273 unsigned int newton_steps,
274 unsigned int krylov_steps,
275 unsigned int tv_sec,
276 unsigned int tv_usec)
277{
278 MeshBase & mesh = es.get_mesh();
279
280 // Query parallel_object_only() methods *outside* if(pid==0)
281 const std::size_t n_active_elem = mesh.n_active_elem();
282 const std::size_t n_active_dofs = es.n_active_dofs();
283
284 if (mesh.processor_id() == 0)
285 {
286 // Write out the number of elements/dofs used
287 std::ofstream activemesh ("out_activemesh.m",
288 std::ios_base::app | std::ios_base::out);
289 activemesh.precision(17);
290 activemesh << (a_step + 1) << ' '
291 << n_active_elem << ' '
292 << n_active_dofs << std::endl;
293
294 // Write out the number of solver steps used
295 std::ofstream solvesteps ("out_solvesteps.m",
296 std::ios_base::app | std::ios_base::out);
297 solvesteps.precision(17);
298 solvesteps << newton_steps << ' '
299 << krylov_steps << std::endl;
300
301 // Write out the clock time
302 std::ofstream clocktime ("out_clocktime.m",
303 std::ios_base::app | std::ios_base::out);
304 clocktime.precision(17);
305 clocktime << tv_sec << '.' << tv_usec << std::endl;
306 }
307}
308
310{
311 // Write footers on output .m files
313 {
314 std::ofstream clocktime ("out_clocktime.m",
315 std::ios_base::app | std::ios_base::out);
316 clocktime << "];" << std::endl;
317
318 if (param.run_simulation)
319 {
320 std::ofstream activemesh ("out_activemesh.m",
321 std::ios_base::app | std::ios_base::out);
322 activemesh << "];" << std::endl;
323
324 std::ofstream solvesteps ("out_solvesteps.m",
325 std::ios_base::app | std::ios_base::out);
326 solvesteps << "];" << std::endl;
327
328 if (param.timesolver_tolerance)
329 {
330 std::ofstream times ("out_time.m",
331 std::ios_base::app | std::ios_base::out);
332 times << "];" << std::endl;
333 std::ofstream timesteps ("out_timesteps.m",
334 std::ios_base::app | std::ios_base::out);
335 timesteps << "];" << std::endl;
336 }
337 if (param.steadystate_tolerance)
338 {
339 std::ofstream changerate ("out_changerate.m",
340 std::ios_base::app | std::ios_base::out);
341 changerate << "];" << std::endl;
342 }
343 }
344
345 // We're done, so write out a file (for e.g. Make to check)
346 std::ofstream complete ("complete");
347 complete << "complete" << std::endl;
348 }
349}
350
351#if defined(LIBMESH_HAVE_GMV) || defined(LIBMESH_HAVE_TECPLOT_API)
353 ErrorVector & error,
354 unsigned int t_number,
355 unsigned int a_number,
356 FEMParameters & param,
357 std::string error_type)
358#else
360 ErrorVector &,
361 unsigned int,
362 unsigned int,
364 std::string)
365#endif
366{
367#ifdef LIBMESH_HAVE_GMV
368 if (param.write_gmv_error)
369 {
370 std::ostringstream error_gmv;
371 error_gmv << "error.gmv."
372 << std::setw(3)
373 << std::setfill('0')
374 << std::right
375 << a_number
376 << "."
377 << std::setw(2)
378 << std::setfill('0')
379 << std::right
380 << t_number
381 << error_type;
382
383 error.plot_error(error_gmv.str(), es.get_mesh());
384 }
385#endif
386
387#ifdef LIBMESH_HAVE_TECPLOT_API
388 if (param.write_tecplot_error)
389 {
390 std::ostringstream error_tecplot;
391 error_tecplot << "error.plt."
392 << std::setw(3)
393 << std::setfill('0')
394 << std::right
395 << a_number
396 << "."
397 << std::setw(2)
398 << std::setfill('0')
399 << std::right
400 << t_number
401 << error_type;
402
403 error.plot_error(error_tecplot.str(), es.get_mesh());
404 }
405#endif
406}
407
408void read_output(EquationSystems & es,
409 unsigned int t_step,
410 unsigned int a_step,
411 std::string solution_type,
412 FEMParameters & param)
413{
414 MeshBase & mesh = es.get_mesh();
415
416 std::string file_name_mesh, file_name_soln;
417 // Look for ASCII files first
418 if (param.output_xda)
419 {
420 file_name_mesh = numbered_filename(t_step, a_step, solution_type, "mesh", "xda", param);
421 file_name_soln = numbered_filename(t_step, a_step, solution_type, "soln", "xda", param);
422 }
423 else if (param.output_xdr)
424 {
425 file_name_mesh = numbered_filename(t_step, a_step, solution_type, "mesh", "xdr", param);
426 file_name_soln = numbered_filename(t_step, a_step, solution_type, "soln", "xdr", param);
427 }
428
429 // Read in the mesh
430 mesh.read(file_name_mesh);
431
432 // And the stored solution
433 es.read(file_name_soln, READ,
437
438 // Put systems in a consistent state
439 for (unsigned int i = 0; i != es.n_systems(); ++i)
440 es.get_system<FEMSystem>(i).update();
441
442 // Figure out the current time
443 Real current_time = 0., current_timestep = 0.;
444
445 if (param.timesolver_tolerance)
446 {
447 std::ifstream times ("out_time.m");
448 std::ifstream timesteps ("out_timesteps.m");
449 if (times.is_open() && timesteps.is_open())
450 {
451 // Read headers
452 const unsigned int headersize = 25;
453 char header[headersize];
454 timesteps.getline (header, headersize);
455 libmesh_error_msg_if(strcmp(header, "vector_timesteps = [") != 0,
456 "Bad header in out_timesteps.m:\n" << header);
457
458 times.getline (header, headersize);
459 libmesh_error_msg_if(strcmp(header, "vector_time = [") != 0,
460 "Bad header in out_time.m:\n" << header);
461
462 // Read each timestep
463 for (unsigned int i = 0; i != t_step; ++i)
464 {
465 libmesh_error_msg_if(!times.good(), "Error: File out_time.m is in non-good state.");
466
467 times >> current_time;
468 timesteps >> current_timestep;
469 }
470 // Remember to increment the last timestep; out_times.m
471 // lists each *start* time
472 current_time += current_timestep;
473 }
474 else
475 libmesh_error_msg("Error opening out_time.m or out_timesteps.m");
476 }
477 else
478 current_time = t_step * param.deltat;
479
480 for (unsigned int i = 0; i != es.n_systems(); ++i)
481 es.get_system<FEMSystem>(i).time = current_time;
482}
483
484void set_system_parameters(FEMSystem & system,
485 FEMParameters & param)
486{
487 // Verify analytic jacobians against numerical ones?
489
490 // More desperate debugging options
492 system.print_solutions = param.print_solutions;
494 system.print_residuals = param.print_residuals;
496 system.print_jacobians = param.print_jacobians;
497
500
501 // Solve this as a time-dependent or steady system
502 if (param.transient)
503 {
504 std::unique_ptr<UnsteadySolver> innersolver;
505 if (param.timesolver_core == "euler2")
506 {
507 auto euler2solver = std::make_unique<Euler2Solver>(system);
508 euler2solver->theta = param.timesolver_theta;
509 innersolver = std::move(euler2solver);
510 }
511 else if (param.timesolver_core == "euler")
512 {
513 auto eulersolver = std::make_unique<EulerSolver>(system);
514 eulersolver->theta = param.timesolver_theta;
515 innersolver = std::move(eulersolver);
516 }
517 else
518 libmesh_error_msg("Don't recognize core TimeSolver type: " << param.timesolver_core);
519
520 if (param.timesolver_tolerance)
521 {
522 system.time_solver = std::make_unique<TwostepTimeSolver>(system);
523 auto timesolver = cast_ptr<TwostepTimeSolver *>(system.time_solver.get());
524
525 timesolver->max_growth = param.timesolver_maxgrowth;
526 timesolver->target_tolerance = param.timesolver_tolerance;
527 timesolver->upper_tolerance = param.timesolver_upper_tolerance;
528 timesolver->component_norm = SystemNorm(param.timesolver_norm);
529 timesolver->core_time_solver = std::move(innersolver);
530 }
531 else
532 system.time_solver = std::move(innersolver);
533 }
534 else
535 system.time_solver = std::make_unique<SteadySolver>(system);
536
537 system.time_solver->reduce_deltat_on_diffsolver_failure =
538 param.deltat_reductions;
539 system.time_solver->quiet = param.time_solver_quiet;
540
541 // Set the time stepping options
542 system.deltat = param.deltat;
543
544 // And the integration options
546
547 // And the nonlinear solver options
548 if (param.use_petsc_snes)
549 {
550#ifdef LIBMESH_HAVE_PETSC
551 system.time_solver->diff_solver() = std::make_unique<PetscDiffSolver>(system);
552#else
553 libmesh_error_msg("This example requires libMesh to be compiled with PETSc support.");
554#endif
555 }
556 else
557 {
558 system.time_solver->diff_solver() = std::make_unique<NewtonSolver>(system);
559 auto solver = cast_ptr<NewtonSolver*>(system.time_solver->diff_solver().get());
560
561 solver->quiet = param.solver_quiet;
562 solver->verbose = !param.solver_quiet;
563 solver->max_nonlinear_iterations = param.max_nonlinear_iterations;
564 solver->minsteplength = param.min_step_length;
565 solver->relative_step_tolerance = param.relative_step_tolerance;
566 solver->absolute_residual_tolerance = param.absolute_residual_tolerance;
567 solver->relative_residual_tolerance = param.relative_residual_tolerance;
568 solver->require_residual_reduction = param.require_residual_reduction;
569 solver->linear_tolerance_multiplier = param.linear_tolerance_multiplier;
570 if (system.time_solver->reduce_deltat_on_diffsolver_failure)
571 {
572 solver->continue_after_max_iterations = true;
573 solver->continue_after_backtrack_failure = true;
574 }
576
577 // And the linear solver options
578 solver->max_linear_iterations = param.max_linear_iterations;
579 solver->initial_linear_tolerance = param.initial_linear_tolerance;
580 solver->minimum_linear_tolerance = param.minimum_linear_tolerance;
581 }
582}
583
584#ifdef LIBMESH_ENABLE_AMR
585
586std::unique_ptr<MeshRefinement> build_mesh_refinement(MeshBase & mesh,
587 FEMParameters & param)
588{
589 auto mesh_refinement = std::make_unique<MeshRefinement>(mesh);
590 mesh_refinement->coarsen_by_parents() = true;
591 mesh_refinement->absolute_global_tolerance() = param.global_tolerance;
592 mesh_refinement->nelem_target() = param.nelem_target;
593 mesh_refinement->refine_fraction() = param.refine_fraction;
594 mesh_refinement->coarsen_fraction() = param.coarsen_fraction;
595 mesh_refinement->coarsen_threshold() = param.coarsen_threshold;
596
597 return mesh_refinement;
598}
599
600#endif // LIBMESH_ENABLE_AMR
601
602// This function builds the Kelly error indicator. This indicator can be used
603// for comparisons of adjoint and non-adjoint based error indicators
604std::unique_ptr<ErrorEstimator> build_error_estimator(FEMParameters & /* param */)
605{
606 return std::make_unique<KellyErrorEstimator>();
607}
608
609// Functions to build the adjoint based error indicators
610// The error_non_pressure and error_pressure contributions are estimated using
611// the build_error_estimator_component_wise function below
612std::unique_ptr<ErrorEstimator>
613build_error_estimator_component_wise (FEMParameters & param,
614 std::vector<std::vector<Real>> & term_weights,
615 std::vector<FEMNormType> & primal_error_norm_type,
616 std::vector<FEMNormType> & dual_error_norm_type)
617{
618 auto adjoint_residual_estimator = std::make_unique<AdjointResidualErrorEstimator>();
619
620 // Both the primal and dual weights are going to be estimated using the patch recovery error estimator
621 adjoint_residual_estimator->primal_error_estimator() = std::make_unique<PatchRecoveryErrorEstimator>();
622 auto p1 = cast_ptr<PatchRecoveryErrorEstimator *>(adjoint_residual_estimator->primal_error_estimator().get());
623
624 adjoint_residual_estimator->dual_error_estimator() = std::make_unique<PatchRecoveryErrorEstimator>();
625 auto p2 = cast_ptr<PatchRecoveryErrorEstimator *>(adjoint_residual_estimator->dual_error_estimator().get());
626
627 // Set the boolean for specifying whether we are reusing patches while building the patch recovery estimates
628 p1->set_patch_reuse(param.patch_reuse);
629 p2->set_patch_reuse(param.patch_reuse);
630
631 // Using the user filled error norm type vector, we pass the type of norm to be used for
632 // the error in each variable, we can have different types of norms for the primal and
633 // dual variables
634 std::size_t size = primal_error_norm_type.size();
635
636 libmesh_assert_equal_to (size, dual_error_norm_type.size());
637 for (unsigned int i = 0; i != size; ++i)
638 {
639 adjoint_residual_estimator->primal_error_estimator()->error_norm.set_type(i, primal_error_norm_type[i]);
640 adjoint_residual_estimator->dual_error_estimator()->error_norm.set_type(i, dual_error_norm_type[i]);
641 }
642
643 // Now we set the right weights for each term in the error estimate, using the user provided
644 // term_weights matrix
645 libmesh_assert_equal_to (size, term_weights.size());
646 for (unsigned int i = 0; i != size; ++i)
647 {
648 libmesh_assert_equal_to (size, term_weights[i].size());
649 adjoint_residual_estimator->error_norm.set_weight(i, term_weights[i][i]);
650 for (unsigned int j = 0; j != size; ++j)
651 if (i != j)
652 adjoint_residual_estimator->error_norm.set_off_diagonal_weight(i, j, term_weights[i][j]);
653 }
654
655 return adjoint_residual_estimator;
656}
657
658// The error_convection_diffusion_x and error_convection_diffusion_y are the nonlinear contributions which
659// are computed using the build_weighted_error_estimator_component_wise below
660std::unique_ptr<ErrorEstimator>
661build_weighted_error_estimator_component_wise (FEMParameters & param,
662 std::vector<std::vector<Real>> & term_weights,
663 std::vector<FEMNormType> & primal_error_norm_type,
664 std::vector<FEMNormType> & dual_error_norm_type,
665 std::vector<FEMFunctionBase<Number> *> coupled_system_weight_functions)
666{
667 auto adjoint_residual_estimator = std::make_unique<AdjointResidualErrorEstimator>();
668
669 // Using the user filled error norm type vector, we pass the type of norm to be used for
670 // the error in each variable, we can have different types of norms for the primal and
671 // dual variables
672 adjoint_residual_estimator->primal_error_estimator() = std::make_unique<WeightedPatchRecoveryErrorEstimator>();
673 auto p1 = cast_ptr<WeightedPatchRecoveryErrorEstimator *>(adjoint_residual_estimator->primal_error_estimator().get());
674
675 adjoint_residual_estimator->dual_error_estimator() = std::make_unique<PatchRecoveryErrorEstimator>();
676 auto p2 = cast_ptr<PatchRecoveryErrorEstimator *>(adjoint_residual_estimator->dual_error_estimator().get());
677
678 p1->set_patch_reuse(param.patch_reuse);
679 p2->set_patch_reuse(param.patch_reuse);
680
681 // This is the critical difference with the build_error_estimate_component_wise
682 p1->weight_functions.clear();
683
684 // We pass the pointers to the user specified weight functions to the patch recovery
685 // error estimator objects declared above
686 std::size_t size = primal_error_norm_type.size();
687
688 libmesh_assert(coupled_system_weight_functions.size() == size);
689 libmesh_assert(dual_error_norm_type.size() == size);
690
691 for (unsigned int i = 0; i != size; ++i)
692 {
693 p1->weight_functions.push_back(coupled_system_weight_functions[i]);
694 adjoint_residual_estimator->primal_error_estimator()->error_norm.set_type(i, primal_error_norm_type[i]);
695 adjoint_residual_estimator->dual_error_estimator()->error_norm.set_type(i, dual_error_norm_type[i]);
696 }
697
698 // Now we set the right weights for each term in the error estimate, using the user provided
699 // term_weights matrix
700 libmesh_assert_equal_to (size, term_weights.size());
701 for (unsigned int i = 0; i != size; ++i)
702 {
703 libmesh_assert_equal_to (size, term_weights[i].size());
704 adjoint_residual_estimator->error_norm.set_weight(i, term_weights[i][i]);
705 for (unsigned int j = 0; j != size; ++j)
706 if (i != j)
707 adjoint_residual_estimator->error_norm.set_off_diagonal_weight(i, j, term_weights[i][j]);
708 }
709
710 return adjoint_residual_estimator;
711}
712
713// The main program.
714int main (int argc, char ** argv)
715{
716 // Initialize libMesh.
717 LibMeshInit init (argc, argv);
718
719 // Skip adaptive examples on a non-adaptive libMesh build
720#ifndef LIBMESH_ENABLE_AMR
721 libmesh_example_requires(false, "--enable-amr");
722#else
723
724 // We use Dirichlet boundary conditions here
725#ifndef LIBMESH_ENABLE_DIRICHLET
726 libmesh_example_requires(false, "--enable-dirichlet");
727#endif
728
729 // This doesn't converge with Eigen BICGSTAB or with Trilinos for some reason...
730 libmesh_example_requires(libMesh::default_solver_package() == PETSC_SOLVERS, "--enable-petsc");
731
732 libMesh::out << "Started " << argv[0] << std::endl;
733
734 // Make sure the general input file exists, and parse it
735 {
736 std::ifstream i("general.in");
737 libmesh_error_msg_if(!i, '[' << init.comm().rank() << "] Can't find general.in; exiting early.");
738 }
739
740 // Read in parameters from the input file
741 GetPot infile("general.in");
742
743 // But allow the command line to override it.
744 infile.parse_command_line(argc, argv);
745
746 FEMParameters param(init.comm());
747 param.read(infile);
748
749 // Skip higher-dimensional examples on a lower-dimensional libMesh build
750 libmesh_example_requires(2 <= LIBMESH_DIM, "2D support");
751
752 // Create a mesh with the given dimension, distributed
753 // across the default MPI communicator.
754 Mesh mesh(init.comm(), cast_int<unsigned char>(param.dimension));
755
756 // And an object to refine it
757 std::unique_ptr<MeshRefinement> mesh_refinement =
759
760 // And an EquationSystems to run on it
761 EquationSystems equation_systems (mesh);
762
763 libMesh::out << "Building mesh" << std::endl;
764
765 if (!param.initial_timestep && param.run_simulation)
766 build_domain(mesh, param);
767
768 libMesh::out << "Building system" << std::endl;
769
770 FEMSystem & system = build_system(equation_systems, infile, param);
771
772 set_system_parameters(system, param);
773
774 libMesh::out << "Initializing systems" << std::endl;
775
776 // Create a QoI object, we will need this to compute the QoI
777 {
779 // Our QoI is computed on the side
780 qoi.assemble_qoi_sides = true;
781 system.attach_qoi(&qoi);
782 }
783
784 equation_systems.init ();
785
786 // Print information about the mesh and system to the screen.
788 equation_systems.print_info();
789
790 libMesh::out << "Starting adaptive loop" << std::endl << std::endl;
791
792 // Count the number of steps used
793 unsigned int a_step = 0;
794
795 // Get the linear solver object to set the preconditioner reuse flag
796 LinearSolver<Number> * linear_solver = system.get_linear_solver();
797
798 // Adaptively solve the timestep
799 for (; a_step <= param.max_adaptivesteps; ++a_step)
800 {
801 // We have to ensure that we are refining to either an error
802 // tolerance or to a target number of elements, and, not to a
803 // non-zero tolerance and a target number of elements
804 // simultaneously
805 if (param.global_tolerance > 0 && param.nelem_target > 0)
806 {
807 libMesh::out<<"We cant refine to both a non-zero tolerance and a target number of elements, EXITING adaptive loop. "<<std::endl<<std::endl;
808 break;
809 }
810
811 // We dont want to reuse the preconditioner for the forward solve
812 linear_solver->reuse_preconditioner(false);
813
814 libMesh::out << "Adaptive step " << a_step << std::endl;
815
816 libMesh::out << "Solving the forward problem" << std::endl;
817
818 libMesh::out << "We have "
820 << " active elements and "
821 << equation_systems.n_active_dofs()
822 << " active dofs."
823 << std::endl
824 << std::endl;
825
826 // Solve the forward system
827 system.solve();
828
829 // Write the output
830 write_output(equation_systems, 0, a_step, "primal", param);
831
832 // Compute the QoI
833 system.assemble_qoi();
834
835 // We just call a postprocess here to set the variable computed_QoI to the value computed by assemble_qoi
836 system.postprocess();
837
838 // Get the value of the computed_QoI variable of the CoupledSystem class
839 Number QoI_0_computed = (dynamic_cast<CoupledSystem &>(system)).get_QoI_value();
840
841 libMesh::out << "The boundary QoI is "
842 << std::setprecision(17)
843 << QoI_0_computed
844 << std::endl
845 << std::endl;
846
847 // Hard coded assert to ensure that the actual numbers we are getting are what they should be
848 if (a_step == param.max_adaptivesteps)
849 libmesh_assert_less(std::abs(QoI_0_computed - 0.0833), 2.5e-4);
850
851 // You dont need to compute error estimates and refine at the last
852 // adaptive step, only before that
853 if (a_step!=param.max_adaptivesteps)
854 {
855 NumericVector<Number> & primal_solution = (*system.solution);
856
857 // Make sure we get the contributions to the adjoint RHS from the sides
858 system.assemble_qoi_sides = true;
859
860 // We are about to solve the adjoint system, but before we
861 // do this we see the same preconditioner flag to reuse the
862 // preconditioner from the forward solver
863 linear_solver->reuse_preconditioner(param.reuse_preconditioner);
864
865 // Solve the adjoint system
866 libMesh::out<< "Solving the adjoint problem" <<std::endl;
867 system.adjoint_solve();
868
869 // Now that we have solved the adjoint, set the adjoint_already_solved boolean to true, so we dont solve unnecessarily in the error estimator
870 system.set_adjoint_already_solved(true);
871
872 // To plot the adjoint solution, we swap it with the primal solution
873 // and use the write_output function
874 NumericVector<Number> & dual_solution = system.get_adjoint_solution();
875 primal_solution.swap(dual_solution);
876
877 write_output(equation_systems, 0, a_step, "adjoint", param);
878
879 // Swap back
880 primal_solution.swap(dual_solution);
881
882 // We need the values of the parameters Pe from the
883 // system for the adjoint error estimate
884 Real Pe = (dynamic_cast<CoupledSystem &>(system)).get_Pe();
885
886 // The total error is the sum: error = error_non_pressure +
887 // error_with_pressure + ...
888 // error_estimator_convection_diffusion_x +
889 // error_estimator_convection_diffusion_y
890 ErrorVector error;
891
892 // We first construct the non-pressure contributions
893 ErrorVector error_non_pressure;
894
895 // First we build the norm_type_vector_non_pressure vectors and
896 // weights_matrix_non_pressure matrix for the non-pressure term
897 // error contributions
898 std::vector<FEMNormType> primal_norm_type_vector_non_pressure;
899 primal_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
900 primal_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
901 primal_norm_type_vector_non_pressure.push_back(L2);
902 primal_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
903
904 std::vector<FEMNormType> dual_norm_type_vector_non_pressure;
905 dual_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
906 dual_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
907 dual_norm_type_vector_non_pressure.push_back(L2);
908 dual_norm_type_vector_non_pressure.push_back(H1_SEMINORM);
909
910 std::vector<std::vector<Real>>
911 weights_matrix_non_pressure(system.n_vars(),
912 std::vector<Real>(system.n_vars(), 0.0));
913 weights_matrix_non_pressure[0][0] = 1.;
914 weights_matrix_non_pressure[1][1] = 1.;
915 weights_matrix_non_pressure[3][3] = 1./Pe;
916
917 // We build the error estimator to estimate the contributions
918 // to the QoI error from the non pressure term
919 std::unique_ptr<ErrorEstimator> error_estimator_non_pressure =
920 build_error_estimator_component_wise (param,
921 weights_matrix_non_pressure,
922 primal_norm_type_vector_non_pressure,
923 dual_norm_type_vector_non_pressure);
924
925 // Estimate the contributions to the QoI error from the non
926 // pressure terms
927 error_estimator_non_pressure->estimate_error(system, error_non_pressure);
928
929 // Plot the estimated error from the non_pressure terms
930 write_error(equation_systems, error_non_pressure, 0, a_step, param, "_non_pressure");
931
932 // Now for the pressure contributions
933 ErrorVector error_with_pressure;
934
935 // Next we build the norm_type_vector_with_pressure vectors and
936 // weights_matrix_with_pressure matrix for the pressure term
937 // error contributions
938 std::vector<FEMNormType> primal_norm_type_vector_with_pressure;
939 primal_norm_type_vector_with_pressure.push_back(H1_X_SEMINORM);
940 primal_norm_type_vector_with_pressure.push_back(H1_Y_SEMINORM);
941 primal_norm_type_vector_with_pressure.push_back(L2);
942 primal_norm_type_vector_with_pressure.push_back(L2);
943
944 std::vector<FEMNormType> dual_norm_type_vector_with_pressure;
945 dual_norm_type_vector_with_pressure.push_back(H1_X_SEMINORM);
946 dual_norm_type_vector_with_pressure.push_back(H1_Y_SEMINORM);
947 dual_norm_type_vector_with_pressure.push_back(L2);
948 dual_norm_type_vector_with_pressure.push_back(L2);
949
950 std::vector<std::vector<Real>>
951 weights_matrix_with_pressure (system.n_vars(),
952 std::vector<Real>(system.n_vars(), 0.0));
953 weights_matrix_with_pressure[0][2] = 1.;
954 weights_matrix_with_pressure[1][2] = 1.;
955 weights_matrix_with_pressure[2][0] = 1.;
956 weights_matrix_with_pressure[2][1] = 1.;
957
958 // We build the error estimator to estimate the contributions
959 // to the QoI error from the pressure term
960 std::unique_ptr<ErrorEstimator> error_estimator_with_pressure =
961 build_error_estimator_component_wise (param,
962 weights_matrix_with_pressure,
963 primal_norm_type_vector_with_pressure,
964 dual_norm_type_vector_with_pressure);
965
966 // Estimate the contributions to the QoI error from the pressure terms
967 error_estimator_with_pressure->estimate_error(system, error_with_pressure);
968
969 // Plot the error due to the pressure terms
970 write_error(equation_systems, error_with_pressure, 0, a_step, param, "_with_pressure");
971
972 // Now for the convection diffusion term errors (in the x and y directions)
973
974 ErrorVector error_convection_diffusion_x;
975
976 // The norm type vectors and weights matrix for the convection_diffusion_x errors
977 std::vector<FEMNormType> primal_norm_type_vector_convection_diffusion_x;
978 primal_norm_type_vector_convection_diffusion_x.push_back(L2);
979 primal_norm_type_vector_convection_diffusion_x.push_back(L2);
980 primal_norm_type_vector_convection_diffusion_x.push_back(L2);
981 primal_norm_type_vector_convection_diffusion_x.push_back(H1_X_SEMINORM);
982
983 std::vector<FEMNormType> dual_norm_type_vector_convection_diffusion_x;
984 dual_norm_type_vector_convection_diffusion_x.push_back(L2);
985 dual_norm_type_vector_convection_diffusion_x.push_back(L2);
986 dual_norm_type_vector_convection_diffusion_x.push_back(L2);
987 // Note that we need the error of the dual concentration in L2
988 dual_norm_type_vector_convection_diffusion_x.push_back(L2);
989
990 std::vector<std::vector<Real>>
991 weights_matrix_convection_diffusion_x (system.n_vars(),
992 std::vector<Real>(system.n_vars(), 0.0));
993 weights_matrix_convection_diffusion_x[0][3] = 1.;
994 weights_matrix_convection_diffusion_x[3][3] = 1.;
995
996 // We will also have to build and pass the weight functions to the weighted patch recovery estimators
997
998 // We pass the identity function as weights to error entries that the above matrix will scale to 0.
999 ConstFEMFunction<Number> identity(1);
1000
1001 // Declare object of class CoupledFEMFunctionsx, the definition of the function contains the weight
1002 // to be applied to the relevant terms
1003 // For ||e(u1 C,1_h)||_{L2} ||e(C^*)||_{L2} term, returns C,1_h
1004 CoupledFEMFunctionsx convdiffx0(system, 0);
1005 // For ||e((u_1)_h C,1)||_{L2} ||e(C^*)||_{L2} term, returns (u_1)_h
1006 CoupledFEMFunctionsx convdiffx3(system, 3);
1007
1008 // Make a vector of pointers to these objects
1009 std::vector<FEMFunctionBase<Number> *> coupled_system_weight_functions_x;
1010 coupled_system_weight_functions_x.push_back(&convdiffx0);
1011 coupled_system_weight_functions_x.push_back(&identity);
1012 coupled_system_weight_functions_x.push_back(&identity);
1013 coupled_system_weight_functions_x.push_back(&convdiffx3);
1014
1015 // Build the error estimator to estimate the contributions
1016 // to the QoI error from the convection diffusion x term
1017 std::unique_ptr<ErrorEstimator> error_estimator_convection_diffusion_x =
1018 build_weighted_error_estimator_component_wise (param,
1019 weights_matrix_convection_diffusion_x,
1020 primal_norm_type_vector_convection_diffusion_x,
1021 dual_norm_type_vector_convection_diffusion_x,
1022 coupled_system_weight_functions_x);
1023
1024 // Estimate the contributions to the QoI error from the
1025 // convection diffusion x term
1026 error_estimator_convection_diffusion_x->estimate_error(system, error_convection_diffusion_x);
1027
1028 // Plot this error
1029 write_error (equation_systems,
1030 error_convection_diffusion_x,
1031 0,
1032 a_step,
1033 param,
1034 "_convection_diffusion_x");
1035
1036 // Now for the y direction terms
1037 ErrorVector error_convection_diffusion_y;
1038
1039 // The norm type vectors and weights matrix for the convection_diffusion_x errors
1040 std::vector<FEMNormType> primal_norm_type_vector_convection_diffusion_y;
1041 primal_norm_type_vector_convection_diffusion_y.push_back(L2);
1042 primal_norm_type_vector_convection_diffusion_y.push_back(L2);
1043 primal_norm_type_vector_convection_diffusion_y.push_back(L2);
1044 primal_norm_type_vector_convection_diffusion_y.push_back(H1_Y_SEMINORM);
1045
1046 std::vector<FEMNormType> dual_norm_type_vector_convection_diffusion_y;
1047 dual_norm_type_vector_convection_diffusion_y.push_back(L2);
1048 dual_norm_type_vector_convection_diffusion_y.push_back(L2);
1049 dual_norm_type_vector_convection_diffusion_y.push_back(L2);
1050 // Note that we need the error of the dual concentration in L2
1051 dual_norm_type_vector_convection_diffusion_y.push_back(L2);
1052
1053 std::vector<std::vector<Real>>
1054 weights_matrix_convection_diffusion_y (system.n_vars(),
1055 std::vector<Real>(system.n_vars(), 0.0));
1056 weights_matrix_convection_diffusion_y[1][3] = 1.;
1057 weights_matrix_convection_diffusion_y[3][3] = 1.;
1058
1059 // For ||e(u2 C,2_h)||_{L2} ||e(C^*)||_{L2} term, returns C,2_h
1060 CoupledFEMFunctionsy convdiffy1(system, 1);
1061 // For ||e((u_2)_h C,2)||_{L2} ||e(C^*)||_{L2} term, returns (u_2)_h
1062 CoupledFEMFunctionsy convdiffy3(system, 3);
1063
1064 // Make a vector of pointers to these objects
1065 std::vector<FEMFunctionBase<Number> *> coupled_system_weight_functions_y;
1066 coupled_system_weight_functions_y.push_back(&identity);
1067 coupled_system_weight_functions_y.push_back(&convdiffy1);
1068 coupled_system_weight_functions_y.push_back(&identity);
1069 coupled_system_weight_functions_y.push_back(&convdiffy3);
1070
1071 // Build the error estimator to estimate the contributions
1072 // to the QoI error from the convection diffusion y term
1073 std::unique_ptr<ErrorEstimator> error_estimator_convection_diffusion_y =
1074 build_weighted_error_estimator_component_wise (param,
1075 weights_matrix_convection_diffusion_y,
1076 primal_norm_type_vector_convection_diffusion_y,
1077 dual_norm_type_vector_convection_diffusion_y,
1078 coupled_system_weight_functions_y);
1079
1080 // Estimate the contributions to the QoI error from the
1081 // convection diffusion y terms
1082 error_estimator_convection_diffusion_y->estimate_error(system, error_convection_diffusion_y);
1083
1084 // Plot this error
1085 write_error(equation_systems, error_convection_diffusion_y, 0, a_step, param, "_convection_diffusion_y");
1086
1087 if (param.indicator_type == "adjoint_residual")
1088 {
1089 error.resize(error_non_pressure.size());
1090
1091 // Now combine the contribs from the pressure and non
1092 // pressure terms to get the complete estimate
1093 for (std::size_t i = 0; i < error.size(); i++)
1094 error[i] = error_non_pressure[i] + error_with_pressure[i] + error_convection_diffusion_x[i] + error_convection_diffusion_y[i];
1095 }
1096 else
1097 {
1098 libMesh::out << "Using Kelly Estimator" << std::endl;
1099
1100 // Build the Kelly error estimator
1101 std::unique_ptr<ErrorEstimator> error_estimator = build_error_estimator(param);
1102
1103 // Estimate the error
1104 error_estimator->estimate_error(system, error);
1105 }
1106
1107 write_error(equation_systems, error, 0, a_step, param, "_total");
1108
1109 // We have to refine either based on reaching an error
1110 // tolerance or a number of elements target, which should be
1111 // verified above
1112
1113 // Otherwise we flag elements by error tolerance or nelem
1114 // target
1115
1116 if (param.refine_uniformly)
1117 {
1118 mesh_refinement->uniformly_refine(1);
1119 }
1120 else if (param.global_tolerance >= 0. && param.nelem_target == 0.) // Refine based on reaching an error tolerance
1121 {
1122 mesh_refinement->flag_elements_by_error_tolerance (error);
1123
1124 // Carry out the adaptive mesh refinement/coarsening
1125 mesh_refinement->refine_and_coarsen_elements();
1126 }
1127 else // Refine based on reaching a target number of elements
1128 {
1129 //If we have reached the desired number of elements, we
1130 //dont do any more adaptive steps
1131 if (mesh.n_active_elem() >= param.nelem_target)
1132 {
1133 libMesh::out << "We reached the target number of elements." << std::endl <<std::endl;
1134 break;
1135 }
1136
1137 mesh_refinement->flag_elements_by_nelem_target (error);
1138
1139 // Carry out the adaptive mesh refinement/coarsening
1140 mesh_refinement->refine_and_coarsen_elements();
1141 }
1142
1143 equation_systems.reinit();
1144 }
1145 }
1146
1147 write_output_footers(param);
1148
1149#endif // #ifndef LIBMESH_ENABLE_AMR
1150
1151 // All done.
1152 return 0;
1153
1154}
void set_system_parameters(LaplaceSystem &system, FEMParameters &param)
std::unique_ptr< MeshRefinement > build_mesh_refinement(MeshBase &mesh, const FEMParameters &param)
std::unique_ptr< ErrorEstimator > build_error_estimator(const FEMParameters &param, const QoISet &qois)
void write_error(EquationSystems &es, ErrorVector &error, unsigned int t_number, unsigned int a_number, FEMParameters &param, std::string error_type) void write_error(EquationSystems &
void write_output_headers(FEMParameters &param)
void write_output_footers(FEMParameters &param)
void write_output(EquationSystems &es, unsigned int t_step, unsigned int a_step, std::string solution_type, FEMParameters &param)
void write_output_solvedata(EquationSystems &es, unsigned int a_step, unsigned int newton_steps, unsigned int krylov_steps, unsigned int tv_sec, unsigned int tv_usec)
std::string numbered_filename(unsigned int t_step, unsigned int a_step, std::string solution_type, std::string type, std::string extension, FEMParameters &param)
bool write_tecplot_error
double minimum_linear_tolerance
double initial_linear_tolerance
unsigned int max_adaptivesteps
libMesh::Real timesolver_theta
double linear_tolerance_multiplier
libMesh::Real deltat
libMesh::Real refine_fraction
libMesh::Real timesolver_tolerance
libMesh::Real steadystate_tolerance
libMesh::Real verify_analytic_jacobians
unsigned int max_nonlinear_iterations
libMesh::Real timesolver_maxgrowth
libMesh::Real global_tolerance
std::string indicator_type
bool print_element_residuals
libMesh::Real min_step_length
libMesh::Real timesolver_upper_tolerance
std::string timesolver_core
unsigned int initial_timestep
unsigned int dimension
libMesh::Real relative_residual_tolerance
bool print_residual_norms
libMesh::Real absolute_residual_tolerance
bool print_jacobian_norms
std::vector< libMesh::FEMNormType > timesolver_norm
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
libMesh::Real coarsen_threshold
bool print_solution_norms
unsigned int deltat_reductions
bool reuse_preconditioner
bool print_element_solutions
FEMFunction that returns a single value, regardless of the time and location inputs.
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 print_residuals
Set print_residuals to true to print F whenever it is assembled.
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time.
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...
void attach_qoi(DifferentiableQoI *qoi_in)
Attach external QoI object.
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_element_solutions
Set print_element_solutions to true to print each U_elem input.
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_element_residuals
Set print_element_residuals to true to print each R_elem contribution.
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.
std::size_t n_active_dofs() const
void write(std::string_view name, const XdrMODE, const unsigned int write_flags=(WRITE_DATA), bool partition_agnostic=true) const
Write the systems to disk using the XDR data format.
unsigned int n_systems() const
void read(std::string_view name, const XdrMODE, const unsigned int read_flags=(READ_HEADER|READ_DATA), bool partition_agnostic=true)
Read & initialize the systems from disk using the XDR data format.
const MeshBase & get_mesh() const
const T_sys & get_system(std::string_view name) const
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
void plot_error(const std::string &filename, const MeshBase &mesh, const std::string &data_type="error") const
Plots a data file, of a type determined by looking at the file extension in filename,...
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.
FEMFunctionBase is a base class from which users can derive in order to define "function-like" object...
This class provides a specific system class.
Definition fem_system.h:55
virtual void solve() override
Invokes the solver associated with the system.
virtual void assemble_qoi(const QoISet &indices=QoISet()) override
Runs a qoi assembly loop over all elements, and if assemble_qoi_sides is true over all sides.
virtual void postprocess() override
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides.
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
virtual void renumber_nodes_and_elements()=0
After partitioning a mesh it is useful to renumber the nodes and elements so that they lie in contigu...
virtual void write(const std::string &name) const =0
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
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
This class defines a norm/seminorm to be applied to a NumericVector which contains coefficients in a ...
Definition system_norm.h:50
int extra_quadrature_order
A member int that can be employed to indicate increased or reduced quadrature order.
Definition system.h:1640
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean.
Definition system.h:417
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
Definition system.h:1677
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition system.C:498
unsigned int n_vars() const
Definition system.C:2674
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
Definition system.C:1232
This class implements writing meshes in the Tecplot format.
Definition tecplot_io.h:44
void build_domain(MeshBase &mesh, FEMParameters &param)
Definition domain.C:10
MeshBase & mesh
FEMSystem & build_system(EquationSystems &es, GetPot &, FEMParameters &)
Definition mysystems.h:7
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
The libMesh namespace provides an interface to certain functionality in the library.
processor_id_type global_processor_id()
SolverPackage default_solver_package()
Definition libmesh.C:1064
libmesh_assert(ctx)
OStreamProxy out
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void start_output(unsigned int timesteps, std::string filename, std::string varname)
Definition output.C:14
int main()