ansys / pymapdl

Pythonic interface to MAPDL
https://mapdl.docs.pyansys.com
MIT License
419 stars 116 forks source link

PyMAPDL performance decrease on MAPDL and on v222 onwards #3208

Open germa89 opened 1 week ago

germa89 commented 1 week ago

Description

For some reason, the performance of MAPDL server got decreased quite a lot from v212, to v222 (and kept in this way unless until 2023R1).

There is also the issue about the degraded performance of the MAPDL based approach with respect to the PYMAPDL based against discussions on #757.

Context

This issue was found while working with @ayush-kumar-423 while doing a comparison between full MAPDL code and PyMAPDL code to modify element and nodal data.

Therefore, there are 2 files to consider.

Metrics

Some metrics to study this issue:

MAPDL v212

PyMAPDL

(.venv_win) PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\xpl_stress_write_hex.py
PyMAPDL is taking longer than expected to connect to an MAPDL session.
Checking if there are any available licenses...
Product:             Ansys Mechanical Enterprise
MAPDL Version:       21.2
ansys.mapdl Version: 0.69.dev0

[        12       4961       4961      10000          3       1000
       1000          0          1     493174       6159      26162
      46165       5156        192      76168          0          0
          0         -1          1          0     493174          0
          0          0          0          0          0          0
          0          0          0       -999          0  134218824
          0         -1          0   67108864          0          0
          0          0          0          0          0          0
       4961          0          0          0          0          0
          0          0          0          0          2 1140850688
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0]
Total Time 85.2099392414093

MAPDL based

 (.venv_win) PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\mapdl_xpl_ens.py       
PyMAPDL is taking longer than expected to connect to an MAPDL session.
Checking if there are any available licenses...
Product:             Ansys Mechanical Enterprise
MAPDL Version:       21.2
ansys.mapdl Version: 0.69.dev0

Time taken 93.53394508361816

MAPDL v231

PyMAPDL based code

(.venv_win) PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\xpl_stress_write_hex.py
PyMAPDL is taking longer than expected to connect to an MAPDL session.
Checking if there are any available licenses...
Product:             Ansys Mechanical Enterprise
MAPDL Version:       23.1
ansys.mapdl Version: 0.69.dev0
          0          0          0          0          2 1140850688
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0]
Total Time 159.12418913841248

MAPDL based code

(.venv_win) PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\mapdl_xpl_ens.py
PyMAPDL is taking longer than expected to connect to an MAPDL session.
Checking if there are any available licenses...
Product:             Ansys Mechanical Enterprise
MAPDL Version:       23.1
ansys.mapdl Version: 0.69.dev0

Time taken 187.73397755622864

Summary

Configuration Time
MAPDL v212 - PyMAPDL 85.21
MAPDL v212 - MAPDL 93.53
MAPDL v231 - PyMAPDL 159.12
MAPDL v231 - MAPDL 187.73

Files

PyMAPDL based code

PyMAPDL based code

