UPF in PyMAPDL#

以下是 Python UPF 示例:

Python UserMat subroutine#

本例模拟了一个使用 3D 单元建模的块。文件 usermat.py 中的用户材料相当于线性弹性材料。 块体受到单轴压缩。将最终变形与理论结果进行比较。

Input data#

/batch,list
/title,upf-py1s, 'test usermat.py with 3D elements'

/prep7
/upf,'usermat.py'
tb,user,1,,2
tbdata,1,1e5, 0.3    ! E, Poisson

et,1,185

block,0,1,0,1,0,1
esize,1
mshape,0,3D
vmesh,all
elist

nsel,s,loc,x,0
d,all,ux

nsel,s,loc,y,0
d,all,uy

nsel,s,loc,z,0
d,all,uz,

allsel,all
finish

/solu

time,1
deltime,0.1
eresx,no
nsel,s,loc,x,1
!d,all,ux,-0.01
sf,all,pres,1000        ! pressure on x-axis
allsel,all

outres,all,all

solve

finish
/POST1
set,last
esel,s,elem,,1
/output
presol,s
presol,epel
/com, expected results: Sx=-1000, epel_x=-1e-2
finish
/exit,nosave

usermat.py file#

import grpc
import sys
import math
import numpy as np
from mapdl import *


class MapdlUserService(MapdlUser_pb2_grpc.MapdlUserServiceServicer):
    #   #################################################################
    def UserMat(self, request, context):
        ncomp = request.ncomp
        nDirect = request.nDirect

        response = MapdlUser_pb2.UserMatResponse()

        response.stress[:] = request.stress[:]
        response.ustatev[:] = request.ustatev[:]
        response.sedEl = request.sedEl
        response.sedPl = request.sedPl
        response.epseq = request.epseq
        response.epsPl[:] = request.epsPl[:]
        response.var0 = request.var0
        response.var3 = request.var3
        response.var4 = request.var4
        response.var5 = request.var5
        response.var6 = request.var6
        response.var7 = request.var7

        if ncomp > 4:  # ***    3d, plane strain and axisymmetric example
            usermat3d(request, context, response)
        elif nDirect == 2 and ncomp == 3:  # ***    plane stress example
            usermatps(request, context, response)
        elif ncomp == 3:  # ***    3d beam example
            usermatbm(request, context, response)
        elif ncomp == 1:  # ***    1d beam example
            usermat1d(request, context, response)

        return response


def usermat3d(request, context, response):
    ZERO = 0.0
    HALF = 0.5
    THIRD = 1.0 / 3.0
    ONE = 1.0
    TWO = 2.0
    SMALL = 1.0e-08
    sqTiny = 1.0e-20
    ONEDM02 = 1.0e-02
    ONEDM05 = 1.0e-05
    ONEHALF = 1.5
    TWOTHIRD = 2.0 / 3.0
    mcomp = 6

    G = [1.0, 1.0, 1.0, 0.0, 0.0, 0.0]

    db.start()  # Connect to the MAPDL DB gRPC Server
    ncomp = request.ncomp

    # *** get Young's modulus and Poisson's ratio
    young = request.prop[0]
    posn = request.prop[1]
    twoG = young / (ONE + posn)
    elast1 = young * posn / ((1.0 + posn) * (1.0 - TWO * posn))
    elast2 = HALF * twoG

    #
    # *** calculate elastic stiffness matrix (3d)
    #
    dsdeEl = np.zeros((6, 6))

    dsdeEl[0, 0] = (elast1 + TWO * elast2) * G[0] * G[0]
    dsdeEl[0, 1] = elast1 * G[0] * G[1] + elast2 * TWO * G[3] * G[3]
    dsdeEl[0, 2] = elast1 * G[0] * G[2] + elast2 * TWO * G[4] * G[4]
    dsdeEl[0, 3] = elast1 * G[0] * G[3] + elast2 * TWO * G[0] * G[3]
    dsdeEl[0, 4] = elast1 * G[0] * G[4] + elast2 * TWO * G[0] * G[4]
    dsdeEl[0, 5] = elast1 * G[0] * G[5] + elast2 * TWO * G[3] * G[4]

    dsdeEl[1, 1] = (elast1 + TWO * elast2) * G[1] * G[1]
    dsdeEl[1, 2] = elast1 * G[1] * G[2] + elast2 * TWO * G[5] * G[5]
    dsdeEl[1, 3] = elast1 * G[1] * G[3] + elast2 * TWO * G[0] * G[3]
    dsdeEl[1, 4] = elast1 * G[1] * G[4] + elast2 * TWO * G[0] * G[4]
    dsdeEl[1, 5] = elast1 * G[1] * G[5] + elast2 * TWO * G[1] * G[5]

    dsdeEl[2, 2] = (elast1 + TWO * elast2) * G[2] * G[2]
    dsdeEl[2, 3] = elast1 * G[2] * G[3] + elast2 * TWO * G[4] * G[5]
    dsdeEl[2, 4] = elast1 * G[2] * G[4] + elast2 * TWO * G[4] * G[2]
    dsdeEl[2, 5] = elast1 * G[2] * G[5] + elast2 * TWO * G[5] * G[2]

    dsdeEl[3, 3] = elast1 * G[3] * G[3] + elast2 * (G[0] * G[1] + G[3] * G[3])
    dsdeEl[3, 4] = elast1 * G[3] * G[4] + elast2 * (G[0] * G[5] + G[4] * G[3])
    dsdeEl[3, 5] = elast1 * G[3] * G[5] + elast2 * (G[3] * G[5] + G[4] * G[1])

    dsdeEl[4, 4] = elast1 * G[4] * G[4] + elast2 * (G[0] * G[2] + G[4] * G[4])
    dsdeEl[4, 5] = elast1 * G[4] * G[5] + elast2 * (G[3] * G[2] + G[4] * G[5])

    dsdeEl[5, 5] = elast1 * G[5] * G[5] + elast2 * (G[1] * G[2] + G[5] * G[5])

    for i in range(0, 5):
        for j in range(i + 1, 6):
            dsdeEl[j, i] = dsdeEl[i, j]

    Strain = np.zeros(ncomp)
    Strain[0:ncomp] = request.Strain[0:ncomp]
    dStrain = np.zeros(ncomp)
    dStrain[0:ncomp] = request.dStrain[0:ncomp]

    #
    # *** calculate the stress and
    #     copy elastic moduli dsdeEl to material Jacobian matrix

    strainEl = np.copy(Strain)  # strainEl = Strain
    strainEl = np.add(strainEl, dStrain)  # strainEl += dStrain

    dsdePl = np.copy(dsdeEl)
    sigElp = np.zeros(ncomp)
    sigElp = dsdeEl.dot(strainEl)

    response.stress[:] = sigElp
    dsdePl.shape = 6 * 6
    response.dsdePl[:] = dsdePl

    return response


