769 {
771 auto &ep = *ctx_impl_ptr->
ep_ptr;
772
773 auto row_sol =
777 CHKERR VecGhostUpdateBegin(row_sol, INSERT_VALUES, SCATTER_FORWARD);
778 CHKERR VecGhostUpdateEnd(row_sol, INSERT_VALUES, SCATTER_FORWARD);
779
780 auto col_sol =
784 CHKERR VecGhostUpdateBegin(col_sol, INSERT_VALUES, SCATTER_FORWARD);
785 CHKERR VecGhostUpdateEnd(col_sol, INSERT_VALUES, SCATTER_FORWARD);
786
787 MOFEM_LOG(
"EP", Sev::inform) <<
"Starting finite difference dJ_adjoint_dX "
788 "gradient test with epsilon = "
789 << epsilon;
790
792 auto direction_vec =
793 opt->
setRandomFields(ep.dmMaterial, {{ep.materialH1Positions, {-1., 1.}}},
795 CHKERR VecGhostUpdateBegin(direction_vec, INSERT_VALUES, SCATTER_FORWARD);
796 CHKERR VecGhostUpdateEnd(direction_vec, INSERT_VALUES, SCATTER_FORWARD);
797
798 const std::array<double, 2> piola_range{{-1, 1}};
799 const std::array<double, 2> bubble_range{{-1, 1}};
800 const std::array<double, 2> spatial_l2_disp_range{{-1, 1}};
801 const std::array<double, 2> rot_axis_range{{-1, 1}};
802 const std::array<double, 2> stretch_tensor_range{{-1, 1}};
803 const std::array<double, 2> hybrid_spatial_disp_range{{-1, 1}};
804
805 std::vector<OperatorsTester::RandomFieldData> adjoint_random_fields{
806 {ep.piolaStress, piola_range},
807 {ep.bubbleField, bubble_range},
808 {ep.spatialL2Disp, spatial_l2_disp_range},
809 {ep.rotAxis, rot_axis_range},
810 {ep.stretchTensor, stretch_tensor_range},
811 {ep.hybridSpatialDisp, hybrid_spatial_disp_range}};
812
813 auto adjoint_vec = opt->setRandomFields(ep.dmMaterial, adjoint_random_fields,
815 CHKERR VecGhostUpdateBegin(adjoint_vec, INSERT_VALUES, SCATTER_FORWARD);
816 CHKERR VecGhostUpdateEnd(adjoint_vec, INSERT_VALUES, SCATTER_FORWARD);
817
818 const std::array<double, 2> state_piola_range{{-1, 1}};
819 const std::array<double, 2> state_bubble_range{{-1, 1}};
820 const std::array<double, 2> state_spatial_l2_disp_range{{-1, 1}};
821 const std::array<double, 2> state_rot_axis_range{{-1, 1}};
822 const std::array<double, 2> state_stretch_tensor_range{{-1, 1}};
823 const std::array<double, 2> state_hybrid_spatial_disp_range{{-1, 1}};
824
825 std::vector<OperatorsTester::RandomFieldData> state_random_fields{
826 {ep.piolaStress, state_piola_range},
827 {ep.bubbleField, state_bubble_range},
828 {ep.spatialL2Disp, state_spatial_l2_disp_range},
829 {ep.rotAxis, state_rot_axis_range},
830 {ep.stretchTensor, state_stretch_tensor_range},
831 {ep.hybridSpatialDisp, state_hybrid_spatial_disp_range}};
832
833 auto state_vec = opt->setRandomFields(ep.dmElastic, state_random_fields,
835 CHKERR VecGhostUpdateBegin(state_vec, INSERT_VALUES, SCATTER_FORWARD);
836 CHKERR VecGhostUpdateEnd(state_vec, INSERT_VALUES, SCATTER_FORWARD);
837
839
840 boost::shared_ptr<double> J_ptr;
842 CHKERR VecZeroEntries(dJ_dX_vec);
844 CHKERR VecZeroEntries(x_t_vec);
845
846 auto get_f_rhs_vec = [&]() {
848 auto fe_interior_rhs = ep.elasticFeRhs;
849 auto fe_boundary_rhs = ep.elasticBcRhs;
850 fe_interior_rhs->f = f_rhs_vec;
851 fe_interior_rhs->x_t = x_t_vec;
852 fe_interior_rhs->data_ctx |=
856 CHKERR TSGetStepNumber(ctx_impl_ptr->
timeSolver, &fe_interior_rhs->ts_step);
857 fe_boundary_rhs->f = f_rhs_vec;
858 fe_boundary_rhs->x_t = x_t_vec;
859 fe_boundary_rhs->data_ctx |=
863 CHKERR TSGetStepNumber(ctx_impl_ptr->
timeSolver, &fe_boundary_rhs->ts_step);
864 CHKERR VecZeroEntries(f_rhs_vec);
866 fe_interior_rhs);
868 fe_boundary_rhs);
869 CHKERR VecAssemblyBegin(f_rhs_vec);
870 CHKERR VecAssemblyEnd(f_rhs_vec);
871 CHKERR VecGhostUpdateBegin(f_rhs_vec, ADD_VALUES, SCATTER_REVERSE);
872 CHKERR VecGhostUpdateEnd(f_rhs_vec, ADD_VALUES, SCATTER_REVERSE);
873 return f_rhs_vec;
874 };
875
876 auto alpha = ep.alphaW;
877 auto rho = ep.alphaRho;
878 auto alpha_viscous_omega = ep.alphaViscousOmega;
879
882 auto fe_adjoint =
883 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
884 auto fe_adjoint_boundary =
885 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
887 ep, fe_adjoint, interior_integration_hook, boundary_integration_hook,
888 adjoint_vec, dJ_dX_vec, alpha,
rho, alpha_viscous_omega,
889 J_ptr);
891 ep, fe_adjoint_boundary, interior_integration_hook,
892 boundary_integration_hook, adjoint_vec, dJ_dX_vec, J_ptr);
893
895 fe_adjoint);
897 fe_adjoint_boundary);
898 CHKERR VecAssemblyBegin(dJ_dX_vec);
899 CHKERR VecAssemblyEnd(dJ_dX_vec);
900 CHKERR VecGhostUpdateBegin(dJ_dX_vec, ADD_VALUES, SCATTER_REVERSE);
901 CHKERR VecGhostUpdateEnd(dJ_dX_vec, ADD_VALUES, SCATTER_REVERSE);
902 CHKERR VecGhostUpdateBegin(dJ_dX_vec, INSERT_VALUES, SCATTER_FORWARD);
903 CHKERR VecGhostUpdateEnd(dJ_dX_vec, INSERT_VALUES, SCATTER_FORWARD);
904
906 CHKERR VecCopy(direction_vec, delta_vec);
907 CHKERR VecScale(delta_vec, epsilon);
908
910 CHKERR VecCopy(row_sol, a_vec);
911 CHKERR VecAXPY(a_vec, 1, delta_vec);
913 CHKERR VecCopy(row_sol, b_vec);
914 CHKERR VecAXPY(b_vec, -1, delta_vec);
915
916 auto fe_adjoint_fd_plus =
917 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
918 auto fe_adjoint_fd_minus =
919 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
920 auto fe_adjoint_fd_plus_boundary =
921 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
922 auto fe_adjoint_fd_minus_boundary =
923 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
924
925 auto J_plus = boost::make_shared<double>(0);
927 ep, fe_adjoint_fd_plus, interior_integration_hook,
928 boundary_integration_hook, adjoint_vec,
931 ep, fe_adjoint_fd_plus_boundary, interior_integration_hook,
933 a_vec);
934 auto J_minus = boost::make_shared<double>(0);
936 ep, fe_adjoint_fd_minus, interior_integration_hook,
937 boundary_integration_hook, adjoint_vec,
940 ep, fe_adjoint_fd_minus_boundary, interior_integration_hook,
942 b_vec);
943
946 fe_adjoint_fd_plus);
948 fe_adjoint_fd_plus_boundary);
949 auto f_rhs_plus_vec = get_f_rhs_vec();
950 double nrm_f_rhs_plus;
951 CHKERR VecNorm(f_rhs_plus_vec, NORM_2, &nrm_f_rhs_plus);
952
954 << "Objective at a_vec: J_plus = " << std::setprecision(12) << *J_plus
955 << ", Norm of f_rhs_plus_vec = " << nrm_f_rhs_plus;
956
959 fe_adjoint_fd_minus);
961 fe_adjoint_fd_minus_boundary);
962 auto f_rhs_minus_vec = get_f_rhs_vec();
963 double nrm_f_rhs_minus;
964 CHKERR VecNorm(f_rhs_minus_vec, NORM_2, &nrm_f_rhs_minus);
965
967 << "Objective at b_vec: J_minus = " << std::setprecision(12) << *J_minus
968 << ", Norm of f_rhs_minus_vec = " << nrm_f_rhs_minus;
969
970 double dJ_da = (*J_plus - *J_minus) / (2 * epsilon);
971 CHKERR VecAXPY(f_rhs_plus_vec, -1, f_rhs_minus_vec);
972 CHKERR VecScale(f_rhs_plus_vec, 1. / (2 * epsilon));
973 double lambda_dJ_dX;
974 CHKERR VecDot(f_rhs_plus_vec, adjoint_vec, &lambda_dJ_dX);
975
976 double exact_dJ = 0;
977 CHKERR VecDot(dJ_dX_vec, direction_vec, &exact_dJ);
978 double fd_error = dJ_da - exact_dJ;
979 double fd_dJ_dX_error = lambda_dJ_dX - exact_dJ;
980
982 << "Fd dJ_adjoint/dX = " << dJ_da << ", exact dJ/dX = " << exact_dJ
983 << ", error = " << fd_error;
985 << "Fd lambda * dJ/dX = " << lambda_dJ_dX
986 << ", exact dJ/dX = " << exact_dJ << ", error = " << fd_dJ_dX_error;
987
990
992}
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
#define MOFEM_LOG(channel, severity)
Log.
static MoFEMErrorCode setSpatialConfigurationImpl(EshelbianCore &ep, Vec sol)
static MoFEMErrorCode setMaterialConfigurationImpl(EshelbianCore &ep, Vec sol)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
SmartPetscObj< DM > dmMaterial
Material problem.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
SmartPetscObj< Vec > setRandomFields(SmartPetscObj< DM > dm, std::vector< RandomFieldData > random_fields, boost::shared_ptr< Range > ents=nullptr, RowColData r=RowColData::COL)
Generate random fields.
@ CTX_SET_X_T
Time derivative X_t is set.
@ CTX_SET_TIME
Time value is set.
@ CTX_SET_X
Solution vector X is set.