1
1
import os
2
+ from warnings import warn
2
3
3
4
from ansys .mapdl .core import __version__
4
5
from ansys .mapdl .core .misc import is_float
@@ -61,21 +62,105 @@ def convert_script(
61
62
>>> from ansys.mapdl.core import examples
62
63
>>> clines = pymapdl.convert_script(examples.vmfiles['vm1'], 'vm1.py')
63
64
"""
65
+ with open (filename_in , 'r' ) as fid :
66
+ apdl_strings = fid .readlines ()
67
+
68
+ translator = _convert (apdl_strings = apdl_strings ,
69
+ loglevel = loglevel ,
70
+ auto_exit = auto_exit ,
71
+ line_ending = line_ending ,
72
+ exec_file = exec_file ,
73
+ macros_as_functions = macros_as_functions ,
74
+ use_function_names = use_function_names
75
+ )
76
+
77
+ translator .save (filename_out )
78
+ return translator .lines
79
+
80
+
81
+ def convert_apdl_block (apdl_strings ,
82
+ loglevel = "WARNING" ,
83
+ auto_exit = True ,
84
+ line_ending = None ,
85
+ exec_file = None ,
86
+ macros_as_functions = True ,
87
+ use_function_names = True ,
88
+ ):
89
+ """Converts an ANSYS input string to a python PyMAPDL string.
90
+
91
+ Parameters
92
+ ----------
93
+ apdl_string : str
94
+ APDL strings or list of strings to convert.
95
+
96
+ filename_out : str
97
+ Filename of the python script to write a translation to.
98
+
99
+ loglevel : str, optional
100
+ Logging level of the ansys object within the script.
101
+
102
+ auto_exit : bool, optional
103
+ Adds a line to the end of the script to exit MAPDL. Default
104
+ ``True``.
105
+
106
+ line_ending : str, optional
107
+ When None, automatically determined by OS being used.
108
+
109
+ macros_as_functions : bool, optional
110
+ Attempt to convert MAPDL macros to python functions.
111
+
112
+ use_function_names : bool, optional
113
+ Convert MAPDL functions to ansys.mapdl.core.Mapdl class
114
+ methods. When ``True``, the MAPDL command "K" will be
115
+ converted to ``mapdl.k``. When ``False``, it will be
116
+ converted to ``mapdl.run('k')``.
117
+
118
+ Returns
119
+ -------
120
+ list
121
+ List of lines translated.
122
+
123
+ """
124
+
125
+ translator = _convert (apdl_strings ,
126
+ loglevel = loglevel ,
127
+ auto_exit = auto_exit ,
128
+ line_ending = line_ending ,
129
+ exec_file = exec_file ,
130
+ macros_as_functions = macros_as_functions ,
131
+ use_function_names = use_function_names )
132
+
133
+ if isinstance (apdl_strings , str ):
134
+ return translator .line_ending .join (translator .lines )
135
+ return translator .lines
136
+
137
+
138
+ def _convert (apdl_strings ,
139
+ loglevel = "WARNING" ,
140
+ auto_exit = True ,
141
+ line_ending = None ,
142
+ exec_file = None ,
143
+ macros_as_functions = True ,
144
+ use_function_names = True ,
145
+ ):
146
+
64
147
translator = FileTranslator (
65
148
loglevel ,
66
149
line_ending ,
67
150
exec_file = exec_file ,
68
151
macros_as_functions = macros_as_functions ,
69
152
use_function_names = use_function_names ,
70
153
)
71
- with open (filename_in ) as file_in :
72
- for line in file_in .readlines ():
73
- translator .translate_line (line )
154
+
155
+ if isinstance (apdl_strings , str ):
156
+ apdl_strings = apdl_strings .split (translator .line_ending )
157
+
158
+ for line in apdl_strings :
159
+ translator .translate_line (line )
74
160
75
161
if auto_exit :
76
162
translator .write_exit ()
77
- translator .save (filename_out )
78
- return translator .lines
163
+ return translator
79
164
80
165
81
166
class FileTranslator :
@@ -107,7 +192,30 @@ def __init__(
107
192
self .initialize_mapdl_object (loglevel , exec_file )
108
193
109
194
self ._valid_commands = dir (Commands )
110
- self ._non_interactive_commands = ["*CRE" , "*VWR" ]
195
+ self ._block_commands = {
196
+ "NBLO" : "NBLOCK" ,
197
+ "EBLO" : "EBLOCK" ,
198
+ "BFBL" : "BFBLOCK" ,
199
+ "BFEB" : "BFEBLOCK" ,
200
+ "PREA" : "PREAD" ,
201
+ "SFEB" : "SFEBLOCK" } #Way out: '-1' , 'END PREAD'
202
+
203
+ self ._enum_block_commands = {
204
+ "CMBL" : "CMBLOCK" ,
205
+ } # Commands where you need to count the number of lines.
206
+
207
+ _NON_INTERACTIVE_COMMANDS = {
208
+ "*CRE" : "*CREATE" ,
209
+ "*VWR" : "*VWRITE" ,
210
+ "*VRE" : "*VREAD"
211
+ }
212
+
213
+ self ._non_interactive_commands = list (_NON_INTERACTIVE_COMMANDS ) + list (self ._block_commands ) + list (self ._enum_block_commands )
214
+
215
+ self ._block_count = 0
216
+ self ._block_count_target = 0
217
+ self ._in_block = False
218
+ self ._block_current_cmd = None
111
219
112
220
def write_header (self ):
113
221
header = f'"""Script generated by ansys-mapdl-core version { __version__ } """'
@@ -152,6 +260,15 @@ def translate_line(self, line):
152
260
line = line .strip ()
153
261
line = line .replace ('"' , "'" )
154
262
263
+ if self ._in_block :
264
+ self ._block_count += 1
265
+
266
+ if self ._in_block and self ._block_count >= self ._block_count_target and self ._block_count_target :
267
+ self ._in_block = False
268
+ self .end_non_interactive ()
269
+ self ._block_count = 0
270
+ self ._block_current_cmd = None
271
+
155
272
# check if line contains a comment
156
273
if "!" in line :
157
274
if "'!'" in line or '"!"' in line :
@@ -168,6 +285,34 @@ def translate_line(self, line):
168
285
169
286
if not line :
170
287
return
288
+ cmd_ = line .split (',' )[0 ].upper ()
289
+
290
+ if cmd_ == '*DO' :
291
+ self .start_non_interactive ()
292
+ self .store_run_command (line )
293
+ return
294
+
295
+ if cmd_ == '*ENDDO' :
296
+ self .store_run_command (line )
297
+ self .end_non_interactive ()
298
+ return
299
+
300
+ if self .output_to_file (line ):
301
+ self .start_non_interactive ()
302
+ self .store_run_command (line )
303
+ return
304
+
305
+ if self .output_to_default (line ):
306
+ self .end_non_interactive ()
307
+ self .store_run_command (line )
308
+ self .store_run_command ('/GOPR' )
309
+ return
310
+
311
+ if cmd_ == '/VERIFY' :
312
+ self .store_run_command ("FINISH" )
313
+ self .store_run_command (line )
314
+ self .store_run_command ("/PREP7" )
315
+ return
171
316
172
317
if line [:4 ].upper () == "*REP" :
173
318
if not self .non_interactive :
@@ -188,8 +333,17 @@ def translate_line(self, line):
188
333
return self .store_command ("title" , ["" .join (parameters ).strip ()])
189
334
190
335
if line [:4 ].upper () == "*GET" :
191
- parameters = line .split ("," )[1 :]
192
- return self .store_command ("get" , parameters )
336
+ if self .non_interactive : # gives error
337
+ self .store_run_command (line )
338
+ return
339
+ else :
340
+ parameters = line .split ("," )[1 :]
341
+ return self .store_command ("get" , parameters )
342
+
343
+ if line [:4 ].upper () == "/NOP" :
344
+ self .comment = "It is not recommended to use '/NOPR' in a normal PyMAPDL session."
345
+ self .store_under_scored_run_command (line )
346
+ return
193
347
194
348
if line [:6 ].upper () == "/PREP7" :
195
349
return self .store_command ("prep7" , [])
@@ -200,11 +354,13 @@ def translate_line(self, line):
200
354
self .store_empty_line ()
201
355
self .indent = self .indent [4 :]
202
356
self ._infunction = False
203
- self .end_non_interactive ()
357
+ if not self ._in_block :
358
+ self .end_non_interactive ()
204
359
return
205
360
else :
206
361
self .store_run_command (line )
207
- self .end_non_interactive ()
362
+ if not self ._in_block :
363
+ self .end_non_interactive ()
208
364
return
209
365
210
366
# check for if statement
@@ -216,12 +372,14 @@ def translate_line(self, line):
216
372
# check if line ends non-interactive
217
373
if line [0 ] == "(" :
218
374
if not self .non_interactive :
219
- print (
220
- "Possible invalid line:\n %s\n " % line
221
- + "This line requires a *VWRITE beforehand"
375
+ warn (
376
+ "\n Possible invalid line:\n %s\n " % line
377
+ + "This line requires a *VWRITE beforehand."
378
+ + "The previous line is: \n %s\n \n " % self .lines [- 1 ]
222
379
)
223
380
self .store_run_command (line )
224
- self .end_non_interactive ()
381
+ if not self ._in_block : # To escape cmds that require (XX) but they are not in block
382
+ self .end_non_interactive ()
225
383
return
226
384
elif line [:4 ] == "*USE" and self .macros_as_functions :
227
385
items = line .split ("," )
@@ -243,15 +401,36 @@ def translate_line(self, line):
243
401
self .store_empty_line ()
244
402
return
245
403
404
+ if line == '-1' or line == 'END PREAD' : # End of block commands
405
+ self .store_run_command (line )
406
+ self ._in_block = False
407
+ self .end_non_interactive ()
408
+ return
409
+
246
410
# check valid command
247
411
if command not in self ._valid_commands :
248
- if line [:4 ] == "*CRE" : # creating a function
412
+ if line [:4 ]. upper () == "*CRE" : # creating a function
249
413
if self .macros_as_functions :
250
414
self .start_function (items [1 ].strip ())
251
415
return
252
416
else :
253
417
self .start_non_interactive ()
254
- elif line [:4 ] in self ._non_interactive_commands :
418
+ elif line [:4 ].upper () in self ._non_interactive_commands :
419
+ if line [:4 ].upper () in self ._block_commands :
420
+ self ._in_block = True
421
+ self ._block_count = 0
422
+ self ._block_count_target = 0
423
+
424
+ elif line [:4 ].upper () in self ._enum_block_commands :
425
+ self ._in_block = True
426
+ self ._block_count = 0
427
+ if line [:4 ].upper () == 'CMBL' : # In cmblock
428
+ # CMBLOCK,Cname,Entity,NUMITEMS,,,,,KOPT
429
+ numitems = int (line .split (',' )[3 ])
430
+ _block_count_target = numitems // 8 + 1 if numitems % 8 != 0 else numitems // 8
431
+ self ._block_count_target = _block_count_target + 2 # because the cmd line and option line.
432
+
433
+ self ._block_current_cmd = line [:4 ].upper ()
255
434
self .start_non_interactive ()
256
435
self .store_run_command (line )
257
436
elif self .use_function_names :
@@ -274,10 +453,18 @@ def start_function(self, func_name):
274
453
self .lines .append (line )
275
454
self .indent = self .indent + " "
276
455
277
- def store_run_command (self , command ):
456
+ def store_under_scored_run_command (self , command ):
457
+ self .store_run_command (command , run_underscored = True )
458
+
459
+ def store_run_command (self , command , run_underscored = False ):
278
460
"""Stores pyansys.ANSYS command that cannot be broken down
279
461
into a function and parameters.
280
462
"""
463
+ if run_underscored :
464
+ underscore = '_'
465
+ else :
466
+ underscore = ''
467
+
281
468
if self ._infunction and "ARG" in command :
282
469
args = []
283
470
for i in range (1 , 19 ):
@@ -288,22 +475,24 @@ def store_run_command(self, command):
288
475
args .append (arg )
289
476
c += 1
290
477
291
- line = '%s%s.run ("%s".format(%s))' % (
478
+ line = '%s%s.%srun ("%s".format(%s))' % (
292
479
self .indent ,
293
480
self .obj_name ,
481
+ underscore ,
294
482
command ,
295
483
", " .join (args ),
296
484
)
297
485
298
486
elif self .comment :
299
- line = '%s%s.run ("%s") # %s' % (
487
+ line = '%s%s.%srun ("%s") # %s' % (
300
488
self .indent ,
301
489
self .obj_name ,
490
+ underscore ,
302
491
command ,
303
492
self .comment ,
304
493
)
305
494
else :
306
- line = '%s%s.run ("%s")' % (self .indent , self .obj_name , command )
495
+ line = '%s%s.%srun ("%s")' % (self .indent , self .obj_name , underscore , command )
307
496
self .lines .append (line )
308
497
309
498
def store_comment (self ):
@@ -355,3 +544,41 @@ def end_non_interactive(self):
355
544
if self ._non_interactive_level == 0 :
356
545
self .non_interactive = False
357
546
self .indent = self .indent [4 :]
547
+
548
+ def output_to_file (self , line ):
549
+ """Return if an APDL line is redirecting to a file."""
550
+ if line [:4 ].upper () == '/OUT' :
551
+ # We are redirecting the output to somewhere, probably a file.
552
+ # Because of the problem with the ansys output, we need to execute
553
+ # this in non_interactive mode.
554
+ output_cmd = line .strip ().upper ().split (',' )
555
+ if len (output_cmd ) > 1 :
556
+ opt1 = output_cmd [1 ].strip ().upper ()
557
+ if opt1 != 'TERM' :
558
+ # A file is supplied.
559
+ return True
560
+
561
+ if line [:4 ].upper () == '*CFO' : # any([each[0:4] in '*CFOPEN' for each in dir(Commands)])
562
+ # We might not need going into interactive mode for *CFOPEN/*CFCLOSE
563
+ return True
564
+
565
+ return False
566
+
567
+ def output_to_default (self , line ):
568
+ if line [:4 ].upper () == '/OUT' :
569
+ # We are redirecting the output to somewhere, probably a file.
570
+ # Because of the problem with the ansys output, we need to execute
571
+ # this in non_interactive mode.
572
+ output_cmd = line .strip ().upper ().split (',' )
573
+ if len (output_cmd ) == 1 :
574
+ return True
575
+ elif len (output_cmd ) > 1 :
576
+ opt1 = output_cmd [1 ].strip ().upper ()
577
+ if opt1 == 'TERM' :
578
+ # A file is supplied.
579
+ return True
580
+ if line [:4 ].upper () in '*CFCLOSE' :
581
+ # We might not need going into interactive mode for *CFOPEN/*CFCLOSE
582
+ return True
583
+
584
+ return False
0 commit comments