767 {
769 auto &ep = *ctx_impl_ptr->
ep_ptr;
770
771 auto row_sol =
775 CHKERR VecGhostUpdateBegin(row_sol, INSERT_VALUES, SCATTER_FORWARD);
776 CHKERR VecGhostUpdateEnd(row_sol, INSERT_VALUES, SCATTER_FORWARD);
777
778 auto col_sol =
782 CHKERR VecGhostUpdateBegin(col_sol, INSERT_VALUES, SCATTER_FORWARD);
783 CHKERR VecGhostUpdateEnd(col_sol, INSERT_VALUES, SCATTER_FORWARD);
784
785 MOFEM_LOG(
"EP", Sev::inform) <<
"Starting finite difference dJ_adjoint_dX "
786 "gradient test with epsilon = "
787 << epsilon;
788
790 auto direction_vec =
791 opt->
setRandomFields(ep.dmMaterial, {{ep.materialH1Positions, {-1., 1.}}},
793 CHKERR VecGhostUpdateBegin(direction_vec, INSERT_VALUES, SCATTER_FORWARD);
794 CHKERR VecGhostUpdateEnd(direction_vec, INSERT_VALUES, SCATTER_FORWARD);
795
796 const std::array<double, 2> piola_range{{-1, 1}};
797 const std::array<double, 2> bubble_range{{-1, 1}};
798 const std::array<double, 2> spatial_l2_disp_range{{-1, 1}};
799 const std::array<double, 2> rot_axis_range{{-1, 1}};
800 const std::array<double, 2> stretch_tensor_range{{-1, 1}};
801 const std::array<double, 2> hybrid_spatial_disp_range{{-1, 1}};
802
803 std::vector<OperatorsTester::RandomFieldData> adjoint_random_fields{
804 {ep.piolaStress, piola_range},
805 {ep.bubbleField, bubble_range},
806 {ep.spatialL2Disp, spatial_l2_disp_range},
807 {ep.rotAxis, rot_axis_range},
808 {ep.stretchTensor, stretch_tensor_range},
809 {ep.hybridSpatialDisp, hybrid_spatial_disp_range}};
810
811 auto adjoint_vec = opt->setRandomFields(ep.dmMaterial, adjoint_random_fields,
813 CHKERR VecGhostUpdateBegin(adjoint_vec, INSERT_VALUES, SCATTER_FORWARD);
814 CHKERR VecGhostUpdateEnd(adjoint_vec, INSERT_VALUES, SCATTER_FORWARD);
815
816 const std::array<double, 2> state_piola_range{{-1, 1}};
817 const std::array<double, 2> state_bubble_range{{-1, 1}};
818 const std::array<double, 2> state_spatial_l2_disp_range{{-1, 1}};
819 const std::array<double, 2> state_rot_axis_range{{-1, 1}};
820 const std::array<double, 2> state_stretch_tensor_range{{-1, 1}};
821 const std::array<double, 2> state_hybrid_spatial_disp_range{{-1, 1}};
822
823 std::vector<OperatorsTester::RandomFieldData> state_random_fields{
824 {ep.piolaStress, state_piola_range},
825 {ep.bubbleField, state_bubble_range},
826 {ep.spatialL2Disp, state_spatial_l2_disp_range},
827 {ep.rotAxis, state_rot_axis_range},
828 {ep.stretchTensor, state_stretch_tensor_range},
829 {ep.hybridSpatialDisp, state_hybrid_spatial_disp_range}};
830
831 auto state_vec = opt->setRandomFields(ep.dmElastic, state_random_fields,
833 CHKERR VecGhostUpdateBegin(state_vec, INSERT_VALUES, SCATTER_FORWARD);
834 CHKERR VecGhostUpdateEnd(state_vec, INSERT_VALUES, SCATTER_FORWARD);
835
837
838 boost::shared_ptr<double> J_ptr;
840 CHKERR VecZeroEntries(dJ_dX_vec);
842 CHKERR VecZeroEntries(x_t_vec);
843
844 auto get_f_rhs_vec = [&]() {
846 auto fe_interior_rhs = ep.elasticFeRhs;
847 auto fe_boundary_rhs = ep.elasticBcRhs;
848 fe_interior_rhs->f = f_rhs_vec;
849 fe_interior_rhs->x_t = x_t_vec;
850 fe_interior_rhs->data_ctx |=
854 CHKERR TSGetStepNumber(ctx_impl_ptr->
timeSolver, &fe_interior_rhs->ts_step);
855 fe_boundary_rhs->f = f_rhs_vec;
856 fe_boundary_rhs->x_t = x_t_vec;
857 fe_boundary_rhs->data_ctx |=
861 CHKERR TSGetStepNumber(ctx_impl_ptr->
timeSolver, &fe_boundary_rhs->ts_step);
862 CHKERR VecZeroEntries(f_rhs_vec);
864 fe_interior_rhs);
866 fe_boundary_rhs);
867 CHKERR VecAssemblyBegin(f_rhs_vec);
868 CHKERR VecAssemblyEnd(f_rhs_vec);
869 CHKERR VecGhostUpdateBegin(f_rhs_vec, ADD_VALUES, SCATTER_REVERSE);
870 CHKERR VecGhostUpdateEnd(f_rhs_vec, ADD_VALUES, SCATTER_REVERSE);
871 return f_rhs_vec;
872 };
873
874 auto alpha = ep.alphaW;
875 auto rho = ep.alphaRho;
876 auto alpha_omega = ep.alphaOmega;
877
880 auto fe_adjoint =
881 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
882 auto fe_adjoint_boundary =
883 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
885 ep, fe_adjoint, interior_integration_hook, boundary_integration_hook,
886 adjoint_vec, dJ_dX_vec, alpha,
rho, alpha_omega,
887 J_ptr);
889 ep, fe_adjoint_boundary, interior_integration_hook,
890 boundary_integration_hook, adjoint_vec, dJ_dX_vec, J_ptr);
891
893 fe_adjoint);
895 fe_adjoint_boundary);
896 CHKERR VecAssemblyBegin(dJ_dX_vec);
897 CHKERR VecAssemblyEnd(dJ_dX_vec);
898 CHKERR VecGhostUpdateBegin(dJ_dX_vec, ADD_VALUES, SCATTER_REVERSE);
899 CHKERR VecGhostUpdateEnd(dJ_dX_vec, ADD_VALUES, SCATTER_REVERSE);
900 CHKERR VecGhostUpdateBegin(dJ_dX_vec, INSERT_VALUES, SCATTER_FORWARD);
901 CHKERR VecGhostUpdateEnd(dJ_dX_vec, INSERT_VALUES, SCATTER_FORWARD);
902
904 CHKERR VecCopy(direction_vec, delta_vec);
905 CHKERR VecScale(delta_vec, epsilon);
906
908 CHKERR VecCopy(row_sol, a_vec);
909 CHKERR VecAXPY(a_vec, 1, delta_vec);
911 CHKERR VecCopy(row_sol, b_vec);
912 CHKERR VecAXPY(b_vec, -1, delta_vec);
913
914 auto fe_adjoint_fd_plus =
915 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
916 auto fe_adjoint_fd_minus =
917 boost::make_shared<VolumeElementForcesAndSourcesCore>(ep.mField);
918 auto fe_adjoint_fd_plus_boundary =
919 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
920 auto fe_adjoint_fd_minus_boundary =
921 boost::make_shared<FaceElementForcesAndSourcesCore>(ep.mField);
922
923 auto J_plus = boost::make_shared<double>(0);
925 ep, fe_adjoint_fd_plus, interior_integration_hook,
926 boundary_integration_hook, adjoint_vec,
929 ep, fe_adjoint_fd_plus_boundary, interior_integration_hook,
931 a_vec);
932 auto J_minus = boost::make_shared<double>(0);
934 ep, fe_adjoint_fd_minus, interior_integration_hook,
935 boundary_integration_hook, adjoint_vec,
938 ep, fe_adjoint_fd_minus_boundary, interior_integration_hook,
940 b_vec);
941
944 fe_adjoint_fd_plus);
946 fe_adjoint_fd_plus_boundary);
947 auto f_rhs_plus_vec = get_f_rhs_vec();
948 double nrm_f_rhs_plus;
949 CHKERR VecNorm(f_rhs_plus_vec, NORM_2, &nrm_f_rhs_plus);
950
952 << "Objective at a_vec: J_plus = " << std::setprecision(12) << *J_plus
953 << ", Norm of f_rhs_plus_vec = " << nrm_f_rhs_plus;
954
957 fe_adjoint_fd_minus);
959 fe_adjoint_fd_minus_boundary);
960 auto f_rhs_minus_vec = get_f_rhs_vec();
961 double nrm_f_rhs_minus;
962 CHKERR VecNorm(f_rhs_minus_vec, NORM_2, &nrm_f_rhs_minus);
963
965 << "Objective at b_vec: J_minus = " << std::setprecision(12) << *J_minus
966 << ", Norm of f_rhs_minus_vec = " << nrm_f_rhs_minus;
967
968 double dJ_da = (*J_plus - *J_minus) / (2 * epsilon);
969 CHKERR VecAXPY(f_rhs_plus_vec, -1, f_rhs_minus_vec);
970 CHKERR VecScale(f_rhs_plus_vec, 1. / (2 * epsilon));
971 double lambda_dJ_dX;
972 CHKERR VecDot(f_rhs_plus_vec, adjoint_vec, &lambda_dJ_dX);
973
974 double exact_dJ = 0;
975 CHKERR VecDot(dJ_dX_vec, direction_vec, &exact_dJ);
976 double fd_error = dJ_da - exact_dJ;
977 double fd_dJ_dX_error = lambda_dJ_dX - exact_dJ;
978
980 << "Fd dJ_adjoint/dX = " << dJ_da << ", exact dJ/dX = " << exact_dJ
981 << ", error = " << fd_error;
983 << "Fd lambda * dJ/dX = " << lambda_dJ_dX
984 << ", exact dJ/dX = " << exact_dJ << ", error = " << fd_dJ_dX_error;
985
988
990}
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.