Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions ansys_transient_structural_command_snippet.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
! ---------------------------------------------------------------------------
! Example ANSYS Mechanical APDL command snippet for Transient Structural.
! Inside the GUI: insert a "Commands (APDL)" object under
! Analysis > Environment > Commands
! then paste this block. You can also run it as a standalone APDL input file.
! This snippet assumes a USERMAT material has been defined elsewhere and
! a Transient Structural analysis is active.
! ---------------------------------------------------------------------------

/prep7
! Define element type (example: SOLID186 for large deformation)
! NOTE: Large deformation is controlled by NLGEOM,ON (not SOLID186 KEYOPT(3)).
! If your Mechanical GUI already inserted a KEYOPT(3)=2 line, remove it.
et,1,186

! Define material with USERMAT
mp,ex,1,1.0 ! Dummy (not used by USERMAT)
mp,nuxy,1,0.3 ! Dummy (not used by USERMAT)

! USERMAT definition: TB,USER
! TB,USER,mat_id,1,number_of_properties
! For PROPS: mu, kappa
TB,USER,1,1,2
TBDATA,1,1.0e6,1.0e9

! Geometry / mesh assumed defined here

finish

/solu
antype,trans ! Transient Structural
trnopt,full ! Full transient
nlgeom,on ! Large deformation
kbc,1 ! Ramped loads

! Time settings
TIME,1.0
DELTIM,0.01,0.001,0.1

! Apply loads / BCs (example placeholder)
! d,all,ux,0
! f,node_id,fx,100

! If elements distort under large deformation, consider:
! - Smaller time steps (reduce initial/min DELTIM)
! - Improved mesh quality/aspect ratios
! - Switching to EQSLV,SPARSE for reduced integration bricks
! - Ramped loading (KBC,1 already set)
! Solve for two steps
nsubst,100,10,200
solve
finish
270 changes: 270 additions & 0 deletions neo_hookean_user_mat.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
! ---------------------------------------------------------------------------
! ANSYS USERMAT: Large-deformation Neo-Hookean (incompressible / penalty)
! ---------------------------------------------------------------------------
! This implementation follows the common USERMAT argument list used by ANSYS
! Mechanical APDL when TB,USER is enabled with large-deformation kinematics.
! If your ANSYS version uses a different interface, adjust the subroutine
! signature accordingly.
!
! Material parameters (PROPS):
! PROPS(1) = shear modulus, mu
! PROPS(2) = augmented Lagrangian bulk parameter, kappa
! PROPS(3) = optional ramp time for kappa (same time units as TIME)
!
! State variables (STATEV):
! STATEV(1) = pressure-like Lagrange multiplier p
!
! Notes:
! - This is a fully incompressible (augmented Lagrangian) formulation.
! The pressure-like variable p is stored in STATEV(1) and updated as
! p_{n+1} = p_n + kappa * (J - 1).
! - Provide NSTATV >= 1 in your material definition.
!
! Voigt order (ANSYS):
! STRESS(1:6) = [Sxx, Syy, Szz, Sxy, Syz, Sxz]
! ---------------------------------------------------------------------------
SUBROUTINE USERMAT(
& STRESS,STATEV,DDSDDE,SSE,SPD,SCD,RPL,DDSDDT,DRPLDE,DRPLDT,
& STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED,CMNAME,
& NDI,NSHR,NTENS,NSTATV,PROPS,NPROPS,COORDS,DROT,PNEWDT,
& CELENT,DFGRD0,DFGRD1,NOEL,NPT,LAYER,KSPT,KSTEP,KINC )

IMPLICIT NONE

