From 0f4e0076f3b9fe7df67c3c0ebe00c56eccef3a47 Mon Sep 17 00:00:00 2001 From: Julian Giordani Date: Wed, 21 Aug 2024 13:35:38 +1000 Subject: [PATCH] Rename uw_record -> auditor * access via underworld3.auditor * test included in test_0005_utils.py --- src/underworld3/__init__.py | 3 +- src/underworld3/utilities/__init__.py | 113 +--------------------- src/underworld3/utilities/_utils.py | 130 ++++++++++++++++++++++---- tests/test_0005_utils.py | 112 ++++++++++++++++++++++ 4 files changed, 229 insertions(+), 129 deletions(-) create mode 100644 tests/test_0005_utils.py diff --git a/src/underworld3/__init__.py b/src/underworld3/__init__.py index 47abc6ff2..c6e9de3c2 100644 --- a/src/underworld3/__init__.py +++ b/src/underworld3/__init__.py @@ -101,9 +101,10 @@ def view(): from ._var_types import * from .utilities._petsc_tools import * from .utilities._nb_tools import * -from .utilities import uw_record # grab record class +from .utilities._utils import auditor from underworld3.utilities import _api_tools +from .utilities import auditor import underworld3.adaptivity import underworld3.coordinates diff --git a/src/underworld3/utilities/__init__.py b/src/underworld3/utilities/__init__.py index 36937d1b8..ffab01a90 100644 --- a/src/underworld3/utilities/__init__.py +++ b/src/underworld3/utilities/__init__.py @@ -16,118 +16,7 @@ def _append_petsc_path(): from .uw_petsc_gen_xdmf import Xdmf, generateXdmf, generate_uw_Xdmf from .uw_swarmIO import swarm_h5, swarm_xdmf -from ._utils import CaptureStdout, h5_scan, mem_footprint, gather_data +from ._utils import CaptureStdout, h5_scan, mem_footprint, gather_data, auditor from .read_medit_ascii import read_medit_ascii, print_medit_mesh_info from .create_dmplex_from_medit import create_dmplex_from_medit - -class _uw_record(): - - def __init__(self): - """ - A class to record runtime information about the underworld3 execution environment. - """ - try: - import mpi4py - comm = mpi4py.MPI.COMM_WORLD - except ImportError: - raise ImportError("Can't import mpi4py for runtime information.") - - - # rank 0 only builds the data and then broadcasts it - self._install_data = None - self._runtime_data = None - if comm.rank == 0: - - import sys - import datetime - import subprocess - import warnings - - # get the start time of this piece of code - start_t = datetime.datetime.now().isoformat() - - # get the git version - try: - gv = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8') - except Exception as e: - gv = None - warnings.warn( f"Warning: Underworld can't retrieving commit hash: {e}" ) - - # get petsc information - try: - import petsc4py as _petsc4py - from petsc4py import PETSc as _PETSc - petsc_version = _PETSc.Sys.getVersion() - petsc_dir = _petsc4py.get_config()['PETSC_DIR'] - except Exception as e: - petsc_version = None - petsc_dir = None - warnings.warn( f"Warning: Underworld can't retrieving petsc installation details: {e}" ) - - # get h5py information - try: - import h5py as _h5py - h5py_dir = _h5py.__file__ - h5py_version = _h5py.version.version - hdf5_version = _h5py.version.hdf5_version - except Exception as e: - h5py_dir = None - h5py_version = None - hdf5_version = None - warnings.warn( f"Warning: Underworld can't retrieving h5py installation details: {e}" ) - - # get mpi4py information - try: - import mpi4py as _mpi4py - mpi4py_version = _mpi4py.__version__ - except Exception as e: - mpi4py_version = None - warnings.warn( f"Warning: Underworld can't retrieving mpi4py installation details: {e}" ) - - # get just the version - from underworld3 import __version__ as uw_version - - self._install_data = { - "git_version": gv, - "uw_version": uw_version, - "python_versions": sys.version, - "petsc_version": petsc_version, - "petsc_dir": petsc_dir, - "h5py_version": h5py_version, - "hdf5_version": hdf5_version, - "h5py_dir": h5py_dir, - "mpi4py_version": mpi4py_version, - } - - self._runtime_data = { - "start_time": start_t, - "uw_object_count": 0, - } - - # rank 0 broadcast information to other procs - self._install_data = comm.bcast(self._install_data, root=0) - - @property - def get_installation_data(self): - return self._install_data - - @property - def get_runtime_data(self): - import datetime - import mpi4py - comm = mpi4py.MPI.COMM_WORLD - - if comm.rank == 0: - now = datetime.datetime.now().isoformat() - self._runtime_data.update({"current_time": now}) - - from underworld3.utilities._api_tools import uw_object - object_count = uw_object.uw_object_counter - self._runtime_data.update({"uw_object_count": object_count}) - - self._runtime_data = comm.bcast(self._runtime_data, root=0) - return self._runtime_data - -uw_record = _uw_record() - diff --git a/src/underworld3/utilities/_utils.py b/src/underworld3/utilities/_utils.py index cc68c73e9..f42350250 100755 --- a/src/underworld3/utilities/_utils.py +++ b/src/underworld3/utilities/_utils.py @@ -7,23 +7,121 @@ from collections import UserString from contextlib import redirect_stdout, redirect_stderr +class _uw_record(): + """ + A class to record runtime information about the underworld3 execution environment. + """ -# # Capture the stdout to an object -# class CaptureStdout(list): -# def __enter__(self, split=True): -# self._stdout = sys.stdout -# self.split = split -# sys.stdout = self._stringio = StringIO() -# return self - -# def __exit__(self, *args): -# if split: -# self.extend(self._stringio.getvalue().splitlines()) -# else: -# self.extend(self._stringio.getvalue() -# del self._stringio # free up some memory -# sys.stdout = self._stdout - + def __init__(self): + try: + import mpi4py + comm = mpi4py.MPI.COMM_WORLD + except ImportError: + raise ImportError("Can't import mpi4py for runtime information.") + + # rank 0 only builds the data and then broadcasts it + self._install_data = None + self._runtime_data = None + if comm.rank == 0: + + import sys + import datetime + import subprocess + import warnings + + # get the start time of this piece of code + start_t = datetime.datetime.now().isoformat() + + # get the git version + try: + gv = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8') + except Exception as e: + gv = None + warnings.warn( f"Warning: Underworld can't retrieving commit hash: {e}" ) + + # get petsc information + try: + import petsc4py as _petsc4py + from petsc4py import PETSc as _PETSc + petsc_version = _PETSc.Sys.getVersion() + petsc_dir = _petsc4py.get_config()['PETSC_DIR'] + except Exception as e: + petsc_version = None + petsc_dir = None + warnings.warn( f"Warning: Underworld can't retrieving petsc installation details: {e}" ) + + # get h5py information + try: + import h5py as _h5py + h5py_dir = _h5py.__file__ + h5py_version = _h5py.version.version + hdf5_version = _h5py.version.hdf5_version + except Exception as e: + h5py_dir = None + h5py_version = None + hdf5_version = None + warnings.warn( f"Warning: Underworld can't retrieving h5py installation details: {e}" ) + + # get mpi4py information + try: + import mpi4py as _mpi4py + mpi4py_version = _mpi4py.__version__ + except Exception as e: + mpi4py_version = None + warnings.warn( f"Warning: Underworld can't retrieving mpi4py installation details: {e}" ) + + # get just the version + from underworld3 import __version__ as uw_version + + self._install_data = { + "git_version": gv, + "uw_version": uw_version, + "python_versions": sys.version, + "petsc_version": petsc_version, + "petsc_dir": petsc_dir, + "hdf5_version": hdf5_version, + "h5py_version": h5py_version, + "h5py_dir": h5py_dir, + "mpi4py_version": mpi4py_version, + } + + self._runtime_data = { + "start_time": start_t, + "uw_object_count": 0, + } + + # rank 0 broadcast information to other procs + self._install_data = comm.bcast(self._install_data, root=0) + + @property + def get_installation_data(self): + ''' + Get the installation data for the underworld3 installation. + ''' + return self._install_data + + @property + def get_runtime_data(self): + ''' + Get the runtime data for the underworld3 installation. + Note this requires a MPI broadcast to get the data. + ''' + import datetime + import mpi4py + comm = mpi4py.MPI.COMM_WORLD + + if comm.rank == 0: + now = datetime.datetime.now().isoformat() + self._runtime_data.update({"current_time": now}) + + from underworld3.utilities._api_tools import uw_object + object_count = uw_object.uw_object_counter + self._runtime_data.update({"uw_object_count": object_count}) + + self._runtime_data = comm.bcast(self._runtime_data, root=0) + return self._runtime_data + +auditor = _uw_record() class CaptureStdout(UserString, redirect_stdout): """ diff --git a/tests/test_0005_utils.py b/tests/test_0005_utils.py new file mode 100644 index 000000000..3aad1599e --- /dev/null +++ b/tests/test_0005_utils.py @@ -0,0 +1,112 @@ +# --- +# jupyter: +# jupytext: +# formats: ipynb,py:percent +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.16.2 +# kernelspec: +# display_name: Python 3 (ipykernel) +# language: python +# name: python3 +# --- + +# %% +import underworld3 as uw +import sympy + +# %% +mesh = uw.meshing.StructuredQuadBox(elementRes=(10,) * 2) +x, y = mesh.X + +# %% +v = uw.discretisation.MeshVariable( r"mathbf{u}", mesh, mesh.dim, vtype=uw.VarType.VECTOR, degree=2) +p = uw.discretisation.MeshVariable( r"mathbf{p}", mesh, 1, vtype=uw.VarType.SCALAR, degree=1) + +def bc_1(solver): + s1 = solver + s1.add_dirichlet_bc((0.0, 0.0), "Bottom") + s1.add_dirichlet_bc((y, 0.0), "Top") + + s1.add_dirichlet_bc((sympy.oo, 0.0), "Left") + s1.add_dirichlet_bc((sympy.oo, 0.0), "Right") + +def bc_2(solver): + s1 = solver + s1.add_dirichlet_bc((0.0, sympy.oo), "Bottom") + s1.add_dirichlet_bc((0.0, sympy.oo), "Top") + + s1.add_dirichlet_bc((0.0, 0.0), "Left") + s1.add_dirichlet_bc((0.0, x), "Right") + + +# %% +def vis_model(mesh): + import pyvista as pv + import underworld3.visualisation as vis + + v = mesh.vars['mathbfu'] + pl = pv.Plotter(window_size=(1000, 750)) + + pvmesh = vis.mesh_to_pv_mesh(mesh) + pvmesh.point_data["V"] = vis.vector_fn_to_pv_points(pvmesh, v.sym) + pvmesh.point_data["Vmag"] = vis.scalar_fn_to_pv_points(pvmesh, v.sym.dot(v.sym)) + pvmesh.point_data["V1"] = vis.scalar_fn_to_pv_points(pvmesh, v.sym[1]) + + pl.add_mesh( + pvmesh, + cmap="coolwarm", + edge_color="Black", + show_edges=True, + scalars="Vmag", + use_transparency=False, + opacity=1.0, + ) + + velocity_points = vis.meshVariable_to_pv_cloud(v) + velocity_points.point_data["V"] = vis.vector_fn_to_pv_points(velocity_points, v.sym) + arrows = pl.add_arrows(velocity_points.points, velocity_points.point_data["V"], mag=3e-1, opacity=0.5, show_scalar_bar=False, cmap="coolwarm") + + pl.show(cpos="xy") + + + +# %% +stokes = uw.systems.Stokes(mesh, velocityField=v, pressureField=p) +stokes.constitutive_model = uw.constitutive_models.ViscousFlowModel +stokes.constitutive_model.Parameters.shear_viscosity_0 = 1 + +# %% +bc_1(stokes) + +# %% +stokes.solve() + +# %% +# vis_model(mesh) + +# %% +s1 = uw.systems.Stokes(mesh, velocityField=v, pressureField=p) +s1.constitutive_model = uw.constitutive_models.ViscousFlowModel +s1.constitutive_model.Parameters.shear_viscosity_0 = 1 +# stokes._rebuild_after_mesh_update() +bc_2(s1) + +# %% +#stokes.solve() +s1.solve() + +# %% +# vis_model(mesh) + +def test_auditor(): + # assert not values are in install data are None + for v in uw.auditor.get_installation_data.values(): + assert v is not None + + # assert 7 uw_objects are created + assert uw.auditor.get_runtime_data.get('uw_object_count') == 7 + +# %%