libMesh
adjoints_ex3.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 // <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
113 using namespace libMesh;
114 
115 // Number output files
116 
117 std::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.
251  if (libMesh::global_processor_id() != 0)
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
312  if (libMesh::global_processor_id() == 0)
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)
352 void write_error(EquationSystems & es,
353  ErrorVector & error,
354  unsigned int t_number,
355  unsigned int a_number,
356  FEMParameters & param,
357  std::string error_type)
358 #else
361  unsigned int,
362  unsigned int,
363  FEMParameters &,
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 
408 void 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 
484 void 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 
586 std::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
604 std::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
612 std::unique_ptr<ErrorEstimator>
613 build_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
660 std::unique_ptr<ErrorEstimator>
661 build_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.
714 int 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 =
758  build_mesh_refinement(mesh, param);
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  {
778  CoupledSystemQoI qoi;
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.
787  mesh.print_info();
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 "
819  << mesh.n_active_elem()
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 }
unsigned int nelem_target
Definition: femparameters.h:60
libMesh::Real timesolver_upper_tolerance
Definition: femparameters.h:39
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
Definition: system.h:1615
bool print_solution_norms
void start_output(unsigned int timesteps, std::string filename, std::string varname)
Definition: output.C:14
libMesh::Real deltat
Definition: femparameters.h:39
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.
unsigned int initial_timestep
Definition: femparameters.h:34
bool print_element_residuals
unsigned int dimension
Definition: femparameters.h:46
void write_output_headers(FEMParameters &param)
Definition: adjoints_ex3.C:248
virtual dof_id_type n_active_elem() const =0
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
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
bool reuse_preconditioner
libMesh::Real timesolver_tolerance
Definition: femparameters.h:39
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean.
Definition: system.h:415
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
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
int extra_quadrature_order
A member int that can be employed to indicate increased or reduced quadrature order.
Definition: system.h:1578
std::string timesolver_core
Definition: femparameters.h:37
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
MeshBase & mesh
bool print_residual_norms
libMesh::Real timesolver_maxgrowth
Definition: femparameters.h:39
std::string numbered_filename(unsigned int t_step, unsigned int a_step, std::string solution_type, std::string type, std::string extension, FEMParameters &param)
Definition: adjoints_ex3.C:117
libMesh::Real relative_step_tolerance
std::string indicator_type
This class defines a norm/seminorm to be applied to a NumericVector which contains coefficients in a ...
Definition: system_norm.h:49
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
void set_system_parameters(LaplaceSystem &system, FEMParameters &param)
Definition: adjoints_ex1.C:163
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled.
Definition: diff_system.h:366
const T_sys & get_system(std::string_view name) const
This class provides a specific system class.
Definition: fem_system.h:53
This is the MeshBase class.
Definition: mesh_base.h:75
bool print_element_residuals
Set print_element_residuals to true to print each R_elem contribution.
Definition: diff_system.h:376
bool print_element_solutions
Set print_element_solutions to true to print each U_elem input.
Definition: diff_system.h:371
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
bool write_gmv_error
Definition: femparameters.h:69
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
std::unique_ptr< ErrorEstimator > build_error_estimator(const FEMParameters &param, const QoISet &qois)
Definition: adjoints_ex1.C:250
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time...
Definition: diff_system.h:280
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
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.
libmesh_assert(ctx)
unsigned int max_adaptivesteps
Definition: femparameters.h:63
double initial_linear_tolerance
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.
int extra_quadrature_order
libMesh::Real global_tolerance
Definition: femparameters.h:61
void attach_qoi(DifferentiableQoI *qoi_in)
Attach external QoI object.
Definition: diff_system.C:279
void read(GetPot &input, const std::vector< std::string > *other_variable_names=nullptr)
std::unique_ptr< MeshRefinement > build_mesh_refinement(MeshBase &mesh, const FEMParameters &param)
Definition: adjoints_ex1.C:227
libMesh::Real absolute_residual_tolerance
void plot_error(const std::string &filename, const MeshBase &mesh) const
Plots a data file, of a type determined by looking at the file extension in filename, of the error values on the active elements of mesh.
Definition: error_vector.C:210
virtual void postprocess() override
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides...
Definition: fem_system.C:1127
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
void write_output_footers(FEMParameters &param)
Definition: adjoints_ex3.C:309
virtual void write(const std::string &name) const =0
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition: system.C:510
bool print_element_solutions
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...
Definition: fem_system.C:1147
void build_domain(MeshBase &mesh, FEMParameters &param)
Definition: domain.C:10
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual LinearSolver< Number > * get_linear_solver() const override
Definition: diff_system.C:163
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)
Definition: adjoints_ex3.C:271
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
FEMSystem & build_system(EquationSystems &es, GetPot &, FEMParameters &)
Definition: mysystems.h:7
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
processor_id_type global_processor_id()
Definition: libmesh_base.h:85
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 &
const MeshBase & get_mesh() const
libMesh::Real min_step_length
std::size_t n_active_dofs() const
libMesh::Real timesolver_theta
Definition: femparameters.h:39
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
This class implements writing meshes in the Tecplot format.
Definition: tecplot_io.h:43
FEMFunction that returns a single value, regardless of the time and location inputs.
void write_output(EquationSystems &es, unsigned int t_step, unsigned int a_step, std::string solution_type, FEMParameters &param)
Definition: adjoints_ex3.C:149
bool time_solver_quiet
unsigned int n_vars() const
Definition: system.h:2430
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
std::vector< libMesh::FEMNormType > timesolver_norm
Definition: femparameters.h:42
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 renumber_nodes_and_elements()=0
After partitioning a mesh it is useful to renumber the nodes and elements so that they lie in contigu...
bool write_tecplot_error
Definition: femparameters.h:69
libMesh::Real coarsen_fraction
Definition: femparameters.h:62
int main(int argc, char **argv)
libMesh::Real steadystate_tolerance
Definition: femparameters.h:39
unsigned int deltat_reductions
Definition: femparameters.h:36