diff --git a/doc/changelog.d/4197.maintenance.md b/doc/changelog.d/4197.maintenance.md new file mode 100644 index 0000000000..1e1a38abb9 --- /dev/null +++ b/doc/changelog.d/4197.maintenance.md @@ -0,0 +1 @@ +Remove Python UPF examples and related documentation diff --git a/doc/source/examples/extended_examples/Python_UPF/python_upf_examples.rst b/doc/source/examples/extended_examples/Python_UPF/python_upf_examples.rst deleted file mode 100644 index 53a8565349..0000000000 --- a/doc/source/examples/extended_examples/Python_UPF/python_upf_examples.rst +++ /dev/null @@ -1,543 +0,0 @@ -.. _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]) - diff --git a/doc/source/examples/extended_examples/index.rst b/doc/source/examples/extended_examples/index.rst index 7815c184c5..3cfd775b05 100644 --- a/doc/source/examples/extended_examples/index.rst +++ b/doc/source/examples/extended_examples/index.rst @@ -13,8 +13,6 @@ with other programs, libraries, and features in development. +------------------------------------------------------+--------------------------------------------------------------------------------------------+ | :ref:`extended_example01` | Demonstrates the interoperability between PyMAPDL and the `Gmsh `_ meshing library. | +------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| :ref:`python_upf_examples` | Demonstrates the interoperability between user-programmable functions in MAPDL and Python. | -+------------------------------------------------------+--------------------------------------------------------------------------------------------+ | :ref:`krylov_example` | Demonstrates the usage of the Krylov method for solving a customized harmonic analysis. | +------------------------------------------------------+--------------------------------------------------------------------------------------------+ | :ref:`dash_example` | Demonstrates the use of PyMAPDL with Dash. | @@ -40,7 +38,6 @@ with other programs, libraries, and features in development. Cart-Pole Simulation ex_01-gmsh_example/ex_01-gmsh_example.rst - Python_UPF/python_upf_examples.rst Krylov/krylov_example.rst dash/dash_example.rst executable/executable.rst diff --git a/doc/source/user_guide/index.rst b/doc/source/user_guide/index.rst index c1b1957190..c53f69d485 100644 --- a/doc/source/user_guide/index.rst +++ b/doc/source/user_guide/index.rst @@ -42,7 +42,6 @@ This section provides a general overview of PyMAPDL and how you use it. :caption: Advanced xpl - upf krylov .. toctree:: diff --git a/doc/source/user_guide/mapdl.rst b/doc/source/user_guide/mapdl.rst index fceee2a4e3..7a0f93502f 100644 --- a/doc/source/user_guide/mapdl.rst +++ b/doc/source/user_guide/mapdl.rst @@ -957,6 +957,9 @@ Here are some examples: - The ``*IF`` command can be replaced with a Python ``if`` statement. - The ``*CREATE`` and ``*USE`` commands can be replaced with calls to another Python function or module. +The User Programmable Features (UPF) are not compatible with MAPDL running through PyMAPDL, hence +the related command such as ``/UPF`` are not supported. + Other commands do not make sense in a non-GUI session. For example, the ``/ERASE`` and ``ERASE`` commands that clear the graphics screen are not needed in a non-GUI session. @@ -972,7 +975,6 @@ which returns the following warning: is ignored. - Table-1_ Comprehensive information on commands that are unavailable .. _Table-1: @@ -1030,7 +1032,7 @@ Table-1_ Comprehensive information on commands that are unavailable .. note:: - * **Interactive** means there is a method in MAPDL, such as the + * **Interactive** means there is a method, such as the :func:`Mapdl.prep7() ` method. * **Non-interactive** means it is run inside a :attr:`Mapdl.non_interactive ` context block, diff --git a/doc/source/user_guide/upf.rst b/doc/source/user_guide/upf.rst deleted file mode 100644 index 4f1bd6823d..0000000000 --- a/doc/source/user_guide/upf.rst +++ /dev/null @@ -1,300 +0,0 @@ -.. _python_upf: - - -Using Python to code UPF subroutines -==================================== - -As an alternative to compiled languages like C and Fortran, you can use the -Python language to code user programmable subroutines. A subset of the -documented UPF subroutines support the Python UPF capability. For more information, -see `Supported UPF subroutines`_). - -You must install a Python distribution before using this feature. Python 3.10 -through Python 3.13 are supported. - -Python UPFs are only supported on Linux. - -You are strongly advised to start your code based on one of the examples in -`Python UPF examples`_. In your Python code, you can make use of standard -Python libraries like NumPy. - -These topics are available: - -* `Supported UPF subroutines`_ -* `Python UPF methodology`_ -* `Accessing the database from the Python code`_ -* `Python UPF limitations`_ -* `Python UPF examples`_ - - -Supported UPF subroutines -------------------------- - -A subset of the entire set of available UPF subroutines supports Python coding. The following -table lists those that are supported. - -**Table 1: Python support for subroutines** - - -+---------------------------------------+-----------------------------------------------------------------------------+ -| **Subroutine** | **Fortran description** | -+=======================================+=============================================================================+ -| **Material behavior** | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UserMat`` | Subroutine ``UserMat`` (Creating Your Own Material Model) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UserMatTh`` | Subroutine ``UserMatTh`` (Creating Your Own Thermal Material Model) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UserHyper`` | Subroutine ``UserHyper`` (Writing Your Own Isotropic Hyperelasticity Laws) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UserCreep`` | Subroutine ``UserCreep`` (Defining Creep Material Behavior) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| **Modifying and Monitoring Elements** | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UsrShift`` | Subroutine ``UsrShift`` (Calculating Pseudotime Time Increment) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UTimeInc`` | Subroutine ``UTimeInc`` (Overriding the Program-Determined Time Step) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UCnvrg`` | Subroutine ``UCnvrg`` (Overriding the Program-Determined Convergence) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| **Customizing loads** | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``usrefl`` | Subroutine ``usrefl`` (Changing Scalar Fields to User-Defined Values) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``userpr`` | Subroutine ``userpr`` (Changing Element Pressure Information) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``usercv`` | Subroutine ``usercv`` (Changing Element Face Convection Surface Information)| -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``userfx`` | Subroutine ``userfx`` (Changing Element Face Heat Flux Surface Information) | -+---------------------------------------+-----------------------------------------------------------------------------+ -| **Accessing subroutines** | -+---------------------------------------+-----------------------------------------------------------------------------+ -| ``UanBeg`` / ``UanFin`` | Access at the beginning and end of various operations | -| | | -| ``USolBeg`` / ``USolFin`` | | -| | | -| ``ULdBeg`` / ``ULdFin`` | | -| | | -| ``UItBeg`` / ``UItFin`` | | -| | | -| ``USsBeg`` / ``USsFin`` | | -+---------------------------------------+-----------------------------------------------------------------------------+ - - -Python UPF methodology ----------------------- - -Coding a Python UPF is different from using a compiled language like C/C++ or Fortran, -mainly in terms of the API. Because the `gRPC technology `_ is used to handle -the communication and the exchange of data between the Python process and the Mechanical APDL -process, you need to understand the way this feature handles the serialization and -deserialization of data. - -The main difference is in the subroutine arguments. Instead of having a full list of -arguments as described for each of the subroutines, there are only two: the request -object (for inputs), and the response object (for outputs). If an argument is both input -and output of the subroutine, it is part of both objects. - -The description of the request object and the response object can be found in the -``MapdlUser.proto`` file stored in this installation directory: - - -.. code:: output - - Ansys Inc\vXXX\ansys\syslib\ansGRPC\User - -Where ``XXX`` is the version of Mechanical APDL you are using. -For example ``222`` for Mechanical APDL 2022R2. - -First, create a Python file starting from this template: - - -**my\_upf.py** - -.. code:: python - - import grpc - import sys - from mapdl import * - - - class MapdlUserService(MapdlUser_pb2_grpc.MapdlUserServiceServicer): - # ################################################################# - def UAnBeg(self, request, context): - print(" ======================================= ") - print(" >> Inside the PYTHON UAnBeg routine << ") - print(" ======================================= \n") - - response = google_dot_protobuf_dot_empty__pb2._EMPTY() - return response - - - if __name__ == "__main__": - upf.launch(sys.argv[0]) - - -Note that Mechanical APDL automatically installs a Mechanical APDL Python package (a -set of Python functions) to handle the connection between Mechanical APDL and the Python -environment. Each Python UPF must be imported: - - -.. code:: python - - from mapdl import * - - -The preceding example redefines the `UAnBeg` routine and prints a -customized banner. This file must be in the same directory as the input file. - -To use this Python UPF, you must add the Mechanical APDL ``/UPF`` command to your -input file (``my\_inp.dat``). - -.. code:: apdl - - /UPF,'my_upf.py' - - ! The UAnBeg UPF must be activated by using the USRCAL APDL command - - USRCAL,UANBEG - - -This command is trapped by the Mechanical APDL Launcher so that a Python gRPC server is up -and running when the Mechanical APDL process starts. - -When launching Mechanical APDL using this input file, you see the following printout to -indicate Mechanical APDL detected the Python UPF instructions and has launched a Python -server: - - -.. code:: output - - Processing "/upf" found in input file "my_inp.dat" - - Python UPF Detected - - PYTHON VERSION : 3.10 - >> - >> START PYTHON GRPC SERVER - >> - >> User Functions Python File : my_upf.py - >> - >> Server started on port [50054] - - -During the Mechanical APDL process, you see this Python printout: - - -.. code:: output - - RUN SETUP PROCEDURE FROM FILE= /ansys_inc/v241/ansys/apdl/start.ans - ======================================= - >> Inside the PYTHON UAnBeg routine << - ======================================= - - -At the very end of the process, the Python server is automatically shut -down: - - -.. code:: output - - |-----------------------------------------------------------------| - | | - | CP Time (sec) = 0.326 Time = 10:40:24 | - | Elapsed Time (sec) = 2.000 Date = 03/11/2021 | - | | - *-----------------------------------------------------------------* - - >> We shutdown Python Server(s) - - - -Accessing the database from the Python code -------------------------------------------- - -Within your UPF routine, you might need to access the Mechanical APDL database in read/write -mode. - -In the Python code, you can create a connection with the DB server. This command must -be called only once, so that you can protect the call based on the value of a static -variable: - - -.. code:: python - - import grpc - import sys - from mapdl import * - - firstcall = 1 - - - class MapdlUserService(MapdlUser_pb2_grpc.MapdlUserServiceServicer): - # ############################################################### - def UserMat(self, request, context): - global firstcall - - if firstcall == 1: - print(">> Connection to the MAPDL DB Server\n") - db.start() - firstcall = 0 - - # continuation of the python function - # ... - - -Once the DB connection has been initialized, you can access the database of the -Mechanical APDL instance in read/write mode. - -Of the functions documented in accessing the Mechanical APDL Database, a -subset has been exposed so that they can be called from the Python code. -The following table describes the exposed functions. - -**Table 2. Supported database access functions** - -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Supported database access functions** | -+==========================================================+===========================================================================================================================================================================================+ -| ``db.start()`` | Initializes the connection with a running Mechanical APDL instance. The DB Server is automatically started in Mechanical APDL if a **/UPF** command with a Python file has been detected. | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.stop()`` | Closes the connection with the DB Server. | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.ndnext(next)`` | Equivalent to the function described in function ``ndnext`` (Getting the Next Node Number) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.ndinqr(ind, key)`` | Equivalent to the function described in function ``ndinqr`` (Getting Information About a Node) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.getnod(inod)`` | Equivalent to the function described in function ``getnod`` (Getting a Nodal Point) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.putnod(inod, x, y, z)`` | Equivalent to the function described in function ``putnod`` (Storing a Node) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.elnext(ielm)`` | Equivalent to the function described in function ``elnext`` (Getting the Number of the Next Element) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.getelem(ielm)`` | Equivalent to the function described in function ``elmget`` (Getting an Element's Attributes and Nodes) | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.get_ElmInfo(inquire)`` | Equivalent to the function ``get\_ElmInfo`` described in accessing Solution and Material Data | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.get_ElmData(kchar, elemId, kMatRecPt, ncomp, vect)``| Equivalent to the function ``get\_ElmData`` described in accessing Solution and Material Data | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``db.putElmData(inquire, elemId, kIntg, nvect, vect)`` | Equivalent to the function ``put\_ElmData`` described in accessing Solution and Material Data | -+----------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - - -Python UPF limitations ----------------------- - -The Python UPF capability has these limitations: - -* Currently, Distributed Ansys is not supported. You must specify the ``-smp`` option on the command line to make sure Mechanical APDL is running in shared-memory processing mode. -* Python UPFs are only available on Linux platforms. - - - -Python UPF examples -------------------- - -The following Python UPF examples are available in :ref:`python_upf_examples`: - -* Python `UserMat` subroutine -* Python `UsrShift` subroutine -* Python `UserHyper` subroutine -