#include "../MEF90/mef90.inc" module m_MEF90_DefMech #include "petsc/finclude/petsc.h" use petscsnes use petsctao use, intrinsic :: iso_c_binding use m_MEF90_EXO use m_MEF90_DefMech_class use m_MEF90_DefMechAT use m_MEF90_DefMechAssembly2D, & MEF90DefMechOperatorDisplacement2D => MEF90DefMechOperatorDisplacement, & MEF90DefMechBilinearFormDisplacement2D => MEF90DefMechBilinearFormDisplacement, & MEF90DefMechWork2D => MEF90DefMechWork, & MEF90DefMechCohesiveEnergy2D => MEF90DefMechCohesiveEnergy, & MEF90DefMechPlasticdissipation2D => MEF90DefMechPlasticDissipation, & MEF90DefMechElasticEnergy2D => MEF90DefMechElasticEnergy, & MEF90DefMechOperatorDamage2D => MEF90DefMechOperatorDamage, & MEF90DefMechTAOGradientDamage2D => MEF90DefMechTAOGradientDamage, & MEF90DefMechBilinearFormDamage2D => MEF90DefMechBilinearFormDamage, & MEF90DefMechTAOHessianDamage2D => MEF90DefMechTAOHessianDamage, & MEF90DefMechSurfaceEnergy2D => MEF90DefMechSurfaceEnergy, & MEF90DefMechTAOObjectiveDamage2D => MEF90DefMechTAOObjectiveDamage, & MEF90DefMechCrackVolume2D => MEF90DefMechCrackVolume, & MEF90DefMechStress2D => MEF90DefMechStress use m_MEF90_DefMechPlasticity2D, & MEF90DefMechPlasticStrainUpdate2D => MEF90DefMechPlasticStrainUpdate use m_MEF90_DefMechAssembly3D, & MEF90DefMechOperatorDisplacement3D => MEF90DefMechOperatorDisplacement, & MEF90DefMechBilinearFormDisplacement3D => MEF90DefMechBilinearFormDisplacement, & MEF90DefMechWork3D => MEF90DefMechWork, & MEF90DefMechCohesiveEnergy3D => MEF90DefMechCohesiveEnergy, & MEF90DefMechPlasticdissipation3D => MEF90DefMechPlasticDissipation, & MEF90DefMechElasticEnergy3D => MEF90DefMechElasticEnergy, & MEF90DefMechOperatorDamage3D => MEF90DefMechOperatorDamage, & MEF90DefMechTAOGradientDamage3D => MEF90DefMechTAOGradientDamage, & MEF90DefMechBilinearFormDamage3D => MEF90DefMechBilinearFormDamage, & MEF90DefMechTAOHessianDamage3D => MEF90DefMechTAOHessianDamage, & MEF90DefMechSurfaceEnergy3D => MEF90DefMechSurfaceEnergy, & MEF90DefMechTAOObjectiveDamage3D => MEF90DefMechTAOObjectiveDamage, & MEF90DefMechCrackVolume3D => MEF90DefMechCrackVolume, & MEF90DefMechStress3D => MEF90DefMechStress use m_MEF90_DefMechPlasticity3D, & MEF90DefMechPlasticStrainUpdate3D => MEF90DefMechPlasticStrainUpdate implicit none(type) ! private public :: MEF90DefMechSetTransients public :: MEF90DefMechOperatorDisplacement public :: MEF90DefMechBilinearFormDisplacement public :: MEF90DefMechCreateSNESDisplacement public :: MEF90DefMechOperatorDamage public :: MEF90DefMechBilinearFormDamage public :: MEF90DefMechCreateSNESDamage public :: MEF90DefMechUpdateDamageBounds public :: MEF90DefMechTAOObjectiveDamage public :: MEF90DefMechTAOGradientDamage public :: MEF90DefMechTAOHessianDamage public :: MEF90DefMechCreateTAODamage public :: MEF90DefMechTAOUpdateDamageBounds public :: MEF90DefMechViewEXO public :: MEF90DefMechSurfaceEnergy public :: MEF90DefMechElasticEnergy public :: MEF90DefMechWork public :: MEF90DefMechCohesiveEnergy public :: MEF90DefMechPlasticDissipation public :: MEF90DefMechCrackVolume public :: MEF90DefMechStress public :: MEF90DefMechPlasticStrainUpdate public :: MEF90DefMechFormatEXO contains #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechComputeCompositeDamage" !!! author: Blaise Bourdin (2026, bourdin@mcmaster.ca) !!! !!! MEF90DefMechComputeCompositeDamage: Reconstruct a global damage field by taking the min of all set damage fields !!! Use in multi-phase field for I/O, error on altmin etc !!! subroutine MEF90DefMechComputeCompositeDamage(damage, damageSets, ierr) type(tVec), intent(in) :: damage type(tVec), dimension(:), pointer :: damageSets PetscErrorCode, intent(INOUT) :: ierr PetscInt :: set PetscCall(VecSet(damage, 0.0_Kr, ierr)) do set = 1, size(damageSets) PetscCall(VecPointwiseMax(damage, damage, damageSets(set), ierr)) end do end subroutine MEF90DefMechComputeCompositeDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechSetTransients" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! author: Blaise Bourdin (2026, bourdin@mcmaster.ca) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechSetTransients: !!! subroutine MEF90DefMechSetTransients(MEF90DefMechCtx, step, time, ierr) type(MEF90DefMech_Type), intent(INOUT) :: MEF90DefMechCtx PetscInt, intent(IN) :: step PetscReal, intent(IN) :: time PetscErrorCode, intent(INOUT) :: ierr type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions type(MEF90CtxGlobalOptions_Type) :: MEF90GlobalOptions type(tDM) :: dmDisplacement, dmDamage, dmCohesiveDisplacement type(tVec) :: tmpVec character(len=MEF90MXSTRLEN) :: IOBuffer, vecName PetscExodusIIInt :: EXOstep PetscInt :: set EXOstep = step PetscCall(MEF90CtxGlobalOptionsSetFromOptions(MEF90DefMechCtx%MEF90Ctx%comm, trim(MEF90DefMechCtx%MEF90Ctx%prefix), MEF90GlobalOptions, ierr)) PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%damageLocal, dmDamage, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%displacementLocal, dmDisplacement, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%cohesiveDisplacement, dmCohesiveDisplacement, ierr)) select case (MEF90DefMechGlobalOptions%boundaryDisplacementScaling) case (MEF90Scaling_File) PetscCall(DMGetLocalVector(dmDisplacement, tmpVec, ierr)) PetscCall(PetscObjectSetName(tmpVec, "Displacement", ierr)) PetscCall(MEF90EXOVecLoad(tmpVec, MEF90DefMechCtx%displacementToIOSF, MEF90DefMechCtx%IOToDisplacementSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, EXOstep, MEF90DefMechCtx%dim, ierr)) PetscCall(MEF90VecCopySF(tmpVec, MEF90DefMechCtx%displacementLocal, MEF90DefMechCtx%displacementConstraintsSF, ierr)) PetscCall(DMRestoreLocalVector(dmDisplacement, tmpVec, ierr)) case (MEF90Scaling_Linear) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementLocal, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementLocal, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetBCValuesFromOptionsExpr(MEF90DefMechCtx%displacementLocal, time, ierr)) end select select case (MEF90DefMechGlobalOptions%boundaryDamageScaling) case (MEF90Scaling_File) PetscCall(DMGetLocalVector(dmDamage, tmpVec, ierr)) PetscCall(PetscObjectSetName(tmpVec, "Damage", ierr)) PetscCall(MEF90EXOVecLoad(tmpVec, MEF90DefMechCtx%damageToIOSF, MEF90DefMechCtx%IOToDamageSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, EXOstep, 1_ki, ierr)) PetscCall(MEF90VecCopySF(tmpVec, MEF90DefMechCtx%damageLocal, MEF90DefMechCtx%damageConstraintsSF, ierr)) if (MEF90DefMechGlobalOptions%multiPhaseField) then do set = 1, size(MEF90DefMechCtx%partialDamageLocal) write(Vecname,'("partialDamage-", I4.4)') set PetscCall(PetscObjectSetName(tmpVec, vecName, ierr)) PetscCall(MEF90EXOVecLoad(tmpVec, MEF90DefMechCtx%damageToIOSF, MEF90DefMechCtx%IOToDamageSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, EXOstep, 1_ki, ierr)) PetscCall(MEF90VecCopySF(tmpVec, MEF90DefMechCtx%partialDamageLocal(set), MEF90DefMechCtx%damageConstraintsSF, ierr)) end do end if PetscCall(DMRestoreLocalVector(dmDamage, tmpVec, ierr)) case (MEF90Scaling_Linear) write (IOBuffer, '((A),": linear scaling of damage does not make any sense.\n")') __FUNCT__ SETERRQ(MEF90DefMechCtx%MEF90Ctx%Comm, PETSC_ERR_ARG_WRONG, IOBuffer) case (MEF90Scaling_CST) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%damageLocal, 1.0_kr, ierr)) if (MEF90DefMechGlobalOptions%multiPhaseField) then do set = 1, size(MEF90DefMechCtx%partialDamageLocal) !! MEF90VecSetBCValuesFromOptions retrieves BC from the option database, using a Vector's name as prefix !! We temporarily change it to "Damage" so that we do not need to pass BC for each phase-field. PetscCall(PetscObjectGetName(MEF90DefMechCtx%partialDamageLocal(set), vecName, ierr)) PetscCall(PetscObjectSetName(MEF90DefMechCtx%partialDamageLocal(set), "Damage", ierr)) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%partialDamageLocal(set), 1.0_kr, ierr)) PetscCall(PetscObjectSetName(MEF90DefMechCtx%partialDamageLocal(set), vecName, ierr)) end do end if case (MEF90Scaling_Expr) PetscCall(MEF90VecSetBCValuesFromOptionsExpr(MEF90DefMechCtx%damageLocal, 1.0_kr, ierr)) if (MEF90DefMechGlobalOptions%multiPhaseField) then do set = 1, size(MEF90DefMechCtx%partialDamageLocal) !! MEF90VecSetBCValuesFromOptions retrieves BC from the option database, using a Vector's name as prefix !! We temporarily change it to "Damage" so that we do not need to pass BC for each phase-field. PetscCall(PetscObjectGetName(MEF90DefMechCtx%partialDamageLocal(set), vecName, ierr)) PetscCall(PetscObjectSetName(MEF90DefMechCtx%partialDamageLocal(set), "Damage", ierr)) PetscCall(MEF90VecSetBCValuesFromOptionsExpr(MEF90DefMechCtx%partialDamageLocal(set), time, ierr)) PetscCall(PetscObjectSetName(MEF90DefMechCtx%partialDamageLocal(set), vecName, ierr)) end do end if end select select case (MEF90DefMechGlobalOptions%cohesiveDisplacementScaling) case (MEF90Scaling_File) PetscCall(MEF90EXOVecLoad(MEF90DefMechCtx%cohesiveDisplacement, MEF90DefMechCtx%cohesiveDisplacementToIOSF, MEF90DefMechCtx%IOToCohesiveDisplacementSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, EXOstep, MEF90DefMechCtx%dim, ierr)) case (MEF90Scaling_Linear) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%cohesiveDisplacement, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%cohesiveDisplacement, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetValuesFromOptionsExpr(MEF90DefMechCtx%cohesiveDisplacement, time, ierr)) end select select case (MEF90DefMechGlobalOptions%displacementLowerBoundScaling) case (MEF90Scaling_File) write (*, *) __FUNCT__, ": file scaling of displacement lower bound does not make any sense." stop case (MEF90Scaling_Linear) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementLowerBoundLocal, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementLowerBoundLocal, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetBCValuesFromOptionsExpr(MEF90DefMechCtx%displacementLowerBoundLocal, time, ierr)) end select select case (MEF90DefMechGlobalOptions%displacementUpperBoundScaling) case (MEF90Scaling_File) write (*, *) __FUNCT__, ": file scaling of displacement upper bound does not make any sense." stop case (MEF90Scaling_Linear) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementUpperBoundLocal, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetBCValuesFromOptions(MEF90DefMechCtx%displacementUpperBoundLocal, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetBCValuesFromOptionsExpr(MEF90DefMechCtx%displacementUpperBoundLocal, time, ierr)) end select select case (MEF90DefMechGlobalOptions%bodyForceScaling) case (MEF90Scaling_File) PetscCall(MEF90EXOVecLoad(MEF90DefMechCtx%bodyForce, MEF90DefMechCtx%bodyForceToIOSF, MEF90DefMechCtx%IOToBodyForceSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, EXOstep, MEF90DefMechCtx%dim, ierr)) case (MEF90Scaling_Linear) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%bodyForce, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%bodyForce, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetValuesFromOptionsExpr(MEF90DefMechCtx%bodyForce, time, ierr)) end select select case (MEF90DefMechGlobalOptions%boundaryForceScaling) case (MEF90Scaling_File) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_LIB, "Boundary force from file not implemented yet "//__FUNCT__) ! PetscCall(MEF90EXOVecLoad(MEF90DefMechCtx%boundaryForce,MEF90DefMechCtx%boundaryForceToIOSF,MEF90DefMechCtx%IOToBoundaryForceSF,MEF90DefMechCtx%MEF90Ctx%resultViewer,step,MEF90DefMechCtx%dim,ierr)) case (MEF90Scaling_Linear) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%boundaryForce, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%boundaryForce, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetValuesFromOptionsExpr(MEF90DefMechCtx%boundaryForce, time, ierr)) end select select case (MEF90DefMechGlobalOptions%pressureForceScaling) case (MEF90Scaling_File) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_LIB, "Pressure force from file not implemented yet "//__FUNCT__) ! PetscCall(MEF90EXOVecLoad(MEF90DefMechCtx%pressureForce,MEF90DefMechCtx%pressureForceToIOSF,MEF90DefMechCtx%IOToPressureForceSF,MEF90DefMechCtx%MEF90Ctx%resultViewer,step,1_Ki,ierr)) case (MEF90Scaling_Linear) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%pressureForce, time, ierr)) case (MEF90Scaling_CST) PetscCall(MEF90VecSetValuesFromOptions(MEF90DefMechCtx%pressureForce, 1.0_kr, ierr)) case (MEF90Scaling_Expr) PetscCall(MEF90VecSetValuesFromOptionsExpr(MEF90DefMechCtx%pressureForce, time, ierr)) end select end subroutine MEF90DefMechSetTransients #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechOperatorDisplacement" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! !!! MEF90DefMechOperatorDisplacement: wraps calls to MEF90DefMechOperatorDisplacement from m_MEF90_DefMechAssembly !!! since overloading cannot be used here !!! subroutine MEF90DefMechOperatorDisplacement(snesTemp, x, residual, PETScCtx, ierr) type(tSNES), intent(IN) :: snesTemp type(tVec), intent(IN) :: x type(tVec), intent(INOUT) :: residual type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechOperatorDisplacement2D(snesTemp, x, residual, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechOperatorDisplacement3D(snesTemp, x, residual, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechOperatorDisplacement #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechBilinearFormDisplacement" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! !!! MEF90DefMechBilinearFormDisplacement: wraps calls to MEF90DefMechBilinearFormDisplacement from m_MEF90_DefMechAssembly !!! since overloading cannot be used here !!! subroutine MEF90DefMechBilinearFormDisplacement(snesDispl, x, A, M, PETScCtx, ierr) type(tSNES), intent(IN) :: snesDispl type(tVec), intent(IN) :: x type(tMat), intent(INOUT) :: A, M type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechBilinearFormDisplacement2D(snesDispl, x, A, M, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechBilinearFormDisplacement3D(snesDispl, x, A, M, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechBilinearFormDisplacement #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechWork" !! !! !! MEF90DefMechWork: wraps calls to MEF90DefMechWork from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Blaise Bourdin (2012-22, bourdin@lsu.edu) !!! subroutine MEF90DefMechWork(MEF90DefMechCtx, bodyForceWork, boundaryForceWork, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: bodyForceWork, boundaryForceWork PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechWork2D(MEF90DefMechCtx, bodyForceWork, boundaryForceWork, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechWork3D(MEF90DefMechCtx, bodyForceWork, boundaryForceWork, ierr)) end if end subroutine MEF90DefMechWork #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechCohesiveEnergy" !! !! !! MEF90DefMechCohesiveEnergy: wraps calls to MEF90DefMechCohesiveEnergy from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! subroutine MEF90DefMechCohesiveEnergy(MEF90DefMechCtx, cohesiveEnergy, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: cohesiveEnergy PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechCohesiveEnergy2D(MEF90DefMechCtx, cohesiveEnergy, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechCohesiveEnergy3D(MEF90DefMechCtx, cohesiveEnergy, ierr)) end if end subroutine MEF90DefMechCohesiveEnergy #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechElasticEnergy" !! !! !! MEF90DefMechElasticEnergy: wraps calls to MEF90DefMechElasticEnergy from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! subroutine MEF90DefMechElasticEnergy(MEF90DefMechCtx, energy, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: energy PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechElasticEnergy2D(MEF90DefMechCtx, energy, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechElasticEnergy3D(MEF90DefMechCtx, energy, ierr)) end if end subroutine MEF90DefMechElasticEnergy #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechPlasticDissipation" !! !! !! MEF90DefMechPlasticDissipation: wraps calls to MEF90DefMechPlasticDissipation from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Erwan Tanne (2012-14, erwan.tanne@gmail.com) !!! subroutine MEF90DefMechPlasticDissipation(x, MEF90DefMechCtx, plasticStrainOld, energy, ierr) type(tVec), intent(IN) :: x type(tVec), intent(IN) :: plasticStrainOld type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: energy PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then ! Call MEF90DefMechPlasticDissipation2D(x,MEF90DefMechCtx,plasticStrainOld,energy,ierr) else if (MEF90DefMechCtx%dim == 3) then ! Call MEF90DefMechPlasticDissipation3D(x,MEF90DefMechCtx,plasticStrainOld,energy,ierr) end if end subroutine MEF90DefMechPlasticDissipation #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechStress" !! !! !! MEF90DefMechStress: wraps calls to MEF90DefMechElasticEnergy from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! subroutine MEF90DefMechStress(MEF90DefMechCtx, stress, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tVec), intent(IN) :: stress PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechStress2D(MEF90DefMechCtx, stress, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechStress3D(MEF90DefMechCtx, stress, ierr)) end if end subroutine MEF90DefMechStress #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechCrackVolume" !!! author: Erwan Tanne (2016, erwan.tanne@gmail.com) !!! !!! MEF90DefMechCrackVolume: !!! subroutine MEF90DefMechCrackVolume(MEF90DefMechCtx, CrackVolume, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: CrackVolume PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechCrackVolume2D(MEF90DefMechCtx, CrackVolume, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechCrackVolume3D(MEF90DefMechCtx, CrackVolume, ierr)) end if end subroutine MEF90DefMechCrackVolume #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechOperatorDamage" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! !!! MEF90DefMechOperatorDamage: wraps calls to MEF90DefMechOperatorDamage from m_MEF90_DefMechAssembly !!! since overloading cannot be used here !!! subroutine MEF90DefMechOperatorDamage(snesDamage, damage, residual, PETScCtx, ierr) type(tSNES), intent(IN) :: snesDamage type(tVec), intent(IN) :: damage type(tVec), intent(INOUT) :: residual type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechOperatorDamage2D(snesDamage, damage, residual, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechOperatorDamage3D(snesDamage, damage, residual, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechOperatorDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechTAOGradientDamage" !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechTAOGradientDamage: !!! subroutine MEF90DefMechTAOGradientDamage(taoDamage, damage, residual, PETScCtx, ierr) type(tTao), intent(IN) :: taoDamage type(tVec), intent(IN) :: damage type(tVec), intent(INOUT) :: residual type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechTAOGradientDamage2D(taoDamage, damage, residual, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechTAOGradientDamage3D(taoDamage, damage, residual, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechTAOGradientDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechBilinearFormDamage" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! !!! MEF90DefMechBilinearFormDamage: wraps calls to MEF90DefMechBilinearFormDamage from m_MEF90_DefMechAssembly !!! since overloading cannot be used here !!! subroutine MEF90DefMechBilinearFormDamage(snesDamage, damage, A, M, PETScCtx, ierr) type(tSNES), intent(IN) :: snesDamage type(tVec), intent(IN) :: damage type(tMat), intent(INOUT) :: A, M type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechBilinearFormDamage2D(snesDamage, damage, A, M, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechBilinearFormDamage3D(snesDamage, damage, A, M, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechBilinearFormDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechTAOHessianDamage" !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechTAOHessianDamage: !!! subroutine MEF90DefMechTAOHessianDamage(taoDamage, damage, A, M, PETScCtx, ierr) type(tTao), intent(IN) :: taoDamage type(tVec), intent(IN) :: damage type(tMat), intent(INOUT) :: A, M type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechTAOHessianDamage2D(taoDamage, damage, A, M, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechTAOHessianDamage3D(taoDamage, damage, A, M, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechTAOHessianDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechSurfaceEnergy" !! !! !! MEF90DefMechSurfaceEnergy: wraps calls to MEF90DefMechSurfaceEnergy from m_MEF90_DefMechAssembly !! since overloading cannot be used here !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! subroutine MEF90DefMechSurfaceEnergy(MEF90DefMechCtx, energy, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: energy PetscErrorCode, intent(INOUT) :: ierr if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechSurfaceEnergy2D(MEF90DefMechCtx, energy, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechSurfaceEnergy3D(MEF90DefMechCtx, energy, ierr)) end if end subroutine MEF90DefMechSurfaceEnergy #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechTAOObjectiveDamage" !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechTAOObjectiveDamage: !!! subroutine MEF90DefMechTAOObjectiveDamage(taoDamage, damage, energy, PETScCtx, ierr) type(tTao), intent(IN) :: taoDamage type(tVec), intent(IN) :: damage PetscReal, intent(INOUT) :: energy type(c_ptr), intent(IN) :: PETScCtx type(MEF90DefMech_Type), pointer :: MEF90DefMechCtx PetscErrorCode, intent(INOUT) :: ierr call c_f_pointer(PETScCtx, MEF90DefMechCtx) if (MEF90DefMechCtx%dim == 2) then PetscCall(MEF90DefMechTAOObjectiveDamage2D(taoDamage, damage, energy, MEF90DefMechCtx, ierr)) else if (MEF90DefMechCtx%dim == 3) then PetscCall(MEF90DefMechTAOObjectiveDamage3D(taoDamage, damage, energy, MEF90DefMechCtx, ierr)) end if end subroutine MEF90DefMechTAOObjectiveDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechFormatEXO" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Blaise Bourdin (2022-2026, bourdin@mcmaster.ca) !!! !!! MEF90DefMechFormatEXO: !!! subroutine MEF90DefMechFormatEXO(MEF90DefMechCtx, time, ierr) type(MEF90DefMech_Type), intent(INOUT) :: MEF90DefMechCtx PetscReal, dimension(:), pointer :: time PetscErrorCode, intent(OUT) :: ierr character(len=MXSTLN), dimension(:), pointer :: nameG, nameN, nameC type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions PetscInt :: numFields, offset, set, numSet PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) allocate (nameG(0)) numFields = 0 if (MEF90DefMechGlobalOptions%displacementExport) then numFields = numFields + MEF90DefMechCtx%dim end if if (MEF90DefMechGlobalOptions%damageExport) then numFields = numFields + 1 if (MEF90DefMechGlobalOptions%multiPhaseField) then PetscCall(MEF90DMGetNumSets(MEF90DefMechCtx%megaDM, "Cell Sets", numSet, ierr)) numFields = numFields + numSet end if end if if (MEF90DefMechGlobalOptions%temperatureExport) then numFields = numFields + 1 end if allocate (nameN(numFields)) offset = 1 if (MEF90DefMechGlobalOptions%displacementExport) then nameN(offset + 0) = "Displacement_X" nameN(offset + 1) = "Displacement_Y" if (MEF90DefMechCtx%dim == 3) then nameN(offset + 2) = "Displacement_Z" end if offset = offset + MEF90DefMechCtx%dim end if if (MEF90DefMechGlobalOptions%damageExport) then nameN(offset) = "Damage" offset = offset + 1 if (MEF90DefMechGlobalOptions%multiPhaseField) then do set = 1, numSet write(nameN(offset),'("partialDamage-", I4.4)') set offset = offset + 1 end do end if end if if (MEF90DefMechGlobalOptions%temperatureExport) then nameN(offset) = "Temperature" offset = offset + 1 end if numFields = 0 if (MEF90DefMechGlobalOptions%stressExport) then numFields = numFields + MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2 end if if (MEF90DefMechGlobalOptions%plasticStrainExport) then numFields = numFields + MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2 end if if (MEF90DefMechGlobalOptions%cumulatedPlasticDissipationExport) then numFields = numFields + MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2 end if allocate (nameC(numFields)) offset = 1 if (MEF90DefMechGlobalOptions%stressExport) then if (MEF90DefMechCtx%dim == 2) then nameC(offset + 0) = "Stress_XX" nameC(offset + 1) = "Stress_YY" nameC(offset + 2) = "Stress_XY" else nameC(offset + 0) = "Stress_XX" nameC(offset + 1) = "Stress_YY" nameC(offset + 2) = "Stress_ZZ" nameC(offset + 3) = "Stress_YZ" nameC(offset + 4) = "Stress_XZ" nameC(offset + 5) = "Stress_XY" end if offset = offset + MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2 end if if (MEF90DefMechGlobalOptions%plasticStrainExport) then if (MEF90DefMechCtx%dim == 2) then nameC(offset + 0) = "PlasticStrain_XX" nameC(offset + 1) = "PlasticStrain_YY" nameC(offset + 2) = "PlasticStrain_XY" else nameC(offset + 0) = "PlasticStrain_XX" nameC(offset + 1) = "PlasticStrain_YY" nameC(offset + 2) = "PlasticStrain_ZZ" nameC(offset + 3) = "PlasticStrain_YZ" nameC(offset + 4) = "PlasticStrain_XZ" nameC(offset + 5) = "PlasticStrain_XY" end if offset = offset + MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2 end if if (MEF90DefMechGlobalOptions%cumulatedPlasticDissipationExport) then if (MEF90DefMechCtx%dim == 2) then nameC(offset + 0) = "CumulatedPlasticDissipation_XX" nameC(offset + 1) = "CumulatedPlasticDissipation_YY" nameC(offset + 2) = "CumulatedPlasticDissipation_XY" else nameC(offset + 0) = "CumulatedPlasticDissipation_XX" nameC(offset + 1) = "CumulatedPlasticDissipation_YY" nameC(offset + 2) = "CumulatedPlasticDissipation_ZZ" nameC(offset + 3) = "CumulatedPlasticDissipation_YZ" nameC(offset + 4) = "CumulatedPlasticDissipation_XZ" nameC(offset + 5) = "CumulatedPlasticDissipation_XY" end if end if PetscCall(MEF90EXOFormat(MEF90DefMechCtx%MEF90Ctx%resultViewer, nameG, nameC, nameN, time, ierr)) deallocate (nameG) deallocate (nameN) deallocate (nameC) end subroutine MEF90DefMechFormatEXO #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechViewEXO" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Blaise Bourdin (2026, bourdin@mcmaster.ca) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechViewEXO: Save all fields in a MEF90DefMech_Type in an exodus file !!! subroutine MEF90DefMechViewEXO(MEF90DefMechCtx, step, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx PetscExodusIIInt, intent(IN) :: step PetscErrorCode, intent(INOUT) :: ierr type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions PetscInt :: set PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) if (MEF90DefMechGlobalOptions%displacementExport) then PetscCall(MEF90EXOVecView(MEF90DefMechCtx%displacementLocal, MEF90DefMechCtx%displacementToIOSF, MEF90DefMechCtx%IOToDisplacementSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, MEF90DefMechCtx%dim, ierr)) end if if (MEF90DefMechGlobalOptions%damageExport) then PetscCall(MEF90EXOVecView(MEF90DefMechCtx%damageLocal, MEF90DefMechCtx%damageToIOSF, MEF90DefMechCtx%IOToDamageSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, 1_ki, ierr)) if (MEF90DefMechGlobalOptions%multiPhaseField) then do set = 1, size(MEF90DefMechCtx%partialDamageLocal) PetscCall(MEF90EXOVecView(MEF90DefMechCtx%partialDamageLocal(set), MEF90DefMechCtx%damageToIOSF, MEF90DefMechCtx%IOToDamageSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, 1_ki, ierr)) end do end if end if if (MEF90DefMechGlobalOptions%stressExport) then PetscCall(MEF90EXOVecView(MEF90DefMechCtx%stress, MEF90DefMechCtx%stressToIOSF, MEF90DefMechCtx%IOToStressSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2, ierr)) end if if (MEF90DefMechGlobalOptions%plasticStrainExport) then PetscCall(MEF90EXOVecView(MEF90DefMechCtx%plasticStrain, MEF90DefMechCtx%plasticStrainToIOSF, MEF90DefMechCtx%IOToPlasticStrainSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2, ierr)) end if if (MEF90DefMechGlobalOptions%cumulatedPlasticDissipationExport) then PetscCall(MEF90EXOVecView(MEF90DefMechCtx%cumulatedPlasticDissipation, MEF90DefMechCtx%cumulatedPlasticDissToIOSF, MEF90DefMechCtx%IOToCumulatedPlasticDissSF, MEF90DefMechCtx%MEF90Ctx%resultViewer, step, MEF90DefMechCtx%dim * (MEF90DefMechCtx%dim + 1) / 2, ierr)) end if end subroutine MEF90DefMechViewEXO #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechCreateSNESDisplacement" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechCreateSNESDisplacement: !!! subroutine MEF90DefMechCreateSNESDisplacement(MEF90DefMechCtx, snesDisplacement, residual, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tSNES), intent(OUT) :: snesDisplacement type(tVec), intent(IN) :: residual PetscErrorCode, intent(INOUT) :: ierr type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions type(tDM) :: dm type(tMat) :: matDisplacement type(tMatNullSpace) :: nspDisplacement type(tKSP) :: kspDisplacement type(tVec) :: gCoord PetscReal :: rtol, dtol, atol, stol PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%displacementLocal, dm, ierr)) PetscCall(DMCreateMatrix(dm, matDisplacement, ierr)) PetscCall(MatSetOptionsPrefix(matDisplacement, "Displacement_", ierr)) PetscCall(MatSetOption(matDisplacement, MAT_SPD, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDisplacement, MAT_SYMMETRY_ETERNAL, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDisplacement, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE, ierr)) !! !! Set the matrix near null-space consisting of all rigid motions. !! PetscCall(DMGetGlobalVector(dm, gCoord, ierr)) PetscCall(MEF90DefMechProjectCoordinates_Private(gCoord, ierr)) PetscCall(MatNullSpaceCreateRigidBody(gCoord, nspDisplacement, ierr)) PetscCall(MatSetNearNullSpace(matDisplacement, nspDisplacement, ierr)) PetscCall(MatNullSpaceDestroy(nspDisplacement, ierr)) PetscCall(DMRestoreGlobalVector(dm, gCoord, ierr)) PetscCall(MatSetFromOptions(matDisplacement, ierr)) PetscCall(SNESCreate(MEF90DefMechCtx%MEF90Ctx%Comm, snesDisplacement, ierr)) PetscCall(SNESSetApplicationContext(snesDisplacement, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(SNESSetDM(snesDisplacement, dm, ierr)) PetscCall(SNESSetType(snesDisplacement, SNESKSPONLY, ierr)) PetscCall(SNESSetOptionsPrefix(snesDisplacement, 'Displacement_', ierr)) PetscCall(SNESSetFunction(snesDisplacement, residual, MEF90DefMechOperatorDisplacement, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(SNESSetJacobian(snesDisplacement, matDisplacement, matDisplacement, MEF90DefMechBilinearFormDisplacement, MEF90DefMechCtx%PETScCtx, ierr)) atol = 1.0d-7 rtol = 1.0d-5 stol = 1.0d-7 PetscCall(SNESSetTolerances(snesDisplacement, atol, rtol, stol, PETSC_DEFAULT_INTEGER, PETSC_DEFAULT_INTEGER, ierr)) PetscCall(SNESSetFromOptions(snesDisplacement, ierr)) !! !! Set some KSP options !! PetscCall(SNESGetKSP(snesDisplacement, kspDisplacement, ierr)) PetscCall(KSPSetType(kspDisplacement, KSPCG, ierr)) PetscCall(KSPSetInitialGuessNonzero(kspDisplacement, PETSC_TRUE, ierr)) atol = 1.0d-8 rtol = 1.0d-8 dtol = 1.0d+10 PetscCall(KSPSetTolerances(kspDisplacement, rtol, atol, dtol, PETSC_DEFAULT_INTEGER, ierr)) PetscCall(KSPSetFromOptions(kspDisplacement, ierr)) PetscCall(MatDestroy(matDisplacement, ierr)) end subroutine MEF90DefMechCreateSNESDisplacement #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechCreateSNESDamage" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechCreateSNESDamage: !!! subroutine MEF90DefMechCreateSNESDamage(MEF90DefMechCtx, snesDamage, residual, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tSNES), intent(OUT) :: snesDamage type(tVec), intent(IN) :: residual PetscErrorCode, intent(INOUT) :: ierr type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions type(tDM) :: dm type(tMat) :: matDamage type(tKSP) :: kspDamage type(tVec) :: UB, LB PetscReal :: rtol, dtol, atol, stol PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%damageLocal, dm, ierr)) PetscCall(DMCreateMatrix(dm, matDamage, ierr)) PetscCall(MatSetOptionsPrefix(matDamage, "Damage_", ierr)) !! The matrix is not symmetric if the advection vector is /= 0 PetscCall(MatSetOption(matDamage, MAT_SPD, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDamage, MAT_SYMMETRY_ETERNAL, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDamage, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE, ierr)) PetscCall(MatSetFromOptions(matDamage, ierr)) PetscCall(SNESCreate(MEF90DefMechCtx%MEF90Ctx%Comm, snesDamage, ierr)) PetscCall(SNESSetApplicationContext(snesDamage, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(SNESSetDM(snesDamage, dm, ierr)) PetscCall(SNESSetType(snesDamage, SNESVINEWTONRSLS, ierr)) PetscCall(SNESSetOptionsPrefix(snesDamage, 'Damage_', ierr)) PetscCall(DMCreateGlobalVector(dm, LB, ierr)) PetscCall(VecDuplicate(LB, UB, ierr)) PetscCall(VecSet(LB, 0.0_kr, ierr)) PetscCall(VecSet(UB, 1.0_kr, ierr)) PetscCall(SNESVISetVariableBounds(snesDamage, LB, UB, ierr)) PetscCall(VecDestroy(LB, ierr)) PetscCall(VecDestroy(UB, ierr)) PetscCall(SNESSetFunction(snesDamage, residual, MEF90DefMechOperatorDamage, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(SNESSetJacobian(snesDamage, matDamage, matDamage, MEF90DefMechBilinearFormDamage, MEF90DefMechCtx%PETScCtx, ierr)) atol = 1.0d-7 rtol = 1.0d-5 stol = 1.0d-7 PetscCall(SNESSetTolerances(snesDamage, atol, rtol, stol, PETSC_DEFAULT_INTEGER, PETSC_DEFAULT_INTEGER, ierr)) PetscCall(SNESSetFromOptions(snesDamage, ierr)) !! !! Set some KSP options !! PetscCall(SNESGetKSP(snesDamage, kspDamage, ierr)) PetscCall(KSPSetType(kspDamage, KSPCG, ierr)) PetscCall(KSPSetInitialGuessNonzero(kspDamage, PETSC_TRUE, ierr)) atol = 1.0d-8 rtol = 1.0d-8 dtol = 1.0d+10 PetscCall(KSPSetTolerances(kspDamage, rtol, atol, dtol, PETSC_DEFAULT_INTEGER, ierr)) PetscCall(KSPSetFromOptions(kspDamage, ierr)) PetscCall(MatDestroy(matDamage, ierr)) end subroutine MEF90DefMechCreateSNESDamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechCreateTAODamage" !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechCreateTAODamage: !!! subroutine MEF90DefMechCreateTAODamage(MEF90DefMechCtx, taoDamage, residual, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tTao), intent(OUT) :: taoDamage type(tVec), intent(IN) :: residual PetscErrorCode, intent(INOUT) :: ierr type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions type(tDM) :: dm type(tMat) :: matDamage type(tKSP) :: kspDamage type(tVec) :: UB, LB PetscReal :: rtol, dtol, atol, stol PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(MEF90DefMechCtx%damageLocal, dm, ierr)) PetscCall(DMCreateMatrix(dm, matDamage, ierr)) PetscCall(MatSetOptionsPrefix(matDamage, "Damage_", ierr)) !! The matrix is not symmetric if the advection vector is /= 0 PetscCall(MatSetOption(matDamage, MAT_SPD, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDamage, MAT_SYMMETRY_ETERNAL, PETSC_TRUE, ierr)) PetscCall(MatSetOption(matDamage, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE, ierr)) PetscCall(MatSetFromOptions(matDamage, ierr)) PetscCall(TAOCreate(MEF90DefMechCtx%MEF90Ctx%Comm, taoDamage, ierr)) PetscCall(TAOSetApplicationContext(taoDamage, MEF90DefMechCtx%PETScCtx, ierr)) ! PetscCall(TAOSetDM(taoDamage,dm,ierr)) PetscCall(TAOSetType(taoDamage, TAOBNTR, ierr)) PetscCall(TAOSetOptionsPrefix(taoDamage, 'Damage_', ierr)) PetscCall(DMCreateGlobalVector(dm, LB, ierr)) PetscCall(VecDuplicate(LB, UB, ierr)) PetscCall(VecSet(LB, 0.0_kr, ierr)) PetscCall(VecSet(UB, 1.0_kr, ierr)) PetscCall(TAOSetVariableBounds(taoDamage, LB, UB, ierr)) PetscCall(VecDestroy(LB, ierr)) PetscCall(VecDestroy(UB, ierr)) PetscCall(TAOSetObjective(taoDamage, MEF90DefMechTAOObjectiveDamage, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(TAOSetGradient(taoDamage, residual, MEF90DefMechTAOGradientDamage, MEF90DefMechCtx%PETScCtx, ierr)) PetscCall(TAOSetHessian(taoDamage, matDamage, matDamage, MEF90DefMechTAOHessianDamage, MEF90DefMechCtx%PETScCtx, ierr)) atol = 1.0d-5 rtol = 1.0d-4 stol = 1.0d-5 PetscCall(TAOSetTolerances(taoDamage, atol, rtol, stol, ierr)) PetscCall(TAOSetFromOptions(taoDamage, ierr)) ! !!! ! !!! Set some KSP options ! !!! PetscCall(TAOGetKSP(taoDamage, kspDamage, ierr)) PetscCall(KSPSetType(kspDamage, KSPSTCG, ierr)) PetscCall(KSPSetInitialGuessNonzero(kspDamage, PETSC_TRUE, ierr)) atol = 1.0d-8 rtol = 1.0d-8 dtol = 1.0d+10 PetscCall(KSPSetTolerances(kspDamage, rtol, atol, dtol, PETSC_DEFAULT_INTEGER, ierr)) PetscCall(KSPSetFromOptions(kspDamage, ierr)) PetscCall(MatDestroy(matDamage, ierr)) end subroutine MEF90DefMechCreateTAODamage #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechUpdateDamageBounds" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechUpdateDamageBounds: !!! subroutine MEF90DefMechUpdateDamageBounds(MEF90DefMechCtx, snesDamage, alpha, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tSNES), intent(INOUT) :: snesDamage type(tVec), intent(IN) :: alpha PetscErrorCode, intent(INOUT) :: ierr type(tDM) :: dm type(tVec) :: LB, UB PetscReal, dimension(:), pointer :: LBPtr PetscInt :: i type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(alpha, dm, ierr)) PetscCall(DMGetGlobalVector(dm, LB, ierr)) PetscCall(DMGetGlobalVector(dm, UB, ierr)) PetscCall(VecSet(UB, 1.0_kr, ierr)) PetscCall(VecCopy(alpha, LB, ierr)) if (MEF90DefMechGlobalOptions%irrevthres > 0.0_kr) then PetscCall(VecGetArray(LB, LBPtr, ierr)) do i = 1, size(LBPtr) if (LBPtr(i) <= MEF90DefMechGlobalOptions%irrevthres) then LBPtr(i) = 0.0_kr end if end do PetscCall(VecRestoreArray(LB, LBPtr, ierr)) end if PetscCall(SNESVISetVariableBounds(snesDamage, LB, UB, ierr)) PetscCall(DMRestoreGlobalVector(dm, LB, ierr)) PetscCall(DMRestoreGlobalVector(dm, UB, ierr)) end subroutine MEF90DefMechUpdateDamageBounds #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechTAOUpdateDamageBounds" !!! author: Blaise Bourdin (2014, bourdin@lsu.edu) !!! author: Alexis Marboeuf (2022, marboeua@mcmaster.ca) !!! !!! MEF90DefMechTAOUpdateDamageBounds: !!! subroutine MEF90DefMechTAOUpdateDamageBounds(MEF90DefMechCtx, taoDamage, alpha, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tTao), intent(INOUT) :: taoDamage type(tVec), intent(IN) :: alpha PetscErrorCode, intent(INOUT) :: ierr type(tDM) :: dm type(tVec) :: LB, UB PetscReal, dimension(:), pointer :: LBPtr PetscInt :: i type(MEF90DefMechGlobalOptions_Type) :: MEF90DefMechGlobalOptions PetscCall(MEF90DefMechGlobalOptionsSetFromOptions(MEF90DefMechCtx%comm, trim(MEF90DefMechCtx%prefix), MEF90DefMechGlobalOptions, ierr)) PetscCall(VecGetDM(alpha, dm, ierr)) PetscCall(DMGetGlobalVector(dm, LB, ierr)) PetscCall(DMGetGlobalVector(dm, UB, ierr)) PetscCall(VecSet(UB, 1.0_kr, ierr)) PetscCall(VecCopy(alpha, LB, ierr)) if (MEF90DefMechGlobalOptions%irrevthres > 0.0_kr) then PetscCall(VecGetArray(LB, LBPtr, ierr)) do i = 1, size(LBPtr) if (LBPtr(i) <= MEF90DefMechGlobalOptions%irrevthres) then LBPtr(i) = 0.0_kr end if end do PetscCall(VecRestoreArray(LB, LBPtr, ierr)) end if PetscCall(TAOSetVariableBounds(taoDamage, LB, UB, ierr)) PetscCall(DMRestoreGlobalVector(dm, LB, ierr)) PetscCall(DMRestoreGlobalVector(dm, UB, ierr)) end subroutine MEF90DefMechTAOUpdateDamageBounds #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechPlasticStrainUpdate" !!! author: Blaise Bourdin (2012-14, bourdin@lsu.edu) !!! !!! MEF90DefMechPlasticStrainUpdate: wraps calls to MEF90DefMechPlasticStrainUpdate from m_MEF90_DefMechPlasticity !!! since overloading cannot be used here !!! subroutine MEF90DefMechPlasticStrainUpdate(MEF90DefMechCtx, plasticStrain, x, PlasticStrainOld, plasticStrainPrevious, cumulatedDissipatedPlasticEnergyVariation, cumulatedDissipatedPlasticEnergyOld, ierr) type(MEF90DefMech_Type), intent(IN) :: MEF90DefMechCtx type(tVec), intent(INOUT) :: plasticStrain type(tVec), intent(IN) :: x, PlasticStrainOld, plasticStrainPrevious, cumulatedDissipatedPlasticEnergyVariation, cumulatedDissipatedPlasticEnergyOld PetscErrorCode, intent(INOUT) :: ierr PetscInt :: dim PetscCall(DMGetDimension(MEF90DefMechCtx%megaDM, dim, ierr)) if (dim == 2) then ! Call MEF90DefMechPlasticStrainUpdate2D(MEF90DefMechCtx,plasticStrain,x,PlasticStrainOld,plasticStrainPrevious,cumulatedDissipatedPlasticEnergyVariation,cumulatedDissipatedPlasticEnergyOld,ierr) else if (dim == 3) then ! Call MEF90DefMechPlasticStrainUpdate3D(MEF90DefMechCtx,plasticStrain,x,PlasticStrainOld,plasticStrainPrevious,cumulatedDissipatedPlasticEnergyVariation,cumulatedDissipatedPlasticEnergyOld,ierr) end if end subroutine MEF90DefMechPlasticStrainUpdate #undef __FUNCT__ #define __FUNCT__ "MEF90DefMechProjectCoordinates_Private" subroutine MEF90DefMechProjectCoordinates_Private(v, ierr) type(tVec), intent(INOUT) :: v PetscErrorCode, intent(INOUT) :: ierr PetscInt :: pStart, pEnd, p, numDof, cNumDof, i type(tDM) :: dm type(tPetscSection) :: coordSection, s type(tVec) :: coordVec, locV PetscScalar, dimension(:), pointer :: coordArray, vArray PetscScalar, dimension(3) :: xyz PetscInt :: dim, pOffset PetscCall(VecGetDM(v, dm, ierr)) PetscCall(DMGetLocalSection(dm, s, ierr)) PetscCall(PetscSectionGetChart(s, pStart, pEnd, ierr)) PetscCall(DMGetCoordinateSection(dm, coordSection, ierr)) PetscCall(DMGetCoordinatesLocal(dm, coordVec, ierr)) PetscCall(DMGetDimension(dm, dim, ierr)) PetscCall(DMGetLocalVector(dm, locV, ierr)) PetscCall(VecGetArray(locV, vArray, ierr)) do p = pStart, pEnd - 1 PetscCall(PetscSectionGetDof(s, p, numDof, ierr)) PetscCall(PetscSectionGetConstraintDof(s, p, cNumDof, ierr)) if ((numDof > 0) .and. (cNumDof == 0)) then !! trick: the coordinate of a point is the average of the coordinates of the points in its closure PetscCall(DMPlexVecGetClosure(dm, coordSection, coordVec, p, PETSC_NULL_INTEGER, coordArray, ierr)) do i = 1, dim xyz(i) = sum(coordArray(i:size(coordArray):dim)) * dim / size(coordArray) end do PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordVec, p, PETSC_NULL_INTEGER, coordArray, ierr)) PetscCall(PetscSectionGetOffset(s, p, pOffset, ierr)) do i = 1, numDof vArray(pOffset + i) = xyz(i) end do end if end do PetscCall(VecRestoreArray(locV, vArray, ierr)) PetscCall(DMLocalToGlobalBegin(dm, locV, INSERT_VALUES, v, ierr)) PetscCall(DMLocalToGlobalEnd(dm, locV, INSERT_VALUES, v, ierr)) PetscCall(DMRestoreLocalVector(dm, locV, ierr)) end subroutine MEF90DefMechProjectCoordinates_Private end module m_MEF90_DefMech