```python import time import numpy as np # Now open dsub file from ansys.mapdl.core import launch_mapdl solve = True exec_file = r"C:\Program Files\ANSYS Inc\v212\ansys\bin\winx64\ANSYS212.exe" exec_file = r"C:\Program Files\ANSYS Inc\v222\ansys\bin\winx64\ANSYS222.exe" # exec_file = r"C:\Program Files\ANSYS Inc\v231\ansys\bin\winx64\ANSYS231.exe" mapdl = launch_mapdl(exec_file, jobname='dummy_solve', override=True) print(mapdl) esize = 10. length = 100. width = 100. depth = 100. numsteps = 1 if solve: mapdl.fcomp('rst', 0) # Write all data in double precision mapdl.run('/config,resuprec,0') mapdl.prep7() mapdl.k(1, 0.0, 0.0, 0.0) mapdl.k(2, length, 0.0, 0.0) mapdl.k(3, length, width, 0.0) mapdl.k(4, 0.0, width, 0.0) mapdl.k(5, 0.0, 0.0, depth) mapdl.k(6, length, 0.0, depth) mapdl.k(7, length, width, depth) mapdl.k(8, 0.0, width, depth) mapdl.v(1, 2, 3, 4, 5, 6, 7, 8) mapdl.et(1, 186) mapdl.mp('ex', 1, 210000.) mapdl.mp('prxy', 1, .3) mapdl.mp('kxx', 1e-6) mapdl.esize(esize) mapdl.mshape(0, "3D") mapdl.vmesh('all') mapdl.finish() mapdl.slashsolu() # For some reason - with d,all,all - "ENS" block doesn't appear in XPL mapdl.d('all', 'ux', 2.0) mapdl.d('all', 'uy', 2.0) mapdl.d('all', 'uz', 2.0) mapdl.bf('all', 'temp', 100.) mapdl.time(1.) mapdl.nsubst(numsteps, numsteps, numsteps) mapdl.outres('all', 'none') mapdl.outres('strs', 'all') mapdl.outres("epel", "all") mapdl.outres("eppl", "all") mapdl.outres("nsol", "all") mapdl.solve() mapdl.finish() mapdl.aux2() mapdl.combine('FULL') mapdl.finish() xpl = mapdl.xpl mm = mapdl.math t0 = time.time() xpl.open('dummy_solve.rst') header = xpl.read('HEADER', asarray=True) print(header) num_nodes = header[1] num_elems = header[5] xpl.close() # Get internal Element order xpl.open('dummy_solve.rst') internal_elem_order = xpl.read("ELM", "ELEM_ORDER") xpl.close() stress = [float(id) for id in range(1, 2001)] all_time_steps = [] def get_elem_stress(eid): return stress[eid - 1] t0 = time.time() for i in range(1, numsteps + 1): t_elem = 0. for u_eid in range(1, num_elems + 1): # for index, eid in enumerate(internal_elem_order): i_eid = internal_elem_order[u_eid - 1] xpl.open(r"dummy_solve.rst", "WRIT") xpl.step(f"DSI::SET{i}::ESL::ELEM{u_eid}") t0_elem = time.time() stress_elem = get_elem_stress(i_eid) myvec = np.ones(48, dtype=np.float64) * float(i * stress_elem) mm.set_vec(myvec, 'NEWVEC') xpl.write('ENS', 'NEWVEC') t1_elem = time.time() t_elem = t1_elem - t0_elem all_time_steps.append(t_elem) xpl.up() xpl.close() t1 = time.time() print(f"Total Time {t1 - t0}") mapdl.exit() ```

MAPDL based code

MAPDL based code

