.. _python_upf_examples: UPF in PyMAPDL ^^^^^^^^^^^^^^ The following Python UPF examples are available: * `Python UserMat subroutine`_ * `Python UsrShift subroutine`_ * `Python UserHyper subroutine`_ Python ``UserMat`` subroutine ***************************** This example simulates a block modeled with 3D elements. The user material in the ``usermat.py`` file is equivalent to linear elastic. The block is under uniaxial compression. The final deformation is compared with the theoretical result. Input data ++++++++++ .. code:: apdl /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 +++++++++++++++++++ .. code:: python 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 ****************************** This example describes a block of Prony viscoplastic material with a user-defined shift function following a Tool-Narayanaswamy shift function. Uniaxial tension is applied on one end and held for 15 seconds with a constant 280 K uniform temperature. The final stress is obtained to verify stress relaxation. Input data ++++++++++ .. code:: apdl /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 ++++++++++++++++++++ .. code:: python 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 ******************************* This example models a block under simple uniaxial tension. The block is made of a user-defined hyper material that is identical to Arruda-Boyce hyperelasticity. Large deformation effects are included. The final stress is printed for comparison against the reference. Input data ++++++++++ .. code:: apdl /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 +++++++++++++++++++++ .. code:: python 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])