44 #include "adjoint_initial.h"    45 #include "femparameters.h"    46 #include "heatsystem.h"    50 #include "libmesh/equation_systems.h"    51 #include "libmesh/dirichlet_boundaries.h"    52 #include "libmesh/system_norm.h"    53 #include "libmesh/numeric_vector.h"    54 #include "libmesh/enum_solver_package.h"    56 #include "libmesh/mesh.h"    57 #include "libmesh/mesh_generation.h"    58 #include "libmesh/mesh_refinement.h"    60 #include "libmesh/petsc_diff_solver.h"    61 #include "libmesh/steady_solver.h"    62 #include "libmesh/euler_solver.h"    63 #include "libmesh/euler2_solver.h"    64 #include "libmesh/newton_solver.h"    65 #include "libmesh/petsc_diff_solver.h"    66 #include "libmesh/twostep_time_solver.h"    68 #include "libmesh/getpot.h"    69 #include "libmesh/tecplot_io.h"    70 #include "libmesh/gmv_io.h"    71 #include "libmesh/exodusII_io.h"    73 #include "libmesh/adjoint_refinement_estimator.h"    74 #include "libmesh/error_vector.h"    77 #include "libmesh/solution_history.h"    78 #include "libmesh/memory_solution_history.h"    79 #include "libmesh/file_solution_history.h"    89                   std::string solution_type, 
    95 #ifdef LIBMESH_HAVE_GMV    98       MeshBase & 
mesh = es.get_mesh();
   100       std::ostringstream file_name_gmv;
   101       file_name_gmv << solution_type
   108       GMVIO(
mesh).write_equation_systems(file_name_gmv.str(), es);
   112 #ifdef LIBMESH_HAVE_EXODUS_API   115       MeshBase & 
mesh = es.get_mesh();
   125       std::ostringstream file_name_exodus;
   127       file_name_exodus << solution_type << 
".e";
   129         file_name_exodus << 
"-s"   136       ExodusII_IO(
mesh).write_timestep(file_name_exodus.str(),
   166       std::unique_ptr<UnsteadySolver> innersolver;
   169           auto euler2solver = std::make_unique<Euler2Solver>(system);
   171           innersolver = std::move(euler2solver);
   175           auto eulersolver = std::make_unique<EulerSolver>(system);
   177           innersolver = std::move(eulersolver);
   180         libmesh_error_msg(
"This example (and unsteady adjoints in libMesh) only support Backward Euler and explicit methods.");
   184           system.
time_solver = std::make_unique<TwostepTimeSolver>(system);
   185           auto timesolver = cast_ptr<TwostepTimeSolver *>(system.
time_solver.get());
   191           timesolver->core_time_solver = std::move(innersolver);
   196             MemorySolutionHistory heatsystem_solution_history(system);
   197             system.
time_solver->set_solution_history(heatsystem_solution_history);
   201             FileSolutionHistory heatsystem_solution_history(system);
   202             system.
time_solver->set_solution_history(heatsystem_solution_history);
   214           MemorySolutionHistory heatsystem_solution_history(system);
   215           system.
time_solver->set_solution_history(heatsystem_solution_history);
   219           FileSolutionHistory heatsystem_solution_history(system);
   220           system.
time_solver->set_solution_history(heatsystem_solution_history);
   227     system.
time_solver = std::make_unique<SteadySolver>(system);
   232  #ifdef LIBMESH_ENABLE_DIRICHLET   235     std::map<boundary_id_type, FunctionBase<Number> *>::
   242       FunctionBase<Number> *f = i->second;
   248       libMesh::out << 
"Added Dirichlet boundary " << b << 
" for variables ";
   253  #endif // LIBMESH_ENABLE_DIRICHLET   264 #ifdef LIBMESH_HAVE_PETSC   265       system.
time_solver->diff_solver() = std::make_unique<PetscDiffSolver>(system);
   267       libmesh_error_msg(
"This example requires libMesh to be compiled with PETSc support.");
   272       system.
time_solver->diff_solver() = std::make_unique<NewtonSolver>(system);
   273       auto solver = cast_ptr<NewtonSolver*>(system.
time_solver->diff_solver().get());
   283       if (system.
time_solver->reduce_deltat_on_diffsolver_failure)
   285           solver->continue_after_max_iterations = 
true;
   286           solver->continue_after_backtrack_failure = 
true;
   297 #ifdef LIBMESH_ENABLE_AMR   298 std::unique_ptr<AdjointRefinementEstimator>
   301   std::cout<<
"Computing the error estimate using the Adjoint Refinement Error Estimator"<<std::endl<<std::endl;
   303   auto adjoint_refinement_estimator = std::make_unique<AdjointRefinementEstimator>();
   305   adjoint_refinement_estimator->qoi_set() = qois;
   309   adjoint_refinement_estimator->set_residual_evaluation_physics(supplied_physics);
   312   adjoint_refinement_estimator->set_adjoint_evaluation_physics(supplied_physics);
   316   adjoint_refinement_estimator->number_h_refinements = 0;
   318   return adjoint_refinement_estimator;
   320 #endif // LIBMESH_ENABLE_AMR   323 int main (
int argc, 
char ** argv)
   326 #ifndef LIBMESH_ENABLE_AMR   328   libmesh_example_requires(
