Skip to content

Commit

Permalink
Fix off_screen testing open_gui (#264)
Browse files Browse the repository at this point in the history
* remove off_screen arg

* running AATT prior to surface meshing for display

* added surface cache

* fixed open_gui

* version bump to 0.43.2
  • Loading branch information
akaszynski authored Aug 28, 2020
1 parent f6f5401 commit 16b97b4
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 176 deletions.
2 changes: 1 addition & 1 deletion pyansys/_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# major, minor, patch
version_info = 0, 43, 1
version_info = 0, 43, 2

# Nice string for the version
__version__ = '.'.join(map(str, version_info))
129 changes: 4 additions & 125 deletions pyansys/launcher.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
"""Module for launching MAPDL locally."""
from glob import glob
import time
import subprocess
import re
import warnings
import os
import appdirs
import tempfile
import socket
import pexpect

from pyansys.misc import is_float, random_string
from pyansys.errors import LockFileException, VersionError
Expand Down Expand Up @@ -209,114 +206,6 @@ def check_lock_file(path, jobname, override):
'running at "%s"' % path)



def launch_corba(exec_file=None, run_location=None, jobname=None, nproc=None,
additional_switches='', start_timeout=60):
"""Start MAPDL in AAS mode
Notes
-----
The CORBA interface is likely to fail on computers with multiple
network adapters. The ANSYS RPC isn't smart enough to determine
the right adapter and will likely try to communicate on the wrong
IP.
"""
# Using stored parameters so launch command can be run from a
# cached state (when launching the GUI)

# can't run /BATCH in windows, so we trick it using "-b" and
# provide a dummy input file
if os.name == 'nt':
# must be a random filename to avoid conflicts with other
# potential instances
tmp_file = '%s.inp' % random_string(10)
with open(os.path.join(run_location, tmp_file), 'w') as f:
f.write('FINISH')
additional_switches += ' -b -i %s -o out.txt' % tmp_file

# command must include "aas" flag to start MAPDL server
command = '"%s" -aas -j %s -np %d %s' % (exec_file,
jobname,
nproc,
additional_switches)

# if os.name == 'nt': # required after v190
# command = 'START /B "MAPDL" %s' % command

# remove any broadcast files
broadcast_file = os.path.join(run_location, 'mapdl_broadcasts.txt')
if os.path.isfile(broadcast_file):
os.remove(broadcast_file)

# windows 7 won't run this
# if os.name == 'nt' and platform.release() == '7':
# cwd = os.getcwd()
# os.chdir(run_location)
# os.system('START /B "MAPDL" %s' % command)
# os.chdir(cwd)
# else:
subprocess.Popen(command, shell=True,
cwd=run_location,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)

# listen for broadcast file
telapsed = 0
tstart = time.time()
started_rpc = False
while telapsed < start_timeout and not started_rpc:
try:
if os.path.isfile(broadcast_file):
broadcast = open(broadcast_file).read()
# see if connection to RPC has been made
rpc_txt = 'visited:collaborativecosolverunitior-set:'
started_rpc = rpc_txt in broadcast

time.sleep(0.1)
telapsed = time.time() - tstart

except KeyboardInterrupt:
raise KeyboardInterrupt

# exit if timed out
if not started_rpc:
err_str = 'Unable to start ANSYS within %.1f seconds' % start_timeout
if os.path.isfile(broadcast_file):
broadcast = open(broadcast_file).read()
err_str += '\n\nLast broadcast:\n%s' % broadcast
raise TimeoutError(err_str)

# return CORBA key
keyfile = os.path.join(run_location, 'aaS_MapdlId.txt')
return open(keyfile).read()


def launch_pexpect(exec_file=None, run_location=None, jobname=None, nproc=None,
additional_switches='', start_timeout=60):
"""Launch MAPDL as a pexpect process.
Limited to only a linux instance
"""
command = '%s -j %s -np %d %s' % (exec_file, jobname, nproc,
additional_switches)
process = pexpect.spawn(command, cwd=run_location)
process.delaybeforesend = None