if __name__ == "__main__":
    upf.launch(sys.argv[0])

Python UsrShift subroutine#

本示例描述了一种 Prony 粘塑性材料块,用户可根据 Tool-Narayanaswamy 函数定义位移函数。 在一端施加单轴拉力,并在 280 K 的恒定均匀温度下保持 15 秒。获得最终应力以验证应力松弛。

Input data#

/batch,list
/title,upf-py10s, 'test usrshift.py'

/prep7
/upf,'usrshift.py'

n1=60
n2=n1*10
n3=n1
dy = 0.0045
fact=2
t1end=30.0/fact
alpha = 0.5
tau = 2.0
a1 = alpha          ! participating factor for el182, 183
t1 = tau
c1 = a1/a1          ! participating factor for el88

tr = 0
theta = 280
toffst,273
tunif, theta
tref,0
b1 = log(fact)*(273+tr)*(273+theta)/(theta-tr)
b2 = 1
b11=b1/273/273

young = 20e5
poiss = 0.3
G0 = young/2/(1+poiss)
K0 = young/3/(1-2*poiss)

! material 1                ! rate-dependent vpl
mp,ex,1,young
mp,nuxy,1,0.3
tb,prony,1,,1,shear         ! define viscousity parameters
tbdata,1,a1,t1
tb,prony,1,,1,bulk          ! define viscousity parameters
tbdata,1,a1,t1
tb,shift,1,,2,100           ! Tool-Narayanaswamy shift function
tbdata,1,tr,b11,

! FE model and mesh

et,1,186
mat,1
block,0,1,0,1,0,1
esize,1
vmesh,1

nall
nsel,s,loc,x
d,all,ux
nall
nsel,s,loc,y
d,all,uy
nall
nsel,s,loc,z
d,all,uz

/solu
nlgeom,on
cnvtol,u,,1.0e-8
cnvtol,f,,1.0e-6
nsel,s,loc,y,1.000
d,all,uy,dy
nall
time,1.0e-8
nsubst,1,1,1
outres,all,-10
solve

nsel,s,loc,y,1.000
time,t1end
d,all,uy,dy
nall
nsubst,n1,n2,n3
outres,all,-10
outpr,all,last
solve

finish

/post1
set,last
/output
presol,s

/com, expected results   Sy=4490.0

finish
/exit,nosave

usrshift.py file#

import grpc
import sys
import math
from mapdl import *


class MapdlUserService(MapdlUser_pb2_grpc.MapdlUserServiceServicer):
    #   #################################################################

    def UsrShift(self, request, context):
        response = MapdlUser_pb2.UsrShiftResponse()
        one = 1.0
        half = 0.5
        quart = 0.25

        tref = request.propsh[0]
        temp = request.temp
        timinc = request.timinc
        dtemp = request.dtemp
        nTerms = request.nTerms

        thalf = temp - dtemp * half - tref
        t3quart = temp - dtemp * quart - tref

        c1 = 0.0
        c2 = 0.0

        for i in range(nTerms - 1):
            c1 = c1 + request.propsh[i + 1] * thalf ** (i + 1)
            c2 = c2 + request.propsh[i + 1] * t3quart ** (i + 1)

        dxi = math.exp(c1) * timinc
        dxihalf = math.exp(c2) * timinc * half

        response.dxi = dxi
        response.dxihalf = dxihalf

        return response


