Source code for dynamite.tools

'''
Various tools useful for writing and analyzing dynamite programs.
'''

import warnings


[docs] def MPI_COMM_WORLD(): ''' Returns PETSc's COMM_WORLD object. Can be converted to an mpi4py communicator object via the ``.tompi4py()`` method. ''' from . import config config._initialize() # dynamite must be initialized before importing PETSc from petsc4py import PETSc return PETSc.COMM_WORLD
[docs] def mpi_print(*args, rank=0, **kwargs): ''' Print from only a single MPI rank, default rank 0. Aside from the extra "rank" keywork argument, call signature is the same as Python 3's ``print()`` function. ''' if MPI_COMM_WORLD().rank == rank: print(*args, **kwargs)
[docs] def get_version(): ''' Gets the version information for dynamite, and the PETSc and SLEPc libraries it's built on. Returns ------- dict A dictionary with the keys 'PETSc', 'SLEPc', and 'dynamite' ''' from ._backend import bbuild from . import config config._initialize() from petsc4py import PETSc from slepc4py import SLEPc rtn = {} rtn['PETSc'] = PETSc.Sys.getVersionInfo() rtn['SLEPc'] = SLEPc.Sys.getVersionInfo() rtn['dynamite'] = {} rtn['dynamite']['commit'] = bbuild.get_build_commit() rtn['dynamite']['branch'] = bbuild.get_build_branch() rtn['dynamite']['version'] = bbuild.get_build_version() return rtn
[docs] def get_version_str(): ''' Get a string with the version information for PETSc, SLEPc, and dynamite. Returns ------- str The version string ''' info = get_version() dnm_version = info['dynamite']['version'] dnm_commit = info['dynamite']['commit'] dnm_branch = info['dynamite']['branch'] PETSc_v = '.'.join( [str(info['PETSc'][k]) for k in ['major', 'minor', 'subminor']] ) SLEPc_v = '.'.join( [str(info['SLEPc'][k]) for k in ['major', 'minor', 'subminor']] ) rtn = f'dynamite version {dnm_version} (commit {dnm_commit} on branch ' +\ f'"{dnm_branch}") built with PETSc {PETSc_v} and SLEPc {SLEPc_v}' return rtn
[docs] def track_memory(): ''' Begin tracking memory usage for a later call to ``get_memory_usage(..., max_usage=True)``. ''' from . import config config._initialize() from ._backend import bpetsc return bpetsc.track_memory()
[docs] def get_memory_usage(group_by='all', max_usage=False): ''' Get the memory usage, in gigabytes. .. note:: :meth:`track_memory` must be called before this function is called with ``max_usage=True``. .. note:: Grouping by node only works if MPI is configured to allow shared memory between ranks on the same node. If it is not, it may consider each rank its own "node." Whether this is the case can be seen by observing whether the value returned by this function is identical for all ranks on the same node, or if it is instead the same as the value returned for ``group_by='rank'``. Parameters ---------- group_by : str What ranks to sum memory usage over. Options are "rank", which will return each rank's individual memory usage (which may be different across ranks); "node", which will sum over ranks sharing the same memory (and thus again the result may differ between ranks); and "all", which returns the total memory usage of all ranks. max_usage : bool Instead of current memory usage, report maximum since the call to :meth:`track_memory()`. Note that maximum is only updated when PETSc objects are destroyed, which may be delayed due to garbage collection. Returns ------- float The memory usage in gigabytes ''' from . import config config._initialize() from ._backend import bpetsc if max_usage: local_usage = bpetsc.get_max_memory_usage()/1E9 else: local_usage = bpetsc.get_cur_memory_usage()/1E9 comm = MPI_COMM_WORLD() if group_by == 'rank' or comm.size == 1: return local_usage import mpi4py comm = comm.tompi4py() if group_by == 'node': split_comm = comm.Split_type(mpi4py.MPI.COMM_TYPE_SHARED) elif group_by == 'all': split_comm = comm else: raise ValueError(f"group_by must be 'rank', 'node', or 'all'; got '{group_by}'") return split_comm.allreduce(local_usage)
[docs] def get_max_memory_usage(which='all'): ''' [deprecated] ''' if which != 'all': raise ValueError('values of "which" other than "all" no longer supported') warnings.warn( "get_max_memory_usage() is deprecated; use get_memory_usage(max_usage=True) instead", DeprecationWarning, stacklevel=2 ) return get_memory_usage(group_by='rank', max_usage=True)
[docs] def get_cur_memory_usage(which='all'): ''' [deprecated] ''' if which != 'all': raise ValueError('values of "which" other than "all" no longer supported') warnings.warn( "get_cur_memory_usage() is deprecated; use get_memory_usage() instead", DeprecationWarning, stacklevel=2 ) return get_memory_usage(group_by='rank')
[docs] def complex_enabled(): from ._backend import bbuild return bbuild.complex_enabled()