false, 
"--enable-amr");
   331   libmesh_example_requires(2 <= LIBMESH_DIM, 
"2D support");
   334 #ifndef LIBMESH_ENABLE_DIRICHLET   335   libmesh_example_requires(
false, 
"--enable-dirichlet");
   339   LibMeshInit 
init (argc, argv);
   348     std::ifstream i(
"general.in");
   349     libmesh_error_msg_if(!i, 
'[' << 
init.comm().rank() << 
"] Can't find general.in; exiting early.");
   351   GetPot infile(
"general.in");
   354   infile.parse_command_line(argc, argv);
   362   Mesh 
mesh(
init.comm(), cast_int<unsigned char>(param.dimension));
   365   auto mesh_refinement = std::make_unique<MeshRefinement>(
mesh);
   368   EquationSystems equation_systems (
mesh);
   375   if (param.elementtype == 
"tri" ||
   376       param.elementtype == 
"unstructured")
   382                                        param.domain_xmin, param.domain_xmin + param.domain_edge_width,
   383                                        param.domain_ymin, param.domain_ymin + param.domain_edge_length,
   393   auto sigma_physics = std::make_unique<SigmaPhysics>();
   394   sigma_physics->init_data(system);
   399   equation_systems.init ();
   402   for (
unsigned int i=0; i != param.extrarefinements; ++i)
   404       mesh_refinement->uniformly_refine(1);
   405       equation_systems.reinit();
   408   libMesh::out << 
"Setting primal initial conditions" << std::endl;
   411                           equation_systems.parameters);
   432   equation_systems.print_info();
   435   Number QoI_1_accumulated = 0.0;
   440 #if defined(NDEBUG) && defined(LIBMESH_ENABLE_EXCEPTIONS)   446       for (
unsigned int t_step=param.initial_timestep;
   447            t_step != param.initial_timestep + param.n_timesteps; ++t_step)
   467           libMesh::out << 
"Advancing timestep" << std::endl << std::endl;
   471           write_output(equation_systems, t_step+1, 
"primal", param);
   476       (
dynamic_cast<HeatSystem &
>(system).QoI_time_instant)[0] = system.
time;
   485       QoI_1_accumulated = 0.0;
   487       for (
unsigned int t_step=param.initial_timestep;
   488            t_step != param.initial_timestep + param.n_timesteps; ++t_step)
   495       std::cout<< 
"The computed QoI 0 is " << std::setprecision(17) << system.
get_qoi_value(0) << std::endl;
   496       std::cout<< 
"The computed QoI 1 is " << std::setprecision(17) << QoI_1_accumulated << std::endl;
   501       libMesh::out << std::endl << 
"Solving the adjoint problems." << std::endl;
   508       const std::string & adjoint_solution_name0 = 
"adjoint_solution0";
   509       const std::string & adjoint_solution_name1 = 
"adjoint_solution1";
   510       const std::string & old_adjoint_solution_name0 = 
"_old_adjoint_solution0";
   511       const std::string & old_adjoint_solution_name1 = 
"_old_adjoint_solution1";
   528                             equation_systems.parameters,
   567                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   574                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   589       primal_solution.
swap(dual_solution_0);
   591       write_output(equation_systems, param.n_timesteps, 
"dual0", param);
   594       primal_solution.swap(dual_solution_0);
   600       primal_solution.
