From 06397a318a18737902177755a55406cf648609e5 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:47:39 +0100 Subject: [PATCH 1/5] refactor: adding logging calls to misc.py (#3550) --- doc/changelog.d/3550.added.md | 1 + src/ansys/mapdl/core/misc.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 doc/changelog.d/3550.added.md diff --git a/doc/changelog.d/3550.added.md b/doc/changelog.d/3550.added.md new file mode 100644 index 0000000000..9354879ed5 --- /dev/null +++ b/doc/changelog.d/3550.added.md @@ -0,0 +1 @@ +refactor: adding logging calls to misc.py \ No newline at end of file diff --git a/src/ansys/mapdl/core/misc.py b/src/ansys/mapdl/core/misc.py index 138eb23522..4fbc42d7d1 100644 --- a/src/ansys/mapdl/core/misc.py +++ b/src/ansys/mapdl/core/misc.py @@ -183,6 +183,7 @@ def wrapper(*args, **kwargs): name = kwargs.get("name", f"Threaded `{func.__name__}` function") thread = Thread(target=func, name=name, args=args, kwargs=kwargs) thread.start() + LOG.debug(f"Thread started with name: {name}") return thread return wrapper @@ -196,9 +197,11 @@ def wrapper(*args, **kwargs): name = kwargs.pop( "thread_name", f"Threaded (with Daemon) `{func.__name__}` function" ) + thread = Thread(target=func, name=name, args=args, kwargs=kwargs) thread.daemon = True thread.start() + LOG.debug(f"Thread demon started with name: {name}") return thread return wrapper @@ -229,8 +232,10 @@ def creation_time(path_to_file): try: return stat.st_birthtime except AttributeError: - # We're probably on Linux. No easy way to get creation dates here, - # so we'll settle for when its content was last modified. + LOG.debug( + "We're probably on Linux. No easy way to get creation dates here, " + "so we'll settle for when its content was last modified." + ) return stat.st_mtime @@ -280,6 +285,7 @@ def no_return(func): def wrapper(*args, **kwargs): func(*args, **kwargs) + LOG.debug("Output has been suppressed.") return wrapper From bf13bff2c71a8f262306fd9d0b50667ebb67bff6 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:51:34 +0100 Subject: [PATCH 2/5] doc: Update pymapdl.rst (#3527) * Update pymapdl.rst * chore: adding changelog file 3527.documentation.md [dependabot-skip] --------- Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> --- doc/changelog.d/3527.documentation.md | 1 + doc/source/user_guide/hpc/pymapdl.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 doc/changelog.d/3527.documentation.md diff --git a/doc/changelog.d/3527.documentation.md b/doc/changelog.d/3527.documentation.md new file mode 100644 index 0000000000..f8883cc2ba --- /dev/null +++ b/doc/changelog.d/3527.documentation.md @@ -0,0 +1 @@ +DOC: Update pymapdl.rst \ No newline at end of file diff --git a/doc/source/user_guide/hpc/pymapdl.rst b/doc/source/user_guide/hpc/pymapdl.rst index 76d27f75ee..00ed2cb135 100644 --- a/doc/source/user_guide/hpc/pymapdl.rst +++ b/doc/source/user_guide/hpc/pymapdl.rst @@ -11,7 +11,7 @@ Introduction PyMAPDL communicates with MAPDL using the gRPC protocol. This protocol offers the many advantages and features described in -see :ref:`ref_project_page`. +:ref:`ref_project_page`. One of these features is that it is not required to have both PyMAPDL and MAPDL processes running on the same machine. This possibility opens the door to many configurations, depending From 2696095bb02627592c3b49d1706e643cdac58a44 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:12:09 +0100 Subject: [PATCH 3/5] docs: extracting information to another rst file (#3549) * docs: extracting information to another rst file * chore: adding changelog file 3549.documentation.md [dependabot-skip] --------- Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> --- doc/changelog.d/3549.documentation.md | 1 + doc/source/api/index.rst | 1 + doc/source/api/information.rst | 35 +++++++++++ doc/source/api/mapdl.rst | 90 ++++++++++++++++----------- src/ansys/mapdl/core/mapdl_core.py | 15 ++++- src/ansys/mapdl/core/mapdl_grpc.py | 41 ++++++------ 6 files changed, 126 insertions(+), 57 deletions(-) create mode 100644 doc/changelog.d/3549.documentation.md create mode 100644 doc/source/api/information.rst diff --git a/doc/changelog.d/3549.documentation.md b/doc/changelog.d/3549.documentation.md new file mode 100644 index 0000000000..a119c57cd2 --- /dev/null +++ b/doc/changelog.d/3549.documentation.md @@ -0,0 +1 @@ +docs: extracting information to another rst file \ No newline at end of file diff --git a/doc/source/api/index.rst b/doc/source/api/index.rst index 459792ce43..599d31e141 100644 --- a/doc/source/api/index.rst +++ b/doc/source/api/index.rst @@ -23,6 +23,7 @@ PyMAPDL, see :ref:`ref_mapdl_commands`. database geometry helper + information inline krylov launcher diff --git a/doc/source/api/information.rst b/doc/source/api/information.rst new file mode 100644 index 0000000000..a72b55a4fd --- /dev/null +++ b/doc/source/api/information.rst @@ -0,0 +1,35 @@ +.. _ref_information_api: + +``Information`` module +====================== + +``Information`` class attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. currentmodule:: ansys.mapdl.core.information + +.. autosummary:: + :toctree: _autosummary + + Information.aux_capabilities + Information.boundary_condition_information + Information.config_values + Information.database_status + Information.global_status + Information.job_information + Information.load_step_options + Information.mapdl_version + Information.model_information + Information.post_capabilities + Information.preprocessing_capabilities + Information.product + Information.products + Information.pymapdl_version + Information.routine_information + Information.scratch_memory_status + Information.solution_options + Information.solution_options_configuration + Information.stitles + Information.title + Information.titles + Information.units diff --git a/doc/source/api/mapdl.rst b/doc/source/api/mapdl.rst index 5835b572d6..0755b4f35f 100644 --- a/doc/source/api/mapdl.rst +++ b/doc/source/api/mapdl.rst @@ -14,30 +14,68 @@ :toctree: _autosummary Mapdl.add_file_handler + Mapdl.allow_ignore + Mapdl.busy Mapdl.chain_commands + Mapdl.check_parameter_names + Mapdl.default_file_type_for_plots Mapdl.directory + Mapdl.exited + Mapdl.exiting + Mapdl.file_type_for_plots + Mapdl.finish_job_on_exit + Mapdl.force_output Mapdl.get Mapdl.get_array + Mapdl.get_esol + Mapdl.get_nodal_constrains + Mapdl.get_nodal_loads + Mapdl.get_nsol Mapdl.get_value + Mapdl.get_variable + Mapdl.hostname Mapdl.ignore_errors + Mapdl.info + Mapdl.input_strings + Mapdl.is_alive + Mapdl.is_console + Mapdl.is_corba + Mapdl.is_grpc + Mapdl.jobid Mapdl.jobname + Mapdl.kill_job Mapdl.last_response + Mapdl.launched + Mapdl.list_error_file + Mapdl.list_files + Mapdl.load_array Mapdl.load_table - Mapdl.mesh - Mapdl.modal_analysis + Mapdl.locked + Mapdl.logger + Mapdl.mapdl_on_hpc + Mapdl.mute + Mapdl.name Mapdl.non_interactive + Mapdl.on_docker Mapdl.open_apdl_log Mapdl.open_gui - Mapdl.parameters + Mapdl.platform + Mapdl.print_com + Mapdl.process_is_alive + Mapdl.remove_file_handler Mapdl.remove_temp_dir_on_exit Mapdl.result + Mapdl.result_file Mapdl.run + Mapdl.run_as_routine Mapdl.run_multiline - Mapdl.input_strings + Mapdl.save_selection + Mapdl.scalar_param + Mapdl.screenshot Mapdl.set_log_level - Mapdl.version + Mapdl.thermal_result Mapdl.use_vtk - Mapdl.file_type_for_plots + Mapdl.version Constants @@ -57,40 +95,18 @@ Constants .. autosummary:: :toctree: _autosummary + mapdl_grpc.MapdlGrpc.channel_state + mapdl_grpc.MapdlGrpc.check_status + mapdl_grpc.MapdlGrpc.connection mapdl_grpc.MapdlGrpc.download + mapdl_grpc.MapdlGrpc.download_project + mapdl_grpc.MapdlGrpc.download_result + mapdl_grpc.MapdlGrpc.file + mapdl_grpc.MapdlGrpc.ip + mapdl_grpc.MapdlGrpc.is_local mapdl_grpc.MapdlGrpc.list_error_file mapdl_grpc.MapdlGrpc.list_files mapdl_grpc.MapdlGrpc.mute + mapdl_grpc.MapdlGrpc.port mapdl_grpc.MapdlGrpc.upload - -``Information`` class attributes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. currentmodule:: ansys.mapdl.core.information - -.. autosummary:: - :toctree: _autosummary - - Information.product - Information.mapdl_version - Information.pymapdl_version - Information.products - Information.preprocessing_capabilities - Information.aux_capabilities - Information.solution_options - Information.post_capabilities - Information.title - Information.titles - Information.stitles - Information.units - Information.scratch_memory_status - Information.database_status - Information.config_values - Information.global_status - Information.job_information - Information.model_information - Information.boundary_condition_information - Information.routine_information - Information.solution_options_configuration - Information.load_step_options diff --git a/src/ansys/mapdl/core/mapdl_core.py b/src/ansys/mapdl/core/mapdl_core.py index 2a59332b9a..0e5d1cb8a7 100644 --- a/src/ansys/mapdl/core/mapdl_core.py +++ b/src/ansys/mapdl/core/mapdl_core.py @@ -295,7 +295,7 @@ def __init__( self._start_parm: Dict[str, Any] = start_parm self._jobname: str = start_parm.get("jobname", "file") self._path: Union[str, pathlib.Path] = start_parm.get("run_location", None) - self.check_parameter_names = start_parm.get("check_parameter_names", True) + self._check_parameter_names = start_parm.get("check_parameter_names", True) # Setting up loggers self._log: logger = logger.add_instance_logger( @@ -715,8 +715,19 @@ def launched(self): """Check if the MAPDL instance has been launched by PyMAPDL.""" return self._launched + @property + def check_parameter_names(self): + """Whether check if the name which is given to the parameter is allowed or not""" + return self._check_parameter_names + + @check_parameter_names.setter + def check_parameter_names(self, value: bool): + """Whether check if the name which is given to the parameter is allowed or not""" + self._check_parameter_names = value + @property def logger(self) -> logging.Logger: + """MAPDL Python-based logger""" return self._log @property @@ -870,6 +881,8 @@ def post_processing(self) -> "PostProcessing": @property def print_com(self): + """Whether to print or not to the console the + :meth:`mapdl.com ("/COM") ` calls.""" return self._print_com @print_com.setter diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index 3e80ea3e86..d32f67de61 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -629,6 +629,7 @@ def _is_alive_subprocess(self): @property def process_is_alive(self): + """Check if the MAPDL process is alive""" return self._is_alive_subprocess() def _post_mortem_checks(self): @@ -3403,24 +3404,20 @@ def get_esol( node : int Node number on this element for which data are to be stored. If blank, store the average element value (except - for FMAG values, which are summed instead of averaged). + for ``FMAG`` values, which are summed instead of averaged). item : str - Label identifying the item. General item labels are shown - in Table 134: ESOL - General Item and Component Labels - below. Some items also require a component label. + Label identifying the item. Some items also require a component label. comp : str - Component of the item (if required). General component - labels are shown in Table 134: ESOL - General Item and - Component Labels below. If Comp is a sequence number (n), - the NODE field will be ignored. + Component of the item (if required). If Comp is a sequence number (n), + the ``NODE`` field will be ignored. name : str, optional Thirty-two character name for identifying the item on the printout and displays. The default is a label formed by concatenating the first four characters of the ``item`` and - ``comp`` labels. + ``comp`` labels. tstrt : str, optional Time (or frequency) corresponding to start of IR data. If between @@ -3441,21 +3438,18 @@ def get_esol( Notes ----- By default, this command store temporally the variable on the - variable number set by ``VAR_IR`` in the class MapdlGrpc. + variable number set by ``VAR_IR`` in the class + :class:`Mapdl ` Therefore, any variable in that slot will be deleted when using this command. - See Table: 134:: ESOL - General Item and Component Labels for - a list of valid item and component labels for element (except - line element) results. - - The ESOL command defines element results data to be stored - from a results file (FILE). Not all items are valid for all + The ``ESOL`` command defines element results data to be stored + from a results file (``FILE``). Not all items are valid for all elements. To see the available items for a given element, refer to the input and output summary tables in the documentation for that element. - Two methods of data access are available via the ESOL + Two methods of data access are available via the ``ESOL`` command. You can access some simply by using a generic label (component name method), while others require a label and number (sequence number method). @@ -3476,10 +3470,10 @@ def get_esol( system. Element forces and moments are in the nodal coordinate system. Results are obtainable for an element at a specified node. Further location specifications can be made - for some elements via the SHELL, LAYERP26, and FORCE commands. + for some elements via the ``SHELL``, ``LAYERP26``, and ``FORCE`` commands. For more information on the meaning of contact status and its - possible values, see Reviewing Results in POST1 in the Contact + possible values, see Reviewing Results in ``POST1`` in the Contact Technology Guide. """ self.esol( @@ -3759,6 +3753,15 @@ def get_file_name(path): return os.path.basename(target_dir) def kill_job(self, jobid: int) -> None: + """Kill an HPC job + + Kill a job given its identifier. + + Parameters + ---------- + jobid : int + Job ID. + """ cmd = ["scancel", f"{jobid}"] # to ensure the job is stopped properly, let's issue the scancel twice. subprocess.Popen(cmd) From d7e7981f1e6ee626c08d45f4658151f91a94c4c5 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:51:12 +0100 Subject: [PATCH 4/5] refactor: removing-`run_as_prep7`-in-favour-of-`run_as` (#3551) * refactor: using a common wrapper based on context manager * refactor: replace elsewhere * ci: auto fixes from pre-commit.com hooks. for more information, see https://pre-commit.ci * chore: adding changelog file 3551.added.md [dependabot-skip] * feat: making sure we are properly getting the mapdl object in the wrappers --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> --- doc/changelog.d/3551.added.md | 1 + src/ansys/mapdl/core/mapdl_core.py | 4 +-- src/ansys/mapdl/core/mapdl_geometry.py | 4 +-- src/ansys/mapdl/core/mapdl_grpc.py | 4 +-- src/ansys/mapdl/core/misc.py | 39 +++++++++++++++----------- tests/test_misc.py | 4 +-- 6 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 doc/changelog.d/3551.added.md diff --git a/doc/changelog.d/3551.added.md b/doc/changelog.d/3551.added.md new file mode 100644 index 0000000000..987638c792 --- /dev/null +++ b/doc/changelog.d/3551.added.md @@ -0,0 +1 @@ +refactor: removing-`run_as_prep7`-in-favour-of-`run_as` \ No newline at end of file diff --git a/src/ansys/mapdl/core/mapdl_core.py b/src/ansys/mapdl/core/mapdl_core.py index 0e5d1cb8a7..8d6cba88d8 100644 --- a/src/ansys/mapdl/core/mapdl_core.py +++ b/src/ansys/mapdl/core/mapdl_core.py @@ -72,7 +72,7 @@ last_created, random_string, requires_package, - run_as_prep7, + run_as, supress_logging, ) @@ -1574,7 +1574,7 @@ def open_apdl_log( ) @supress_logging - @run_as_prep7 + @run_as("PREP7") def _generate_iges(self): """Save IGES geometry representation to disk""" filename = os.path.join(self.directory, "_tmp.iges") diff --git a/src/ansys/mapdl/core/mapdl_geometry.py b/src/ansys/mapdl/core/mapdl_geometry.py index c008d22e31..fca96f5861 100644 --- a/src/ansys/mapdl/core/mapdl_geometry.py +++ b/src/ansys/mapdl/core/mapdl_geometry.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: # pragma: no cover from pyiges import Iges -from ansys.mapdl.core.misc import requires_package, run_as_prep7, supress_logging +from ansys.mapdl.core.misc import requires_package, run_as, supress_logging from ansys.mapdl.core.plotting.theme import MapdlTheme VALID_SELECTION_TYPE = ["S", "R", "A", "U"] @@ -614,7 +614,7 @@ def get_areas( return areas @supress_logging - @run_as_prep7 + @run_as("PREP7") @requires_package("pyvista") def generate_surface( self, diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index d32f67de61..a15982ce12 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -90,7 +90,7 @@ last_created, only_numbers_and_dots, random_string, - run_as_prep7, + run_as, supress_logging, ) from ansys.mapdl.core.parameters import interp_star_status @@ -2961,7 +2961,7 @@ def __str__(self): return info @supress_logging - @run_as_prep7 + @run_as("PREP7") def _generate_iges(self): """Save IGES geometry representation to disk""" basename = "_tmp.iges" diff --git a/src/ansys/mapdl/core/misc.py b/src/ansys/mapdl/core/misc.py index 4fbc42d7d1..0e2061b874 100644 --- a/src/ansys/mapdl/core/misc.py +++ b/src/ansys/mapdl/core/misc.py @@ -136,7 +136,15 @@ def supress_logging(func): @wraps(func) def wrapper(*args, **kwargs): + from ansys.mapdl.core.mapdl import MapdlBase + mapdl = args[0] + if not issubclass(type(mapdl), (MapdlBase)): + # Assuming we are on a module object. + mapdl = mapdl._mapdl + if not issubclass(type(mapdl), (MapdlBase)): + raise Exception("This wrapper cannot access MAPDL object") + prior_log_level = mapdl._log.level if prior_log_level != "CRITICAL": mapdl._set_log_level("CRITICAL") @@ -151,28 +159,27 @@ def wrapper(*args, **kwargs): return wrapper -def run_as_prep7(func): +def run_as(routine: ROUTINES): """Run a MAPDL method at PREP7 and always revert to the prior processor""" - @wraps(func) - def wrapper(*args, **kwargs): - mapdl = args[0] - if hasattr(mapdl, "_mapdl"): - mapdl = mapdl._mapdl - prior_processor = mapdl.parameters.routine - if prior_processor != "PREP7": - mapdl.prep7() + def decorator(function): + @wraps(function) + def wrapper(self, *args, **kwargs): + from ansys.mapdl.core.mapdl import MapdlBase - out = func(*args, **kwargs) + mapdl = self + if not issubclass(type(mapdl), (MapdlBase)): + # Assuming we are on a module object. + mapdl = mapdl._mapdl + if not issubclass(type(mapdl), (MapdlBase)): + raise Exception("This wrapper cannot access MAPDL object") - if prior_processor == "Begin level": - mapdl.finish() - elif prior_processor != "PREP7": - mapdl.run("/%s" % prior_processor) + with mapdl.run_as_routine(routine.upper()): + return function(self, *args, **kwargs) - return out + return wrapper - return wrapper + return decorator def threaded(func): diff --git a/tests/test_misc.py b/tests/test_misc.py index 95266c70ca..1219da9675 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -36,7 +36,7 @@ load_file, no_return, requires_package, - run_as_prep7, + run_as, ) from conftest import requires @@ -103,7 +103,7 @@ def test_run_as_prep7(mapdl, cleared): mapdl.post1() assert "POST1" in mapdl.parameters.routine - @run_as_prep7 + @run_as("PREP7") def fun( mapdl, ): # This function is for mapdl methods, hence we have to pass the MAPDL instance somehow. From 6677797a5792012e5217f1d489942eaf467fd545 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:51:43 +0100 Subject: [PATCH 5/5] fix: warning and add an exception if using class alone (#3552) * fix: warning and add an exception if using class alone * chore: adding changelog file 3552.fixed.md [dependabot-skip] * ci: auto fixes from pre-commit.com hooks. for more information, see https://pre-commit.ci * feat: clarifying warning --------- Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- doc/changelog.d/3552.fixed.md | 1 + src/ansys/mapdl/core/mapdl.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 doc/changelog.d/3552.fixed.md diff --git a/doc/changelog.d/3552.fixed.md b/doc/changelog.d/3552.fixed.md new file mode 100644 index 0000000000..382312cd67 --- /dev/null +++ b/doc/changelog.d/3552.fixed.md @@ -0,0 +1 @@ +fix: warning and add an exception if using class alone \ No newline at end of file diff --git a/src/ansys/mapdl/core/mapdl.py b/src/ansys/mapdl/core/mapdl.py index 6528dcaa2b..5f0b58005e 100644 --- a/src/ansys/mapdl/core/mapdl.py +++ b/src/ansys/mapdl/core/mapdl.py @@ -27,7 +27,7 @@ class MapdlBase(_MapdlExtended): """Base MAPDL class shared across all MAPDL subclasses. .. warning:: This class should NOT be imported by itself. - You should always import a subclass of it - """ + You should always import a subclass of it like + :class:`MapdlGrpc ` - pass + """