Skip to content

Commit

Permalink
Rename uw_record -> auditor
Browse files Browse the repository at this point in the history
* access via underworld3.auditor
* test included in test_0005_utils.py
  • Loading branch information
julesghub committed Aug 21, 2024
1 parent d237f33 commit 0f4e007
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 129 deletions.
3 changes: 2 additions & 1 deletion src/underworld3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
113 changes: 1 addition & 112 deletions src/underworld3/utilities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

130 changes: 114 additions & 16 deletions src/underworld3/utilities/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
112 changes: 112 additions & 0 deletions tests/test_0005_utils.py
Original file line number Diff line number Diff line change
@@ -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

# %%

0 comments on commit 0f4e007

Please sign in to comment.