swap(dual_solution_1);
   602       write_output(equation_systems, param.n_timesteps, 
"dual1", param);
   605       primal_solution.swap(dual_solution_1);
   611       for (
unsigned int t_step=param.initial_timestep;
   612            t_step != param.initial_timestep + param.n_timesteps; ++t_step)
   630                          << system.
time - (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   667           libMesh::out << 
"Saving adjoint and retrieving primal solutions at time t=" << system.
time - system.
deltat << std::endl;
   684                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   691                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   704           primal_solution.
swap(dual_solution_0);
   706           write_output(equation_systems, param.n_timesteps - (t_step + 1), 
"dual0", param);
   709           primal_solution.swap(dual_solution_0);
   715           primal_solution.
swap(dual_solution_1);
   717           write_output(equation_systems, param.n_timesteps - (t_step + 1), 
"dual1", param);
   720           primal_solution.swap(dual_solution_1);
   736       qois.add_indices({0,1});
   737       qois.set_weight(0, 0.5);
   738       qois.set_weight(1, 0.5);
   741       auto adjoint_refinement_error_estimator =
   745       ErrorVector QoI_elementwise_error;
   746       std::vector<Number> QoI_spatially_integrated_error(system.
n_qois());
   749       ErrorVector accumulated_QoI_elementwise_error;
   750       std::vector<Number> accumulated_QoI_spatially_integrated_error(system.
n_qois());
   791       if(param.timesolver_tolerance)
   793         libmesh_error_msg_if(std::abs(Z0_old_norm - (4.3523242593920151e-06)) >= 2.e-10,
   794                              "Mismatch in expected Z0_old norm for the 1st half timestep!");
   795         libmesh_error_msg_if(std::abs(Z1_old_norm - (0.3118758855352407)) >= 2.e-5,
   796                              "Mismatch in expected Z1_old norm for the 1st half timestep!");
   800         libmesh_error_msg_if(std::abs(Z0_old_norm - (0.0030758523361801263)) >= 2.e-7,
   801                              "Mismatch in expected Z0_old norm for the 1st timestep!");
   802         libmesh_error_msg_if(std::abs(Z1_old_norm - (0.31162043809579365)) >= 2.e-5,
   803                              "Mismatch in expected Z1_old norm for the 1st timestep!");
   807                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   814                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   822       for (
unsigned int t_step=param.initial_timestep;
   823            t_step != param.initial_timestep + param.n_timesteps; ++t_step)
   825           system.
time_solver->integrate_adjoint_refinement_error_estimate(*adjoint_refinement_error_estimator, QoI_elementwise_error);
   860                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   867                        << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
   874           for(
unsigned int i = 0; i < QoI_elementwise_error.size(); i++)
   875             accumulated_QoI_elementwise_error[i] += QoI_elementwise_error[i];
   881             if ((adjoint_refinement_error_estimator->qoi_set()).has_index(j))
   888       std::cout<<
"Time integrated error estimate for QoI 0: "<<std::setprecision(17)<<accumulated_QoI_spatially_integrated_error[0]<<std::endl;
   889       std::cout<<
"Time integrated error estimate for QoI 1: "<<std::setprecision(17)<<accumulated_QoI_spatially_integrated_error[1]<<std::endl;
   895       if(param.timesolver_tolerance)
   897         libmesh_error_msg_if(std::abs(system.
time - (1.7548735069535084)) >= 2.e-4,
   898                              "Mismatch in end time reached by adaptive timestepper!");
   900         libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[0] - (-0.75139371165754232)) >= 2.e-4,
   901                              "Error Estimator identity not satisfied!");
   903         libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[1] - (-0.70905030091469889)) >= 2.e-4,
   904                              "Error Estimator identity not satisfied!");
   908         libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[0] - (-0.44809323880671958)) >= 2.e-4,
   909                              "Error Estimator identity not satisfied!");
   911         libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[1] - (-0.23895256319278346)) >= 2.e-4,
   912                              "Error Estimator identity not satisfied!");
   915 #if defined(NDEBUG) && defined(LIBMESH_ENABLE_EXCEPTIONS)   919                    << 
"] Caught exception; exiting early." << std::endl;
   924                << 