if __name__ == "__main__":
    upf.launch(sys.argv[0])

Python UserHyper subroutine#

该示例模拟了简单单轴拉伸下的块体。该块由用户定义的超弹性材料制成,与 Arruda-Boyce 超弹性材料相同。包含大变形效应。打印出最终应力,以便与参考值进行比较。

Input data#

/BATCH,LIST
/title, upf-py16s, 'test UserHyper.py with MAPDL'
/com, displacement-controlled uniaxial tension test for Boyce material model

/prep7

/upf,'userhyper.py'
tb,hyper,1,,,user
tbdata,1,2/100,0.2,2.8284

et,1,185

block,0,1,0,1,0,1
esize,1
vmesh,1

nsel,s,loc,x
d,all,ux
nsel,s,loc,y
d,all,uy
nsel,s,loc,z
d,all,uz
nall

nsel,s,loc,x,1.0
d,all,ux,0.3

nall

/solu

nlgeom,on
time,1
nsubst,5,20,5

/out,scratch
solve

/post1
/output

set,1,last
presol,s,x

/com, 'expected results from equivalent userhyper.F'
/com,    NODE     SX           SY           SZ           SXY          SYZ
/com,       2  0.20118      0.32054E-003 0.32054E-003 0.13752E-015 0.67903E-017
/com,       4  0.20118      0.32054E-003 0.32054E-003 0.13776E-015 0.40293E-017
/com,       3  0.20118      0.32054E-003 0.32054E-003 0.50933E-015-0.10653E-014
/com,       1  0.20118      0.32054E-003 0.32054E-003 0.50909E-015-0.54682E-015
/com,       5  0.20118      0.32054E-003 0.32054E-003-0.15222E-015 0.58245E-015
/com,       6  0.20118      0.32054E-003 0.32054E-003-0.15313E-015 0.10856E-014
/com,       7  0.20118      0.32054E-003 0.32054E-003-0.55356E-015 0.17421E-016
/com,       8  0.20118      0.32054E-003 0.32054E-003-0.55265E-015 0.28848E-016

finish
/exit,nosave

userhyper.py file#

import grpc
import sys
from mapdl import *
import math
import numpy as np

firstcall = 1


class MapdlUserService(MapdlUser_pb2_grpc.MapdlUserServiceServicer):
    #   #################################################################
    def UserHyper(self, request, context):
        global firstcall
        if firstcall == 1:
            print(">> Using Python UserHyper function\n")
            firstcall = 0

        prophy = np.copy(request.prophy)
        invar = np.copy(request.invar)

        response = MapdlUser_pb2.UserHyperResponse()

        ZERO = 0.0
        ONE = 1.0
        HALF = 0.5
        TWO = 2.0
        THREE = 3.0
        TOLER = 1.0e-12

        ci = (
            0.5,
            0.05,
            0.104761904761905e-01,
            0.271428571428571e-02,
            0.770315398886827e-03,
        )

        i1 = invar[0]
        jj = invar[2]
        mu = prophy[1]
        lm = prophy[2]
        oD1 = prophy[0]
        i1i = ONE
        im1 = ONE / i1
        t3i = ONE
        potential = ZERO
        pInvDer = np.zeros(9)

        for i in range(5):
            ia = i + 1
            t3i = t3i * THREE
            i1i = i1i * i1
            i1i1 = i1i * im1
            i1i2 = i1i1 * im1
            lm2 = ci[i] / (lm ** (TWO * (ia - ONE)))
            potential = potential + lm2 * (i1i - t3i)
            pInvDer[0] = pInvDer[0] + lm2 * ia * i1i1
            pInvDer[2] = pInvDer[2] + lm2 * ia * (ia - ONE) * i1i2

        potential = potential * mu
        pInvDer[0] = pInvDer[0] * mu
        pInvDer[2] = pInvDer[2] * mu

        j1 = ONE / jj
        pInvDer[7] = ZERO
        pInvDer[8] = ZERO

        if oD1 > TOLER:
            oD1 = ONE / oD1
            incomp = False
            potential = potential + oD1 * ((jj * jj - ONE) * HALF - math.log(jj))
            pInvDer[7] = oD1 * (jj - j1)
            pInvDer[8] = oD1 * (ONE + j1 * j1)

        response.potential = potential
        response.incomp = incomp
        response.pInvDer[:] = pInvDer[:]

        return response


if __name__ == "__main__":
    upf.launch(sys.argv[0])