try:
index = process.expect(['BEGIN:', 'CONTINUE'],
timeout=start_timeout)
except: # capture failure
raise RuntimeError(process.before.decode('utf-8'))

if index: # received ... press enter to continue
process.sendline('')
process.expect('BEGIN:', timeout=start_timeout)

return process


def launch_mapdl(exec_file=None, run_location=None, mode=None, jobname='file',
nproc=2, override=False, loglevel='INFO',
additional_switches='', start_timeout=120,
Expand Down Expand Up @@ -632,16 +521,12 @@ def launch_mapdl(exec_file=None, run_location=None, mode=None, jobname='file',

if mode == 'console':
from pyansys.mapdl_console import MapdlConsole
process = launch_pexpect(**start_parm)
return MapdlConsole(process, loglevel=loglevel,
log_apdl=log_apdl, **start_parm)
return MapdlConsole(loglevel=loglevel, log_apdl=log_apdl, **start_parm)
elif mode == 'corba':
from pyansys.mapdl_corba import MapdlCorba
corba_key = launch_corba(**start_parm)
return MapdlCorba(corba_key, loglevel=loglevel,
log_apdl=log_apdl,
log_broadcast=kwargs.get('log_broadcast', False),
**start_parm)
return MapdlCorba(loglevel=loglevel, log_apdl=log_apdl,
log_broadcast=kwargs.get('log_broadcast',
False), **start_parm)
else:
raise ValueError('Invalid mode %s' % mode)

Expand All @@ -663,12 +548,6 @@ def check_mode(mode, version):
if mode == 'corba':
if version < 170:
raise VersionError('CORBA AAS mode requires MAPDL v17.0 or newer.')
# elif version > 20.1 and os.name == 'nt':
# raise ValueError('CORBA AAS mode on Windows requires MAPDL 2020R1'
# ' or earlier.')
# elif version >= 20.0 and os.name == 'posix':
# raise ValueError('CORBA AAS mode on Linux requires MAPDL 2019R3'
# ' or earlier.')

elif mode == 'console' and is_win:
raise ValueError('Console mode requires Linux')
Expand Down
48 changes: 31 additions & 17 deletions pyansys/mapdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from pyansys.element_commands import element_commands
from pyansys.errors import MapdlRuntimeError, MapdlInvalidRoutineError
from pyansys.plotting import general_plotter

from pyansys.launcher import get_ansys_path

MATPLOTLIB_LOADED = True
try:
Expand Down Expand Up @@ -459,22 +459,24 @@ def open_gui(self, include_result=True): # pragma: no cover
if os.path.isfile(tmp_database):
os.remove(tmp_database)

# get the state, close, and finish
# cache result file, version, and routine before closing
resultfile = self._result_file
version = self.version
prior_processor = self.parameters.routine

# get the close, and finish
self.finish()
self.save(tmp_database)
# self.exit(close_log=False)
self.exit()

# copy result file to temp directory
if include_result:
resultfile = os.path.join(self.path, '%s.rst' % self.jobname)
if os.path.isfile(resultfile):
tmp_resultfile = os.path.join(save_path, '%s.rst' % name)
copyfile(resultfile, tmp_resultfile)

# write temporary input file
start_file = os.path.join(save_path, 'start%s.ans' % self.version)
start_file = os.path.join(save_path, 'start%s.ans' % version)
with open(start_file, 'w') as f:
f.write('RESUME\n')

Expand All @@ -486,22 +488,25 @@ def open_gui(self, include_result=True): # pragma: no cover
# issue system command to run ansys in GUI mode
cwd = os.getcwd()
os.chdir(save_path)
os.system('cd "%s" && "%s" -g -j %s' % (save_path,
self._start_parm['exec_file'],
name))
exec_file = self._start_parm.get('exec_file',
get_ansys_path(allow_input=False))
os.system('cd "%s" && "%s" -g -j %s' % (save_path, exec_file, name))
os.chdir(cwd)

# must remove the start file when finished
os.remove(start_file)
os.remove(other_start_file)

# reload database when finished
# self._launch() # TODO
# reattach to a new session and reload database
self._launch(self._start_parm)
self.resume(tmp_database)
if prior_processor is not None:
if 'BEGIN' not in prior_processor:
self.run('/%s' % prior_processor)

def _launch(self, *args, **kwargs): # pragma: no cover
raise NotImplementedError('Implemented by child class')

def _close_apdl_log(self):
"""Closes the APDL log"""
if self._apdl_log is not None:
Expand Down Expand Up @@ -1047,6 +1052,20 @@ def result(self):
if not self._local:
raise RuntimeError('Binary interface only available when result is local.')

result_path = self._result_file
if not os.path.isfile(result_path):
raise FileNotFoundError('No results found at %s' % result_path)
return pyansys.read_binary(result_path)

@property
def _result_file(self):
"""Path of the result file
Notes
-----
There may be multiple result files at this location (if not
combining results)
"""
try:
result_path = self.inquire('RSTFILE')
except RuntimeError:
Expand All @@ -1056,12 +1075,7 @@ def result(self):
result_path = os.path.join(self.path, '%s.rst' % self._jobname)
elif not os.path.dirname(result_path):
result_path = os.path.join(self.path, '%s.rst' % result_path)

# there may be multiple result files at this location (if not
# combining results)
if not os.path.isfile(result_path):
raise FileNotFoundError('No results found at %s' % result_path)
return pyansys.read_binary(result_path)
return result_path

def _get(self, *args, **kwargs):
"""Simply use the default get method"""
Expand Down Expand Up @@ -1332,7 +1346,7 @@ def read_float_from_inline_function(self, function_str):
Returns
-------
float
value : float
Value returned by inline function.
Examples
Expand Down
41 changes: 33 additions & 8 deletions pyansys/mapdl_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Used when launching Mapdl via pexpect on Linux when <= 17.0
"""
import pexpect
import time
import re

Expand Down Expand Up @@ -41,26 +42,50 @@
ignored = re.compile(r'[\s\S]+'.join(['WARNING', 'command', 'ignored']))


def launch_pexpect(exec_file=None, run_location=None, jobname=None, nproc=None,
additional_switches='', start_timeout=60):
"""Launch MAPDL as a pexpect process.
Limited to only a linux instance
"""
command = '%s -j %s -np %d %s' % (exec_file, jobname, nproc,
additional_switches)
process = pexpect.spawn(command, cwd=run_location)
process.delaybeforesend = None

try:
index = process.expect(['BEGIN:', 'CONTINUE'],
timeout=start_timeout)
except: # capture failure
raise RuntimeError(process.before.decode('utf-8'))

if index: # received ... press enter to continue
process.sendline('')
process.expect('BEGIN:', timeout=start_timeout)

return process


class MapdlConsole(_MapdlCore):
"""Control interaction with an ANSYS shell instance.
Only works on Linux.
Parameters
----------
process : pexpect
"""

def __init__(self, process, loglevel='INFO', log_apdl='w',
use_vtk=True, **start_parm):
def __init__(self, loglevel='INFO', log_apdl='w', use_vtk=True,
**start_parm):
"""Opens an ANSYS process using pexpect"""
self._auto_continue = True
self._continue_on_error = False
self._process = process
self._process = None
self._launch(start_parm)
super().__init__(loglevel=loglevel, use_vtk=use_vtk, log_apdl=log_apdl,
**start_parm)

def _launch(self, start_parm):
"""Connect to MAPDL process using pexpect"""
self._process = launch_pexpect(**start_parm)

def _run(self, command):
"""Sends command and returns ANSYS's response"""
self._reset_cache()
Expand Down
Loading

0 comments on commit 16b97b4

Please sign in to comment.