! Arguments
CHARACTER*80 CMNAME
INTEGER NDI,NSHR,NTENS,NSTATV,NPROPS
INTEGER NOEL,NPT,LAYER,KSPT,KSTEP,KINC
DOUBLE PRECISION STRESS(NTENS),STATEV(NSTATV),DDSDDE(NTENS,NTENS)
DOUBLE PRECISION SSE,SPD,SCD,RPL,DDSDDT(NTENS,NTENS)
DOUBLE PRECISION DRPLDE(NTENS),DRPLDT
DOUBLE PRECISION STRAN(NTENS),DSTRAN(NTENS)
DOUBLE PRECISION TIME(2),DTIME,TEMP,DTEMP,PREDEF,DPRED
DOUBLE PRECISION PROPS(NPROPS),COORDS(3),DROT(3,3),PNEWDT,CELENT
DOUBLE PRECISION DFGRD0(3,3),DFGRD1(3,3)

! Locals
DOUBLE PRECISION F(3,3),B(3,3),CMAT(3,3),CMATINV(3,3),I3(3,3)
DOUBLE PRECISION S2PK(3,3)
DOUBLE PRECISION MU,KAPPA,J,TRB,P,KRAMP
DOUBLE PRECISION LAMBDA,I1BAR,PSI
DOUBLE PRECISION CWORK(3,3),SPERT(3,3),SMINUS(3,3)
DOUBLE PRECISION EPS,DC,DE
DOUBLE PRECISION MAT_DET3
EXTERNAL MAT_INV3
INTEGER I,JIDX

! Initialize identity
CALL MAT_IDENTITY(I3)

! Deformation gradient at end of step
F = DFGRD1

! Left Cauchy-Green tensor: B = F * F^T
CALL MAT_MATMULT(F, TRANSPOSE(F), B)
! Right Cauchy-Green tensor: C = F^T * F
CALL MAT_MATMULT(TRANSPOSE(F), F, CMAT)

! Determinant of F
J = MAT_DET3(F)

! Material properties
MU = PROPS(1)
IF (NPROPS .GE. 2) THEN
KAPPA = PROPS(2)
ELSE
KAPPA = 1.0D6 * MU
END IF
KRAMP = KAPPA
IF (NPROPS .GE. 3) THEN
IF (PROPS(3) .GT. 0.0D0) THEN
KRAMP = KAPPA * MIN(1.0D0, TIME(1) / PROPS(3))
END IF
END IF
P = 0.0D0
IF (NSTATV .GE. 1) THEN
P = STATEV(1)
END IF

! 2nd PK stress (Total Lagrangian, incompressible)
! S = mu*J^(-2/3) * (I - (I1bar/3)*Cinv) + p * Cinv
CALL NEOHOOK_S2PK(CMAT, MU, P, S2PK, I1BAR)

! Strain energy density (Neo-Hookean, deviatoric only)
PSI = 0.5D0*MU*(I1BAR - 3.0D0)
SSE = PSI

! Fill STRESS (Voigt) with 2nd PK stress (Total Lagrangian)
STRESS(1) = S2PK(1,1)
STRESS(2) = S2PK(2,2)
STRESS(3) = S2PK(3,3)
STRESS(4) = S2PK(1,2)
STRESS(5) = S2PK(2,3)
STRESS(6) = S2PK(1,3)
Comment on lines +97 to +103
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard Voigt writes for non-3D NTENS

This USERMAT assumes a 3D Voigt layout and writes STRESS(5) and STRESS(6) unconditionally. In ANSYS, 2D elements (plane strain/stress) use NTENS=4, so this will index past the end of STRESS (and later DDSDDE in the 1..6 loop), which can corrupt memory or crash the solver when the same material is used with 2D elements. If this routine is intended to be reusable, it should either restrict itself to 3D-only usage or branch on NTENS/NDI/NSHR to avoid writing components that don’t exist.

Useful? React with 👍 / 👎.