```python import time from ansys.mapdl.core import launch_mapdl solve = True exec_file = r"C:\Program Files\ANSYS Inc\v212\ansys\bin\winx64\ANSYS212.exe" exec_file = r"C:\Program Files\ANSYS Inc\v222\ansys\bin\winx64\ANSYS222.exe" # exec_file = r"C:\Program Files\ANSYS Inc\v231\ansys\bin\winx64\ANSYS231.exe" mapdl = launch_mapdl(exec_file, jobname='dummy_solve', override=True) print(mapdl) esize = 10. length = 100. width = 100. depth = 100. numsteps = 1 if solve: mapdl.fcomp('rst', 0) # Write all data in double precision mapdl.run('/config,resuprec,0') mapdl.prep7() mapdl.k(1, 0.0, 0.0, 0.0) mapdl.k(2, length, 0.0, 0.0) mapdl.k(3, length, width, 0.0) mapdl.k(4, 0.0, width, 0.0) mapdl.k(5, 0.0, 0.0, depth) mapdl.k(6, length, 0.0, depth) mapdl.k(7, length, width, depth) mapdl.k(8, 0.0, width, depth) mapdl.v(1, 2, 3, 4, 5, 6, 7, 8) mapdl.et(1, 186) mapdl.mp('ex', 1, 210000.) mapdl.mp('prxy', 1, .3) mapdl.mp('kxx', 1e-6) mapdl.esize(esize) mapdl.mshape(0, "3D") mapdl.vmesh('all') mapdl.finish() mapdl.slashsolu() # For some reason - with d,all,all - "ENS" block doesn't appear in XPL mapdl.d('all', 'ux', 2.0) mapdl.d('all', 'uy', 2.0) mapdl.d('all', 'uz', 2.0) mapdl.bf('all', 'temp', 100.) mapdl.time(1.) mapdl.nsubst(numsteps, numsteps, numsteps) mapdl.outres('all', 'none') mapdl.outres('strs', 'all') mapdl.outres("epel", "all") mapdl.outres("eppl", "all") mapdl.outres("nsol", "all") mapdl.solve() mapdl.finish() mapdl.aux2() mapdl.combine('FULL') mapdl.finish() cmd = """ /com,*************************START************************* *xpl,open,dummy_solve.rst *xpl,read,elm,int_elem_order *xpl,read,header,header_vec /com,*************************HEADER************************* num_nodes = header_vec(3) num_elems = header_vec(7) n_sets = header_vec(9) *stat,num_elems *stat,num_nodes *stat,n_sets /com,*************************HEADER************************* *xpl,close *print,int_elem_order !Convert Internal Element Order Vector to APDL Parameter *VEC,int_eo_vec,d,copy,int_elem_order *export,int_eo_vec,apdl,int_eo_param *DIM,myarr,ARRAY,48 *vfill,myarr,ramp,1.0,0.0 *do,ts,1,n_sets *do,eid,1,num_elems *vfact,ts*eid *vfun,myarr_scaled,copy,myarr *vec,my_vec,d,import,apdl,myarr_scaled /gopr *print,my_vec *xpl,open,dummy_solve.rst,,writ ! Find internal element index *VOPER,index_array,int_eo_param,EQ,eid *VSCFUN,location,FIRST,index_array(1) *xpl,step,dsi::set%ts%::esl::elem%location% *xpl,write,ens,my_vec *xpl,close *enddo *enddo /com,*************************END************************* """ t0 = time.time() mapdl.run_multiline(cmd) t1 = time.time() print(f"Time taken {t1 - t0}") mapdl.exit() ```

EDITED: I realised the file wasn't totally close at each loop in the PYMAPDL approach. I have fixed and change everything accordingly.

germa89 commented 1 week ago

This issue might be worth looking into detail on the gRPC server summer sprint, starting in July. So I will start with the due diligence.

@mikerife can you have a very quick look at the code (no need to run) and let me know if both codes are equivalent? I want to compare both approaches (run MAPDL commands and run PyMAPDL commands). It seems to me they are the same.

@FredAns do you have any early feedback before we dig more into this?

ayush-kumar-423 commented 1 week ago

@pthieffry, FYI

germa89 commented 5 days ago

More feedback running v242

I have used a remote server in Ansys VPN (in Lyon). Probably that is going to generate some overhead because of the long distance, but the lyon machine is way better than my laptop.

Here the gRPC overhead is shown clearly. Huge difference.

MAPDL based approach

PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\mapdl_xpl_ens.py
Product:             Ansys Mechanical Enterprise
MAPDL Version:       24.2
ansys.mapdl Version: 0.69.dev0

Time taken 23.42877197265625

PyMAPDL based approach

PS C:\Users\gayuso\pymapdl\tmp\Ayush> python .\xpl_stress_write_hex.py
Product:             Ansys Mechanical Enterprise
MAPDL Version:       24.2
ansys.mapdl Version: 0.69.dev0

[        12       4961       4961      10000          3       1000
       1000          0          1     493174       6159      26162
      46165       5156        192      76168          0          0
          0         -1          1          0     493174          0
          0          0          0          0          0          0
          0          0          0       -999          0  134218824
          0         -1          0   67108864          0          0
          0          0          0          0          0          0
       4961          0          0          0          0          0
          0          0          0          2          4 1140850688
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0          0          0          0          0
          0          0]
Total Time 893.2749426364899

Notes

I had to add:

mapdl.clear()
mapdl.filname("dummy_solve", 1)