# Copyright (C) 2011, 2014 David Maxwell # # This file is part of PISM. # # PISM is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # PISM is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License # along with PISM; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # See if we have been imported by sphinx. If so, we won't import any # packages that are not needed just to compile documentation. imported_from_sphinx = False import inspect caller_mod = inspect.getmodule(inspect.currentframe().f_back) if (caller_mod is not None) and caller_mod.__name__.startswith("sphinx"): imported_from_sphinx = True if not imported_from_sphinx: import petsc4py try: # Look if petsc4py has already been initialized PETSc = petsc4py.__getattribute__('PETSc') except: # If not, initialize petsc4py with the PETSc that PISM was compiled against. import sys from PISM.petsc_version import PISM_PETSC_ARCH petsc4py.init(sys.argv,arch=PISM_PETSC_ARCH) from petsc4py import PETSc if not imported_from_sphinx: try: import netCDF4 as netCDF except: print "netCDF4 is not installed!" sys.exit(1) # The following constants will be imported from 'cpp' if we are not # running inside sphinx. But if we are inside sphinx, then we'll # need them to be able to import submodules. if imported_from_sphinx: WITH_GHOSTS = True WITHOUT_GHOSTS = False SSAFEM = None SSAFD = None SIAFD = None IPDesignVariableParamIdent = None IPDesignVariableParamSquare = None IPDesignVariableParamExp = None IPDesignVariableParamTruncatedIdent = None IP_SSATaucForwardProblem = None IP_SSAHardavForwardProblem = None class IP_SSATaucTaoTikhonovProblemLCLListener: pass class IP_SSATaucTaoTikhonovProblemListener: pass class IP_SSAHardavTaoTikhonovProblemListener: pass if not imported_from_sphinx: from PISM.cpp import * import cpp from PISM.options import * import util import vec import ssa import sia import logging # import invert class Context(object): """Maintains PISM data that needs to exist only once per processor. * ``com`` an MPI Comm * ``rank`` the MPI rank of the current processor * ``size`` the number of processors * ``config`` an :cpp:class:`PISMConfig` There is only ever one :class:`Context`. If you make another one, you'll get the first one. You obtain the singleton as so:: context = PISM.Context() The ``config`` member variable is initialized the first time it is accessed. Optionally use :meth:`init_config` to perform initialization (e.g. overides) before accessing it. """ # Implement a Singleton pattern by overriding __new__ _instance = None def __new__(cls): if cls._instance is None: cls._instance = super(Context,cls).__new__(cls) cls._instance.__init_once__() return cls._instance # Since __init__ is always called after __new__, we don't # want to put code that only gets run once in __init__. def __init_once__(self): self.com = PETSc.COMM_WORLD self.rank = PETSc.Comm.getRank(self.com) self.size = PETSc.Comm.getSize(self.com) self._config = None def __getattr__(self,key): """We want the variable 'config' to look like a member. We also want to delay initializing it until after the user has had a chance to do custom initialization with Context.init_config. And we want to perform a default initialization if the user accesses config without performing a custom initialization. This method makes 'config' look like a member and performs initialization if it has not already been done. """ if key == 'config': if self._config is None: self.init_config() return self._config raise AttributeError(key) def init_config(self,overrides=None,unit_system=None,use_command_line_options=True): """Initializes the global :cpp:class:`PISMConfig`. :param overrides: A :cpp:class:`PISMConfig` to contain parameter overrides specified via ``-config_override``. :param unit_system: A :cpp:class:`PISMUnitSystem` for unit conversion (``None`` for default). :param use_command_line_options: A boolean indicating if variables should be additionally overridden by command-line counterparts.""" if not self._config is None: raise RuntimeError("global config already initialized") system = PISM.PISMUnitSystem(unit_system) self._config = PISMConfig(self.com, "pism_config", system) if overrides is None: overrides = PISMConfig(self.com, "pism_overrides", system) init_config(self.com, self.config, overrides, use_command_line_options) def newgrid(self): "Convenience method to construct a new grid using data from the :class:`Context`." return IceGrid(self.com, self.config) class AlgorithmFailureException(Exception): """Python exception wrapping a PISM :cpp:class:`TerminationReason`""" def __init__(self,reason): """:param reason: a :cpp:class:`TerminationReason`""" self._reason = reason def __str__(self): return self._reason.nested_description() def reason(self): return _reason def verbPrintf(verbosity,com,msg,*args): """Mimics PISM's :cpp:func:`verbPrintf` but does formatting on the python side.""" if len(args) > 0: msg = msg % args cpp._verbPrintf(verbosity,com,msg)