! Consistent tangent via numerical differentiation in Green-Lagrange strain
CALL ZERO_TANGENT(DDSDDE, NTENS)
EPS = 1.0D-8
DO JIDX = 1,6
DC = EPS
CWORK = CMAT
IF (JIDX .EQ. 1) THEN
CWORK(1,1) = CWORK(1,1) + DC
ELSEIF (JIDX .EQ. 2) THEN
CWORK(2,2) = CWORK(2,2) + DC
ELSEIF (JIDX .EQ. 3) THEN
CWORK(3,3) = CWORK(3,3) + DC
ELSEIF (JIDX .EQ. 4) THEN
CWORK(1,2) = CWORK(1,2) + DC
CWORK(2,1) = CWORK(2,1) + DC
ELSEIF (JIDX .EQ. 5) THEN
CWORK(2,3) = CWORK(2,3) + DC
CWORK(3,2) = CWORK(3,2) + DC
ELSE
CWORK(1,3) = CWORK(1,3) + DC
CWORK(3,1) = CWORK(3,1) + DC
END IF
CALL NEOHOOK_S2PK(CWORK, MU, P, SPERT, I1BAR)

CWORK = CMAT
IF (JIDX .EQ. 1) THEN
CWORK(1,1) = CWORK(1,1) - DC
ELSEIF (JIDX .EQ. 2) THEN
CWORK(2,2) = CWORK(2,2) - DC
ELSEIF (JIDX .EQ. 3) THEN
CWORK(3,3) = CWORK(3,3) - DC
ELSEIF (JIDX .EQ. 4) THEN
CWORK(1,2) = CWORK(1,2) - DC
CWORK(2,1) = CWORK(2,1) - DC
ELSEIF (JIDX .EQ. 5) THEN
CWORK(2,3) = CWORK(2,3) - DC
CWORK(3,2) = CWORK(3,2) - DC
ELSE
CWORK(1,3) = CWORK(1,3) - DC
CWORK(3,1) = CWORK(3,1) - DC
END IF
CALL NEOHOOK_S2PK(CWORK, MU, P, SMINUS, I1BAR)

IF (JIDX .GE. 4) THEN
DE = DC
ELSE
DE = 0.5D0 * DC
END IF
DDSDDE(1,JIDX) = (SPERT(1,1) - SMINUS(1,1)) / (2.0D0 * DE)
DDSDDE(2,JIDX) = (SPERT(2,2) - SMINUS(2,2)) / (2.0D0 * DE)
DDSDDE(3,JIDX) = (SPERT(3,3) - SMINUS(3,3)) / (2.0D0 * DE)
DDSDDE(4,JIDX) = (SPERT(1,2) - SMINUS(1,2)) / (2.0D0 * DE)
DDSDDE(5,JIDX) = (SPERT(2,3) - SMINUS(2,3)) / (2.0D0 * DE)
DDSDDE(6,JIDX) = (SPERT(1,3) - SMINUS(1,3)) / (2.0D0 * DE)
END DO

! Update pressure-like multiplier (augmented Lagrangian)
IF (NSTATV .GE. 1) THEN
STATEV(1) = P + KRAMP * (J - 1.0D0)
END IF

RETURN
END SUBROUTINE USERMAT

! ---------------------------------------------------------------------------
SUBROUTINE MAT_IDENTITY(I3)
IMPLICIT NONE
DOUBLE PRECISION I3(3,3)
I3 = 0.0D0
I3(1,1) = 1.0D0
I3(2,2) = 1.0D0
I3(3,3) = 1.0D0
END SUBROUTINE MAT_IDENTITY

! ---------------------------------------------------------------------------
SUBROUTINE MAT_MATMULT(A,B,C)
IMPLICIT NONE
DOUBLE PRECISION A(3,3),B(3,3),C(3,3)
INTEGER I,J,K
C = 0.0D0
DO I=1,3
DO J=1,3
DO K=1,3
C(I,J) = C(I,J) + A(I,K) * B(K,J)
END DO
END DO
END DO
END SUBROUTINE MAT_MATMULT

! ---------------------------------------------------------------------------
SUBROUTINE MAT_INV3(A, AINV)
IMPLICIT NONE
DOUBLE PRECISION A(3,3),AINV(3,3)
DOUBLE PRECISION DET
DOUBLE PRECISION MAT_DET3