"] Completing output."   930 #endif // LIBMESH_ENABLE_AMR 
libMesh::Real timesolver_upper_tolerance
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep. 
bool print_solution_norms
ElemType
Defines an enum for geometric element types. 
bool print_element_residuals
std::string solution_history_type
Real verify_analytic_jacobians
If verify_analytic_jacobian is equal to zero (as it is by default), no numeric jacobians will be calc...
Number adjoint_initial_value0(const Point &, const Parameters &, const std::string &, const std::string &)
libMesh::Real timesolver_tolerance
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean. 
void write_output(EquationSystems &es, unsigned int t_step, std::string solution_type, FEMParameters ¶m)
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...
Number get_qoi_value(unsigned int qoi_index) const
bool print_jacobian_norms
Set print_jacobian_norms to true to print |J| whenever it is assembled. 
int main(int argc, char **argv)
unsigned int n_qois() const
Number of currently active quantities of interest. 
int extra_quadrature_order
A member int that can be employed to indicate increased or reduced quadrature order. 
Real numerical_jacobian_h
If calculating numeric jacobians is required, the FEMSystem will perturb each solution vector entry b...
std::string timesolver_core
bool require_residual_reduction
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use. 
bool print_residual_norms
void init_qois(unsigned int n_qois)
Accessors for qoi and qoi_error_estimates vectors. 
libMesh::Real timesolver_maxgrowth
Gradient adjoint_initial_grad0(const Point &, const Parameters &, const std::string &, const std::string &)
libMesh::Real relative_step_tolerance
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled. 
void pop_physics()
Pop a physics object off of our stack. 
bool print_element_residuals
Set print_element_residuals to true to print each R_elem contribution. 
SolverPackage default_solver_package()
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr) const
Projects arbitrary functions onto the current solution. 
bool print_solution_norms
Set print_residual_norms to true to print |U| whenever it is used in an assembly() call...
void libmesh_ignore(const Args &...)
unsigned int max_linear_iterations
bool print_residual_norms
Set print_residual_norms to true to print |F| whenever it is assembled. 
double minimum_linear_tolerance
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time...
libMesh::Real verify_analytic_jacobians
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values. 
Real calculate_norm(const NumericVector< Number > &v, unsigned int var, FEMNormType norm_type, std::set< unsigned int > *skip_dimensions=nullptr) const
bool print_residuals
Set print_residuals to true to print F whenever it is assembled. 
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary. 
double initial_linear_tolerance
void set_system_parameters(HeatSystem &system, FEMParameters ¶m)
int extra_quadrature_order
void read(GetPot &input, const std::vector< std::string > *other_variable_names=nullptr)
bool print_solutions
Set print_solutions to true to print U whenever it is used in an assembly() call. ...
libMesh::Real relative_residual_tolerance
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void set_vector_preservation(const std::string &vec_name, bool preserve)
Allows one to set the boolean controlling whether the vector identified by vec_name should be "preser...
bool print_jacobian_norms
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v. 
libMesh::Real min_step_length
libMesh::Real timesolver_theta
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Gradient initial_grad(const Point &, const Parameters &, const std::string &, const std::string &)
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
bool print_element_jacobians
Set print_element_jacobians to true to print each J_elem contribution. 
bool print_element_jacobians
unsigned int max_nonlinear_iterations
double linear_tolerance_multiplier
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system. 
std::map< libMesh::boundary_id_type, std::vector< unsigned int > > dirichlet_condition_variables
std::unique_ptr< AdjointRefinementEstimator > build_adjoint_refinement_error_estimator(QoISet &qois, FEMPhysics *supplied_physics, FEMParameters &)
void project_vector(NumericVector< Number > &new_vector, FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, int is_adjoint=-1) const
Projects arbitrary functions onto a vector of degree of freedom values for the current system...
virtual void solve() override
Invokes the solver associated with the system. 
void push_physics(DifferentiablePhysics &new_physics)
Push a clone of a new physics object onto our stack, overriding the current physics until the new phy...
Number get_qoi_error_estimate_value(unsigned int qoi_index) const
bool & analytic_jacobians()
libMesh::Real numerical_jacobian_h
std::map< libMesh::boundary_id_type, libMesh::FunctionBase< libMesh::Number > * > dirichlet_conditions
const DofMap & get_dof_map() const
std::vector< libMesh::FEMNormType > timesolver_norm
template class LIBMESH_EXPORT NumericVector< Number >
Number initial_value(const Point &, const Parameters &, const std::string &, const std::string &)
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...
const NumericVector< Number > & get_vector(std::string_view vec_name) const
unsigned int deltat_reductions