324{
325
326#ifndef LIBMESH_ENABLE_AMR
328 libmesh_example_requires(false, "--enable-amr");
329#else
330
331 libmesh_example_requires(2 <= LIBMESH_DIM, "2D support");
332
333
334#ifndef LIBMESH_ENABLE_DIRICHLET
335 libmesh_example_requires(false, "--enable-dirichlet");
336#endif
337
338
339 LibMeshInit
init (argc, argv);
340
341
343
345
346
347 {
348 std::ifstream i("general.in");
349 libmesh_error_msg_if(!i,
'[' <<
init.comm().rank() <<
"] Can't find general.in; exiting early.");
350 }
351 GetPot infile("general.in");
352
353
354 infile.parse_command_line(argc, argv);
355
356
358 param.read(infile);
359
360
361
362 Mesh
mesh(
init.comm(), cast_int<unsigned char>(param.dimension));
363
364
365 auto mesh_refinement = std::make_unique<MeshRefinement>(
mesh);
366
367
368 EquationSystems equation_systems (
mesh);
369
371
372
374
375 if (param.elementtype == "tri" ||
376 param.elementtype == "unstructured")
378 else
380
381 MeshTools::Generation::build_square (
mesh, param.coarsegridx, param.coarsegridy,
382 param.domain_xmin, param.domain_xmin + param.domain_edge_width,
383 param.domain_ymin, param.domain_ymin + param.domain_edge_length,
384 elemtype);
385
387
389
391
392
393 auto sigma_physics = std::make_unique<SigmaPhysics>();
394 sigma_physics->init_data(system);
395
397
398
399 equation_systems.init ();
400
401
402 for (unsigned int i=0; i != param.extrarefinements; ++i)
403 {
404 mesh_refinement->uniformly_refine(1);
405 equation_systems.reinit();
406 }
407
408 libMesh::out <<
"Setting primal initial conditions" << std::endl;
409
411 equation_systems.parameters);
412
413
416 << ")|= "
418 << std::endl
419 << std::endl;
420
421
423
424
426
427
429
430
432 equation_systems.print_info();
433
434
435 Number QoI_1_accumulated = 0.0;
436
437
438
439
440#if defined(NDEBUG) && defined(LIBMESH_ENABLE_EXCEPTIONS)
441 try
442#endif
443 {
444
445
446 for (unsigned int t_step=param.initial_timestep;
447 t_step != param.initial_timestep + param.n_timesteps; ++t_step)
448 {
449
451 << t_step
452 << ", time = "
454 << std::endl;
455
456
458
459
462 << ")|= "
464 << std::endl;
465
466
467 libMesh::out <<
"Advancing timestep" << std::endl << std::endl;
469
470
471 write_output(equation_systems, t_step+1,
"primal", param);
472 }
473
474
475
476 (
dynamic_cast<HeatSystem &
>(system).QoI_time_instant)[0] = system.
time;
477
478
479
480
482
484
485 QoI_1_accumulated = 0.0;
486
487 for (unsigned int t_step=param.initial_timestep;
488 t_step != param.initial_timestep + param.n_timesteps; ++t_step)
489 {
491
493 }
494
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;
497
499
500
501 libMesh::out << std::endl <<
"Solving the adjoint problems." << std::endl;
502
503
504
505
506
507
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";
512
517
520 << ")"
521 <<std::endl;
522
523
524
525
528 equation_systems.parameters,
530
531
532
533
534
535
537
540
543 << ")|= "
544 << Z0_norm
545 << std::endl
546 << std::endl;
547
550 << ")|= "
551 << Z1_norm
552 << std::endl
553 << std::endl;
554
555
556
558
561
562
565
567 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
568 << ")|= "
570 << std::endl
571 << std::endl;
572
574 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
575 << ")|= "
577 << std::endl
578 << std::endl;
579
580
581
582
583 NumericVector<Number> & primal_solution = *system.
solution;
584
585
587
588
589 primal_solution.
swap(dual_solution_0);
590
591 write_output(equation_systems, param.n_timesteps,
"dual0", param);
592
593
594 primal_solution.swap(dual_solution_0);
595
596
598
599
600 primal_solution.
swap(dual_solution_1);
601
602 write_output(equation_systems, param.n_timesteps,
"dual1", param);
603
604
605 primal_solution.swap(dual_solution_1);
606
607
608
609
610
611 for (unsigned int t_step=param.initial_timestep;
612 t_step != param.initial_timestep + param.n_timesteps; ++t_step)
613 {
614
616 << t_step
617 << ", time = "
619 << std::endl;
620
621
622
625 << ")|= "
627 << std::endl;
628
630 << system.
time - (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
631 << ")|= "
633 << std::endl;
634
636
637
639
641
644
647 << ")|= "
648 << Z0_norm
649 << std::endl
650 << std::endl;
651
654 << ")|= "
655 << Z1_norm
656 << std::endl
657 << std::endl;
658
659
661
662
663
664
666
667 libMesh::out <<
"Saving adjoint and retrieving primal solutions at time t=" << system.
time - system.
deltat << std::endl;
668
669
670
671
672
673
675
678
679
682
684 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
685 << ")|= "
686 << Z0_old_norm
687 << std::endl
688 << std::endl;
689
691 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
692 << ")|= "
693 << Z1_old_norm
694 << std::endl
695 << std::endl;
696
697
699
700
702
703
704 primal_solution.
swap(dual_solution_0);
705
706 write_output(equation_systems, param.n_timesteps - (t_step + 1),
"dual0", param);
707
708
709 primal_solution.swap(dual_solution_0);
710
711
713
714
715 primal_solution.
swap(dual_solution_1);
716
717 write_output(equation_systems, param.n_timesteps - (t_step + 1),
"dual1", param);
718
719
720 primal_solution.swap(dual_solution_1);
721 }
722
723
724
726
727
728
729
730
731
732
733
734 QoISet qois;
735
736 qois.add_indices({0,1});
737 qois.set_weight(0, 0.5);
738 qois.set_weight(1, 0.5);
739
740
741 auto adjoint_refinement_error_estimator =
743
744
745 ErrorVector QoI_elementwise_error;
746 std::vector<Number> QoI_spatially_integrated_error(system.
n_qois());
747
748
749 ErrorVector accumulated_QoI_elementwise_error;
750 std::vector<Number> accumulated_QoI_spatially_integrated_error(system.
n_qois());
751
752
754
755
757 << "time = "
759 << std::endl;
760
763 << ")|= "
765 << std::endl;
766
769 << ")|= "
771 << std::endl;
772
775 << ")|= "
777 << std::endl
778 << std::endl;
779
782 << ")|= "
784 << std::endl
785 << std::endl;
786
789
790
791 if(param.timesolver_tolerance)
792 {
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!");
797 }
798 else
799 {
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!");
804 }
805
807 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
808 << ")|= "
810 << std::endl
811 << std::endl;
812
814 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
815 << ")|= "
817 << std::endl
818 << std::endl;
819
820
821
822 for (unsigned int t_step=param.initial_timestep;
823 t_step != param.initial_timestep + param.n_timesteps; ++t_step)
824 {
825 system.
time_solver->integrate_adjoint_refinement_error_estimate(*adjoint_refinement_error_estimator, QoI_elementwise_error);
826
827
829 << "time = "
831 << std::endl;
832
835 << ")|= "
837 << std::endl;
838
841 << ")|= "
843 << std::endl;
844
847 << ")|= "
849 << std::endl
850 << std::endl;
851
854 << ")|= "
856 << std::endl
857 << std::endl;
858
860 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
861 << ")|= "
863 << std::endl
864 << std::endl;
865
867 << system.
time + (system.
time_solver->last_completed_timestep_size())/((param.timesolver_tolerance) ? 2.0 : 1.0)
868 << ")|= "
870 << std::endl
871 << std::endl;
872
873
874 for(unsigned int i = 0; i < QoI_elementwise_error.size(); i++)
875 accumulated_QoI_elementwise_error[i] += QoI_elementwise_error[i];
876
877
879 {
880
881 if ((adjoint_refinement_error_estimator->qoi_set()).has_index(j))
882 {
884 }
885 }
886 }
887
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;
890
891
892
893
894
895 if(param.timesolver_tolerance)
896 {
897 libmesh_error_msg_if(std::abs(system.
time - (1.7548735069535084)) >= 2.e-4,
898 "Mismatch in end time reached by adaptive timestepper!");
899
900 libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[0] - (-0.75139371165754232)) >= 2.e-4,
901 "Error Estimator identity not satisfied!");
902
903 libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[1] - (-0.70905030091469889)) >= 2.e-4,
904 "Error Estimator identity not satisfied!");
905 }
906 else
907 {
908 libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[0] - (-0.44809323880671958)) >= 2.e-4,
909 "Error Estimator identity not satisfied!");
910
911 libmesh_error_msg_if(std::abs(accumulated_QoI_spatially_integrated_error[1] - (-0.23895256319278346)) >= 2.e-4,
912 "Error Estimator identity not satisfied!");
913 }
914 }
915#if defined(NDEBUG) && defined(LIBMESH_ENABLE_EXCEPTIONS)
916 catch (...)
917 {
919 << "] Caught exception; exiting early." << std::endl;
920 }
921#endif
922
924 << "] Completing output."
925 << std::endl;
926
927
928 return 0;
929
930#endif
931}
Number initial_value(const Point &, const Parameters &, const std::string &, const std::string &)
Gradient initial_grad(const Point &, const Parameters &, const std::string &, const std::string &)
Number adjoint_initial_value0(const Point &, const Parameters &, const std::string &, const std::string &)
Gradient adjoint_initial_grad0(const Point &, const Parameters &, const std::string &, const std::string &)
void write_output(EquationSystems &es, unsigned int t_step, std::string solution_type, FEMParameters ¶m)
std::unique_ptr< AdjointRefinementEstimator > build_adjoint_refinement_error_estimator(QoISet &qois, FEMPhysics *supplied_physics, FEMParameters &)
void set_system_parameters(HeatSystem &system, FEMParameters ¶m)
void pop_physics()
Pop a physics object off of our stack.
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time.
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...
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...
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
virtual void solve() override
Invokes the solver associated with the system.
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v.
void project_vector(NumericVector< Number > &new_vector, FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, int is_adjoint=-1, std::optional< ConstElemRange > active_local_range=std::nullopt, std::optional< std::vector< unsigned int > > variable_numbers=std::nullopt) const
Projects arbitrary functions onto a vector of degree of freedom values for the current system.
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, std::optional< ConstElemRange > active_local_range=std::nullopt, std::optional< std::vector< unsigned int > > variable_numbers=std::nullopt) const
Projects arbitrary functions onto the current solution.
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...
Number get_qoi_value(unsigned int qoi_index) const
void init_qois(unsigned int n_qois)
Accessors for qoi and qoi_error_estimates vectors.
void set_adjoint_already_solved(bool setting)
Setter for the adjoint_already_solved boolean.
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
unsigned int n_qois() const
Number of currently active quantities of interest.
Real calculate_norm(const NumericVector< Number > &v, unsigned int var, FEMNormType norm_type, std::set< unsigned int > *skip_dimensions=nullptr) const
Number get_qoi_error_estimate_value(unsigned int qoi_index) const
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
const NumericVector< Number > & get_vector(std::string_view vec_name) const
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
ElemType
Defines an enum for geometric element types.
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...