def check_mode(mode, version): """Check if the MAPDL server mode matches the allowable version If ``None``, the newest mode will be selected. Returns a value from ``ALLOWABLE_MODES``. """ if isinstance(mode, str): mode = mode.lower() if mode == 'grpc': if version < 211: if version < 202 and os.name == 'nt': raise VersionError( 'gRPC mode requires MAPDL 2020R2 or newer ' 'on Windows.') elif os.name == 'posix': raise VersionError( 'gRPC mode requires MAPDL 2021R1 or newer.') elif mode == 'corba': if version < 170: raise VersionError( 'CORBA AAS mode requires MAPDL v17.0 or newer.') if version >= 211: raise VersionError( 'Console mode not supported for 2021R1 or newer. ' 'Use the default "grpc" mode.') elif mode == 'console': if os.name == 'nt': raise ValueError('Console mode requires Linux') if version >= 211: raise VersionError( 'Console mode not supported for 2021R1 or newer. ' 'Use the default "grpc" mode.') else: raise ValueError( f'Invalid MAPDL server mode "{mode}".\n\n' f'Use one of the following modes:\n{ALLOWABLE_MODES}') else: # auto-select based on best version if version >= 211: mode = 'grpc' elif version == 202 and os.name == 'nt': # Windows supports it as of 2020R2 mode = 'grpc' elif version >= 170: mode = 'corba' else: if os.name == 'nt': raise VersionError('Running MAPDL as a service requires ' 'v17.0 or greater on Windows.') mode = 'console' if version < 130: warnings.warn('MAPDL as a service has not been tested on MAPDL < v13') return mode
def check_mode(mode, version): """Check if the MAPDL server mode matches the allowable version If ``None``, the newest mode will be selected. Returns a value from ``ALLOWABLE_MODES``. """ if isinstance(mode, str): mode = mode.lower() if mode == "grpc": if version < 211: if version < 202 and os.name == "nt": raise VersionError( "gRPC mode requires MAPDL 2020R2 or newer " "on Windows.") elif os.name == "posix": raise VersionError( "gRPC mode requires MAPDL 2021R1 or newer.") elif mode == "corba": if version < 170: raise VersionError( "CORBA AAS mode requires MAPDL v17.0 or newer.") if version >= 211: raise VersionError( "Console mode not supported for 2021R1 or newer. " 'Use the default "grpc" mode.') elif mode == "console": if os.name == "nt": raise ValueError("Console mode requires Linux") if version >= 211: raise VersionError( "Console mode not supported for 2021R1 or newer. " 'Use the default "grpc" mode.') else: raise ValueError( f'Invalid MAPDL server mode "{mode}".\n\n' f"Use one of the following modes:\n{ALLOWABLE_MODES}") else: # auto-select based on best version if version >= 211: mode = "grpc" elif version == 202 and os.name == "nt": # Windows supports it as of 2020R2 mode = "grpc" elif version >= 170: mode = "corba" else: if os.name == "nt": raise VersionError("Running MAPDL as a service requires " "v17.0 or greater on Windows.") mode = "console" if version < 130: warnings.warn("MAPDL as a service has not been tested on MAPDL < v13") return mode
def __init__( self, n_instances, wait=True, run_location=None, port=MAPDL_DEFAULT_PORT, progress_bar=True, restart_failed=True, remove_temp_files=True, **kwargs, ): """Initialize several instances of mapdl""" self._instances = [] self._root_dir = run_location kwargs["remove_temp_files"] = remove_temp_files kwargs["mode"] = "grpc" self._spawn_kwargs = kwargs # verify that mapdl is 2021R1 or newer if "exec_file" in kwargs: exec_file = kwargs["exec_file"] else: # get default executable exec_file = get_ansys_path() if exec_file is None: raise FileNotFoundError( "Invalid exec_file path or cannot load cached " "ansys path. Enter one manually using " "exec_file=<path to executable>") if _version_from_path(exec_file) < 211: raise VersionError( "LocalMapdlPool requires MAPDL 2021R1 or later.") # grab available ports ports = available_ports(n_instances, port) if self._root_dir is not None: if not os.path.isdir(self._root_dir): os.makedirs(self._root_dir) self._instances = [] self._active = True # used by pool monitor n_instances = int(n_instances) if n_instances < 2: raise ValueError( "Must request at least 2 instances to create a pool.") pbar = None if wait and progress_bar: pbar = tqdm(total=n_instances, desc="Creating Pool") # initialize a list of dummy instances self._instances = [None for _ in range(n_instances)] # threaded spawn threads = [ self._spawn_mapdl(i, ports[i], pbar, name=f'Instance {i}') for i in range(n_instances) ] if wait: [thread.join() for thread in threads] # check if all clients connected have connected if len(self) != n_instances: n_connected = len(self) warnings.warn( f"Only %d clients connected out of %d requested" % (n_connected, n_instances)) if pbar is not None: pbar.close() # monitor pool if requested if restart_failed: self._pool_monitor_thread = self._monitor_pool( name='Monitoring_Thread') self._verify_unique_ports()
def launch_grpc(exec_file='', jobname='file', nproc=2, ram=None, run_location=None, port=MAPDL_DEFAULT_PORT, additional_switches='', custom_bin=None, override=True, timeout=20, verbose=False) -> int: """Start MAPDL locally in gRPC mode. Parameters ---------- exec_file : str, optional The location of the MAPDL executable. Will use the cached location when left at the default ``None``. jobname : str, optional MAPDL jobname. Defaults to ``'file'``. nproc : int, optional Number of processors. Defaults to 2. ram : float, optional Fixed amount of memory to request for MAPDL. If ``None``, then MAPDL will use as much as available on the host machine. run_location : str, optional MAPDL working directory. Defaults to a temporary working directory. port : int Port to launch MAPDL gRPC on. Final port will be the first port available after (or including) this port. additional_switches : str, optional Additional switches for MAPDL, for example aa_r, and academic research license, would be added with: - ``additional_switches="-aa_r"`` Avoid adding switches like -i -o or -b as these are already included to start up the MAPDL server. See the notes section for additional details. custom_bin : str, optional Path to the MAPDL custom executable. override : bool, optional Attempts to delete the lock file at the run_location. Useful when a prior MAPDL session has exited prematurely and the lock file has not been deleted. verbose : bool, optional Print all output when launching and running MAPDL. Not recommended unless debugging the MAPDL start. Default ``False``. Returns ------- port : int Returns the port number that the gRPC instance started on. Examples -------- Launch MAPDL using the default configuration. >>> from ansys.mapdl import launch_mapdl >>> mapdl = launch_mapdl() Run MAPDL with shared memory parallel and specify the location of the ansys binary. >>> exec_file = 'C:/Program Files/ANSYS Inc/v202/ansys/bin/win64/ANSYS202.exe' >>> mapdl = launch_mapdl(exec_file, additional_switches='-smp') Notes ----- These are the MAPDL switch options as of 2020R2 applicable for running MAPDL as a service via gRPC. Excluded switches such as ``"-j"`` either not applicable or are set via keyword arguments. -acc <device> : Enables the use of GPU hardware. See GPU Accelerator Capability in the Parallel Processing Guide for more information. -amfg : Enables the additive manufacturing capability. Requires an additive manufacturing license. For general information about this feature, see AM Process Simulation in ANSYS Workbench. -ansexe <executable> : Activates a custom mechanical APDL executable. In the ANSYS Workbench environment, activates a custom Mechanical APDL executable. -custom <executable> : Calls a custom Mechanical APDL executable See Running Your Custom Executable in the Programmer's Reference for more information. -db value : Initial memory allocation Defines the portion of workspace (memory) to be used as the initial allocation for the database. The default is 1024 MB. Specify a negative number to force a fixed size throughout the run; useful on small memory systems. -dis : Enables Distributed ANSYS See the Parallel Processing Guide for more information. -dvt : Enables ANSYS DesignXplorer advanced task (add-on). Requires DesignXplorer. -l <language> : Specifies a language file to use other than English This option is valid only if you have a translated message file in an appropriately named subdirectory in ``/ansys_inc/v201/ansys/docu`` or ``Program Files\\ANSYS\\Inc\\V201\\ANSYS\\docu`` -m <workspace> : Specifies the total size of the workspace Workspace (memory) in megabytes used for the initial allocation. If you omit the ``-m`` option, the default is 2 GB (2048 MB). Specify a negative number to force a fixed size throughout the run. -machines <IP> : Specifies the distributed machines Machines on which to run a Distributed ANSYS analysis. See Starting Distributed ANSYS in the Parallel Processing Guide for more information. -mpi <value> : Specifies the type of MPI to use. See the Parallel Processing Guide for more information. -mpifile <appfile> : Specifies an existing MPI file Specifies an existing MPI file (appfile) to be used in a Distributed ANSYS run. See Using MPI Files in the Parallel Processing Guide for more information. -na <value>: Specifies the number of GPU accelerator devices Number of GPU devices per machine or compute node when running with the GPU accelerator feature. See GPU Accelerator Capability in the Parallel Processing Guide for more information. -name <value> : Defines Mechanical APDL parameters Set mechanical APDL parameters at program start-up. The parameter name must be at least two characters long. For details about parameters, see the ANSYS Parametric Design Language Guide. -p <productname> : ANSYS session product Defines the ANSYS session product that will run during the session. For more detailed information about the ``-p`` option, see Selecting an ANSYS Product via the Command Line. -ppf <license feature name> : HPC license Specifies which HPC license to use during a parallel processing run. See HPC Licensing in the Parallel Processing Guide for more information. -smp : Enables shared-memory parallelism. See the Parallel Processing Guide for more information. """ # disable all MAPDL pop-up errors: os.environ['ANS_CMD_NODIAG'] = 'TRUE' # use temporary directory if run_location is unspecified if run_location is None: run_location = create_temp_dir() elif not os.path.isdir(run_location): os.mkdir(run_location) if not os.access(run_location, os.W_OK): raise IOError('Unable to write to ``run_location`` "%s"' % run_location) # verify version if _version_from_path(exec_file) < 202: raise VersionError('The MAPDL gRPC interface requires MAPDL 20.2 or later') # verify lock file does not exist check_lock_file(run_location, jobname, override) # get the next available port if port is None: if not pymapdl._LOCAL_PORTS: port = MAPDL_DEFAULT_PORT else: port = max(pymapdl._LOCAL_PORTS) + 1 while port_in_use(port) or port in pymapdl._LOCAL_PORTS: port += 1 pymapdl._LOCAL_PORTS.append(port) cpu_sw = '-np %d' % nproc if ram: ram_sw = '-m %d' % int(1024*ram) else: ram_sw = '' job_sw = '-j %s' % jobname port_sw = '-port %d' % port grpc_sw = '-grpc' # remove any temporary error files at the run location. This is # important because we need to know if MAPDL is already running # here and because we're looking for any temporary files that are # created to tell when the process has started for filename in os.listdir(run_location): if ".err" == filename[-4:] and jobname in filename: try: os.remove(filename) except: raise IOError('Unable to remove {filename}. There might be ' 'an instance of MAPDL running at this location') # Windows will spawn a new window, only linux will let you use pexpect... if os.name == 'nt': # track PIDs since MAPDL isn't directly launched within the shell tmp_inp = '.__tmp__.inp' with open(os.path.join(run_location, tmp_inp), 'w') as f: f.write('FINISH\r\n') # must start in batch mode on windows to hide APDL window command = ['"%s"' % exec_file, job_sw, cpu_sw, ram_sw, '-b', '-i', tmp_inp, '-o', '.__tmp__.out', additional_switches, port_sw, grpc_sw] command = ' '.join(command) else: # linux command_parm = [] command_parm.extend(['"%s"' % exec_file, job_sw, cpu_sw, ram_sw, additional_switches, port_sw, grpc_sw]) command = ' '.join(command_parm) if verbose: print(f'Running {command}') subprocess.Popen(command, shell=os.name != 'nt', cwd=run_location) else: subprocess.Popen(command, shell=os.name != 'nt', cwd=run_location, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # watch for the creation of temporary files at the run_directory. # This lets us know that the MAPDL process has at least started sleep_time = 0.1 for _ in range(int(timeout/sleep_time)): # check if any error files have been created. This is # more reliable than using the lock file files = os.listdir(run_location) has_ans = any([filename for filename in files if ".err" in filename]) if has_ans: break time.sleep(sleep_time) return port, run_location