DET = MAT_DET3(A)
AINV(1,1) = (A(2,2)*A(3,3)-A(2,3)*A(3,2)) / DET
AINV(1,2) = -(A(1,2)*A(3,3)-A(1,3)*A(3,2)) / DET
AINV(1,3) = (A(1,2)*A(2,3)-A(1,3)*A(2,2)) / DET
AINV(2,1) = -(A(2,1)*A(3,3)-A(2,3)*A(3,1)) / DET
AINV(2,2) = (A(1,1)*A(3,3)-A(1,3)*A(3,1)) / DET
AINV(2,3) = -(A(1,1)*A(2,3)-A(1,3)*A(2,1)) / DET
AINV(3,1) = (A(2,1)*A(3,2)-A(2,2)*A(3,1)) / DET
AINV(3,2) = -(A(1,1)*A(3,2)-A(1,2)*A(3,1)) / DET
AINV(3,3) = (A(1,1)*A(2,2)-A(1,2)*A(2,1)) / DET
END SUBROUTINE MAT_INV3

! ---------------------------------------------------------------------------
SUBROUTINE NEOHOOK_S2PK(CMAT, MU, P, S2PK, I1BAR)
IMPLICIT NONE
DOUBLE PRECISION CMAT(3,3), S2PK(3,3)
DOUBLE PRECISION MU, P, I1BAR
DOUBLE PRECISION CMATINV(3,3), I3(3,3), J, TRC
DOUBLE PRECISION MAT_DET3
EXTERNAL MAT_INV3

CALL MAT_IDENTITY(I3)
J = DSQRT(MAT_DET3(CMAT))
TRC = CMAT(1,1) + CMAT(2,2) + CMAT(3,3)
I1BAR = TRC * J**(-2.0D0/3.0D0)
CALL MAT_INV3(CMAT, CMATINV)
S2PK = MU * J**(-2.0D0/3.0D0) * (I3 - (I1BAR/3.0D0) * CMATINV)
S2PK = S2PK + P * CMATINV
END SUBROUTINE NEOHOOK_S2PK

! ---------------------------------------------------------------------------
DOUBLE PRECISION FUNCTION MAT_DET3(A)
IMPLICIT NONE
DOUBLE PRECISION A(3,3)
MAT_DET3 = A(1,1)*(A(2,2)*A(3,3)-A(2,3)*A(3,2))
& - A(1,2)*(A(2,1)*A(3,3)-A(2,3)*A(3,1))
& + A(1,3)*(A(2,1)*A(3,2)-A(2,2)*A(3,1))
END FUNCTION MAT_DET3

! ---------------------------------------------------------------------------
SUBROUTINE ZERO_TANGENT(DDSDDE, NTENS)
IMPLICIT NONE
INTEGER NTENS, I, J
DOUBLE PRECISION DDSDDE(NTENS,NTENS)
DO I=1,NTENS
DO J=1,NTENS
DDSDDE(I,J) = 0.0D0
END DO
END DO
END SUBROUTINE ZERO_TANGENT

! ---------------------------------------------------------------------------
SUBROUTINE ISOTROPIC_TANGENT(DDSDDE, LAMBDA, MU)
IMPLICIT NONE
DOUBLE PRECISION DDSDDE(6,6), LAMBDA, MU

! 3D isotropic elasticity in Voigt order
DDSDDE(1,1) = LAMBDA + 2.0D0*MU
DDSDDE(2,2) = LAMBDA + 2.0D0*MU
DDSDDE(3,3) = LAMBDA + 2.0D0*MU
DDSDDE(1,2) = LAMBDA
DDSDDE(1,3) = LAMBDA
DDSDDE(2,1) = LAMBDA
DDSDDE(2,3) = LAMBDA
DDSDDE(3,1) = LAMBDA
DDSDDE(3,2) = LAMBDA
DDSDDE(4,4) = MU
DDSDDE(5,5) = MU
DDSDDE(6,6) = MU
END SUBROUTINE ISOTROPIC_TANGENT