diff --git a/pyfms/__init__.py b/pyfms/__init__.py index 8f12b9d..82fe082 100644 --- a/pyfms/__init__.py +++ b/pyfms/__init__.py @@ -1,14 +1,14 @@ -from .py_data_override.py_data_override import pyDataOverride -from .py_diag_manager.pyfms_diag_manager import DiagManager +from .cfms import cFMS +from .py_data_override.py_data_override import data_override +from .py_diag_manager.py_diag_manager import diag_manager +from .pyfms import fms from .py_field_manager.py_field_manager import FieldTable -from .py_horiz_interp.py_horiz_interp import HorizInterp -from .py_mpp.py_mpp import pyFMS_mpp -from .py_mpp.py_mpp_domains import ( - pyDomain, - pyDomainData, - pyFMS_mpp_domains, - pyNestDomain, -) -from .pyfms import pyFMS +from .py_horiz_interp.py_horiz_interp import horiz_interp +from .py_mpp.py_mpp import mpp +from .py_mpp.py_mpp_domains import mpp_domains from .pyfms_utils import data_handling -from .pyfms_utils.grid_utils import GridUtils +from .pyfms_utils.grid_utils import grid_utils + + + +cFMS.init() diff --git a/pyfms/cfms.py b/pyfms/cfms.py new file mode 100644 index 0000000..be2b0a7 --- /dev/null +++ b/pyfms/cfms.py @@ -0,0 +1,34 @@ +import ctypes +import os +import pyfms + +class cFMS(): + + __libpath: str = os.path.dirname(__file__) + "/../cFMS/cLIBFMS/lib/libcFMS.so" + __lib: ctypes.CDLL = ctypes.CDLL(__libpath) + + @classmethod + def init(cls): + pyfms.data_override.setlib(cls.libpath, cls.lib) + pyfms.fms.setlib(cls.libpath, cls.lib) + pyfms.diag_manager.setlib(cls.libpath, cls.lib) + pyfms.grid_utils.setlib(cls.libpath, cls.lib) + pyfms.horiz_interp.setlib(cls.libpath, cls.lib) + pyfms.mpp.setlib(cls.libpath, cls.lib) + pyfms.mpp_domains.setlib(cls.libpath, cls.lib) + + @classmethod + def changelib(cls, libpath): + cls.__libpath = libpath + cls.__lib = ctypes.CDLL(cls.__libpath) + cls.init() + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath diff --git a/pyfms/py_data_override/py_data_override.py b/pyfms/py_data_override/py_data_override.py index 3ee7e1c..b8ec205 100644 --- a/pyfms/py_data_override/py_data_override.py +++ b/pyfms/py_data_override/py_data_override.py @@ -4,14 +4,31 @@ import numpy as np import numpy.typing as npt +import pyfms -class pyDataOverride: +class data_override: - def __init__(self, cFMS: ctypes.CDLL = None): - self.cfms = cFMS + __libpath: str = None + __lib: ctypes.CDLL = None + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath + + @classmethod def init( - self, + cls, atm_domain_id: int = None, ocn_domain_id: int = None, ice_domain_id: int = None, @@ -20,7 +37,7 @@ def init( mode: int = None, ): - _data_override_init = self.cfms.cFMS_data_override_init + _data_override_init = cls.lib.cFMS_data_override_init atm_domain_id_t = ctypes.c_int ocn_domain_id_t = ctypes.c_int @@ -67,8 +84,9 @@ def init( mode_c, ) + @classmethod def set_time( - self, + cls, year: int = None, month: int = None, day: int = None, @@ -78,7 +96,7 @@ def set_time( tick: int = None, ): - _data_override_set_time = self.cfms.cFMS_data_override_set_time + _data_override_set_time = cls.lib.cFMS_data_override_set_time year_t = ctypes.c_int month_t = ctypes.c_int @@ -114,15 +132,16 @@ def set_time( year_c, month_c, day_c, hour_c, minute_c, second_c, tick_c, err_msg_c ) + @classmethod def override_scalar( - self, + cls, gridname: str, fieldname: str, data_type: Any, data_index: int = None, ) -> np.float32 | np.float64: - _data_override_scalar = self.cfms.cFMS_data_override_0d_cdouble + _data_override_scalar = cls.lib.cFMS_data_override_0d_cdouble gridname_t = ctypes.c_char_p fieldname_t = ctypes.c_char_p data_t = ctypes.c_float if data_type is np.float32 else ctypes.c_double @@ -149,8 +168,9 @@ def override_scalar( # TODO: add check for override return data_c.value + @classmethod def override( - self, + cls, gridname: str, fieldname: str, data_shape: list[int], @@ -165,14 +185,14 @@ def override( if data_type is np.float32: if nshape == 2: - _data_override = self.cfms.cFMS_data_override_2d_cfloat + _data_override = cls.lib.cFMS_data_override_2d_cfloat if nshape == 3: - _data_override = self.cfms.cFMS_data_override_3d_cfloat + _data_override = cls.lib.cFMS_data_override_3d_cfloat elif data_type is np.float64: if nshape == 2: - _data_override = self.cfms.cFMS_data_override_2d_cdouble + _data_override = cls.lib.cFMS_data_override_2d_cdouble if nshape == 3: - _data_override = self.cfms.cFMS_data_override_3d_cdouble + _data_override = cls.lib.cFMS_data_override_3d_cdouble else: # add cFMS_end raise RuntimeError("Data_override, datatype not supported") diff --git a/pyfms/py_diag_manager/pyfms_diag_manager.py b/pyfms/py_diag_manager/py_diag_manager.py similarity index 83% rename from pyfms/py_diag_manager/pyfms_diag_manager.py rename to pyfms/py_diag_manager/py_diag_manager.py index 16449ac..c4fc158 100644 --- a/pyfms/py_diag_manager/pyfms_diag_manager.py +++ b/pyfms/py_diag_manager/py_diag_manager.py @@ -2,6 +2,7 @@ import numpy as np from numpy.typing import NDArray +from typing import Any from pyfms.pyfms_utils.data_handling import ( set_Cchar, @@ -15,29 +16,43 @@ ) -class DiagManager: +class diag_manager(): - # To be class var after refactor, accessed directly from cFMS - DIAG_ALL = 2 + __libpath: str = None + __lib: ctypes.CDLL = None - def __init__(self, clibFMS: ctypes.CDLL = None): - self.clibFMS = clibFMS + DIAG_ALL: int = None + DIAG_OCEAN: int = None + DIAG_OTHER: int = None + + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib - def end(self): - _cfms_diag_end = self.clibFMS.cFMS_diag_end + @classmethod + @property + def lib(cls): + return cls.__lib - _cfms_diag_end.restype = None - - _cfms_diag_end() + @classmethod + @property + def libpath(cls): + return cls.__libpath + @classmethod def init( - self, + cls, diag_model_subset: int = None, time_init: NDArray = None, ) -> str: err_msg = " " - _cfms_diag_init = self.clibFMS.cFMS_diag_init + cls.DIAG_OTHER = ctypes.c_int.in_dll(cls.lib, "DIAG_OTHER") + cls.DIAG_OCEAN = ctypes.c_int.in_dll(cls.lib, "DIAG_OCEAN") + cls.DIAG_ALL = ctypes.c_int.in_dll(cls.lib,"DIAG_ALL") + + _cfms_diag_init = cls.lib.cFMS_diag_init diag_model_subset_c, diag_model_subset_t = setscalar_Cint32(diag_model_subset) time_init_p, time_init_t = setarray_Cint32(time_init) @@ -54,14 +69,21 @@ def init( return err_msg_c.value.decode("utf-8") + @classmethod + def end(cls): + _cfms_diag_end = cls.lib.cFMS_diag_end + _cfms_diag_end.restype = None + _cfms_diag_end() + + @classmethod def send_complete( - self, + cls, diag_field_id: int, ) -> str: err_msg = " " - _cfms_diag_send_complete = self.clibFMS.cFMS_diag_send_complete + _cfms_diag_send_complete = cls.lib.cFMS_diag_send_complete diag_field_id_c, diag_field_id_t = setscalar_Cint32(diag_field_id) err_msg_c, err_msg_t = set_Cchar(err_msg) @@ -73,8 +95,9 @@ def send_complete( return err_msg_c.value.decode("utf-8") + @classmethod def set_field_init_time( - self, + cls, year: int, month: int, day: int, @@ -86,7 +109,7 @@ def set_field_init_time( err_msg = " " - _cfms_diag_set_field_init_time = self.clibFMS.cFMS_diag_set_field_init_time + _cfms_diag_set_field_init_time = cls.lib.cFMS_diag_set_field_init_time year_c, year_t = setscalar_Cint32(year) month_c, month_t = setscalar_Cint32(month) @@ -115,8 +138,9 @@ def set_field_init_time( return err_msg_c.value.decode("utf-8") + @classmethod def set_field_timestep( - self, + cls, diag_field_id: int, dseconds: int, ddays: int = None, @@ -125,7 +149,7 @@ def set_field_timestep( err_msg = " " - _cfms_diag_set_field_timestep = self.clibFMS.cFMS_diag_set_field_timestep + _cfms_diag_set_field_timestep = cls.lib.cFMS_diag_set_field_timestep diag_field_id_c, diag_field_id_t = setscalar_Cint32(diag_field_id) dseconds_c, dseconds_t = setscalar_Cint32(dseconds) @@ -148,11 +172,12 @@ def set_field_timestep( return err_msg_c.value.decode("utf-8") + @classmethod def advance_field_time( - self, + cls, diag_field_id: int, ): - _cfms_diag_advance_field_time = self.clibFMS.cFMS_diag_advance_field_time + _cfms_diag_advance_field_time = cls.lib.cFMS_diag_advance_field_time diag_field_id_c, diag_field_id_t = setscalar_Cint32(diag_field_id) @@ -161,8 +186,9 @@ def advance_field_time( _cfms_diag_advance_field_time(diag_field_id_c) + @classmethod def set_time_end( - self, + cls, year: int = None, month: int = None, day: int = None, @@ -175,7 +201,7 @@ def set_time_end( if err_msg is not None: err_msg = err_msg[:128] - _cfms_set_time_end = self.clibFMS.cFMS_diag_set_time_end + _cfms_set_time_end = cls.lib.cFMS_diag_set_time_end year_c, year_t = setscalar_Cint32(year) month_c, month_t = setscalar_Cint32(month) @@ -209,8 +235,9 @@ def set_time_end( err_msg_c, ) + @classmethod def axis_init( - self, + cls, name: str, axis_data: NDArray, units: str, @@ -244,10 +271,10 @@ def axis_init( not_xy_c, not_xy_t = setscalar_Cbool(not_xy) if axis_data.dtype == np.float64: - _cfms_diag_axis_init_ = self.clibFMS.cFMS_diag_axis_init_cdouble + _cfms_diag_axis_init_ = cls.lib.cFMS_diag_axis_init_cdouble axis_data_p, axis_data_t = setarray_Cdouble(axis_data) elif axis_data.dtype == np.float32: - _cfms_diag_axis_init_ = self.clibFMS.cFMS_diag_axis_init_cfloat + _cfms_diag_axis_init_ = cls.lib.cFMS_diag_axis_init_cfloat axis_data_p, axis_data_t = setarray_Cfloat(axis_data) else: raise RuntimeError("diag_axis_init datatype not supported") @@ -287,8 +314,9 @@ def axis_init( not_xy_c, ) + @classmethod def register_field_array( - self, + cls, module_name: str, field_name: str, datatype, @@ -296,7 +324,7 @@ def register_field_array( long_name: str = None, units: str = None, missing_value: int = None, - range_data: NDArray = None, + range_data: list[np.int32|np.int64|np.float32|np.float64] = None, mask_variant: bool = None, standard_name: str = None, verbose: bool = None, @@ -325,13 +353,14 @@ def register_field_array( realm = realm[:64] if axes is not None: - if len(axes) < 5: - for i in range(5 - len(axes)): - axes.append(0) - axes_arr = np.array(axes, dtype=np.int32) - else: - axes_arr = None - + axes_arr = axes + while len(axes_arr) < 5: + axes_arr.append(0) + axes_arr = np.array(axes_arr, dtype=np.int32) + + if range_data is not None: + range_data_arr = np.array(range_data, dtype=datatype) + module_name_c, module_name_t = set_Cchar(module_name) field_name_c, field_name_t = set_Cchar(field_name) axes_p, axes_t = setarray_Cint32(axes_arr) @@ -351,21 +380,21 @@ def register_field_array( if datatype == np.int32: _cfms_register_diag_field_array_ = ( - self.clibFMS.cFMS_register_diag_field_array_cint + cls.lib.cFMS_register_diag_field_array_cint ) - range_data_p, range_data_t = setarray_Cint32(range_data) + range_data_p, range_data_t = setarray_Cint32(range_data_arr) missing_value_c, missing_value_t = setscalar_Cint32(missing_value) elif datatype == np.float64: _cfms_register_diag_field_array_ = ( - self.clibFMS.cFMS_register_diag_field_array_cdouble + cls.lib.cFMS_register_diag_field_array_cdouble ) - range_data_p, range_data_t = setarray_Cdouble(range_data) + range_data_p, range_data_t = setarray_Cdouble(range_data_arr) missing_value_c, missing_value_t = setscalar_Cdouble(missing_value) elif datatype == np.float32: _cfms_register_diag_field_array_ = ( - self.clibFMS.cFMS_register_diag_field_array_cfloat + cls.lib.cFMS_register_diag_field_array_cfloat ) - range_data_p, range_data_t = setarray_Cfloat(range_data) + range_data_p, range_data_t = setarray_Cfloat(range_data_arr) missing_value_c, missing_value_t = setscalar_Cfloat(missing_value) else: raise RuntimeError( @@ -415,8 +444,9 @@ def register_field_array( multiple_send_data_c, ) + @classmethod def register_field_scalar( - self, + cls, module_name: str, field_name: str, datatype, @@ -459,19 +489,19 @@ def register_field_scalar( if datatype == np.int32: _cfms_register_diag_field_scalar_ = ( - self.clibFMS.cFMS_register_diag_field_array_cint + cls.lib.cFMS_register_diag_field_array_cint ) range_data_p, range_data_t = setarray_Cint32(range_data) missing_value_c, missing_value_t = setscalar_Cint32(missing_value) elif datatype == np.float64: _cfms_register_diag_field_scalar_ = ( - self.clibFMS.cFMS_register_diag_field_array_cdouble + cls.lib.cFMS_register_diag_field_array_cdouble ) range_data_p, range_data_t = setarray_Cdouble(range_data) missing_value_c, missing_value_t = setscalar_Cdouble(missing_value) elif datatype == np.float32: _cfms_register_diag_field_scalar_ = ( - self.clibFMS.cFMS_register_diag_field_array_cfloat + cls.lib.cFMS_register_diag_field_array_cfloat ) range_data_p, range_data_t = setarray_Cfloat(range_data) missing_value_c, missing_value_t = setscalar_Cfloat(missing_value) @@ -513,8 +543,9 @@ def register_field_scalar( multiple_send_data_c, ) + @classmethod def send_data( - self, + cls, diag_field_id: int, field_shape: list[int], field: NDArray, @@ -529,49 +560,49 @@ def send_data( if field_shape_arr.size == 2: if field.dtype == np.int32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_2d_cint + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_2d_cint field_p, field_t = setarray_Cint32(field) elif field.dtype == np.float64: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_2d_cdouble + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_2d_cdouble field_p, field_t = setarray_Cdouble(field) elif field.dtype == np.float32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_2d_cfloat + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_2d_cfloat field_p, field_t = setarray_Cfloat(field) else: raise RuntimeError(f"diag_send_data {field.dtype} unsupported") elif field_shape_arr.size == 3: if field.dtype == np.int32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_3d_cint + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_3d_cint field_p, field_t = setarray_Cint32(field) elif field.dtype == np.float64: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_3d_cdouble + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_3d_cdouble field_p, field_t = setarray_Cdouble(field) elif field.dtype == np.float32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_3d_cfloat + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_3d_cfloat field_p, field_t = setarray_Cfloat(field) else: raise RuntimeError(f"diag_send_data {field.dtype} unsupported") elif field_shape_arr.size == 4: if field.dtype == np.int32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_4d_cint + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_4d_cint field_p, field_t = setarray_Cint32(field) elif field.dtype == np.float64: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_4d_cdouble + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_4d_cdouble field_p, field_t = setarray_Cdouble(field) elif field.dtype == np.float32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_4d_cfloat + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_4d_cfloat field_p, field_t = setarray_Cfloat(field) else: raise RuntimeError(f"diag_send_data {field.dtype} unsupported") elif field_shape_arr.size == 5: if field.dtype == np.int32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_5d_cint + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_5d_cint field_p, field_t = setarray_Cint32(field) elif field.dtype == np.float64: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_5d_cdouble + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_5d_cdouble field_p, field_t = setarray_Cdouble(field) elif field.dtype == np.float32: - _cfms_diag_send_data_ = self.clibFMS.cFMS_diag_send_data_5d_cfloat + _cfms_diag_send_data_ = cls.lib.cFMS_diag_send_data_5d_cfloat field_p, field_t = setarray_Cfloat(field) else: raise RuntimeError(f"diag_send_data {field.dtype} unsupported") diff --git a/pyfms/py_horiz_interp/py_horiz_interp.py b/pyfms/py_horiz_interp/py_horiz_interp.py index 92caa2b..15865db 100644 --- a/pyfms/py_horiz_interp/py_horiz_interp.py +++ b/pyfms/py_horiz_interp/py_horiz_interp.py @@ -4,16 +4,56 @@ import numpy.typing as npt -class HorizInterp: - def __init__(self, cfms: ctypes.CDLL): - self.cfms = cfms +class horiz_interp(): - def get_maxxgrid(self) -> np.int32: - self.cfms.get_maxxgrid.restype = np.int32 - return self.cfms.get_maxxgrid() + __libpath: str = None + __lib: ctypes.CDLL = None + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath + + @classmethod + def init(cls, ninterp: int = None): + _cfms_horiz_interp_init = cls.lib.cFMS_horiz_interp_init + + ninterp_c, ninterp_t = ctypes.c_int(ninterp), ctypes.POINTER(ctypes.c_int) + + _cfms_horiz_interp_init.argtypes = [ninterp_t] + _cfms_horiz_interp_init.restype = None + + _cfms_horiz_interp_init(ctypes.byref(ninterp_c)) + + @classmethod + def set_current_interp(cls, interp_id: int = None): + _cfms_set_current_interp = cls.lib.cFMS_set_current_interp + + interp_id_c, interp_id_t = ctypes.c_int(interp_id), ctypes.POINTER(ctypes.c_int) + + _cfms_set_current_interp.argtypes = [interp_id_t] + _cfms_set_current_interp.restype = None + + _cfms_set_current_interp(ctypes.byref(interp_id_c)) + + @classmethod + def get_maxxgrid(cls) -> np.int32: + cls.lib.get_maxxgrid.restype = np.int32 + return cls.lib.get_maxxgrid() + + @classmethod def create_xgrid_2dx2d_order1( - self, + cls, nlon_src: int, nlat_src: int, nlon_tgt: int, @@ -31,7 +71,7 @@ def create_xgrid_2dx2d_order1( ngrid_src_p1 = (nlon_src + 1) * (nlat_src + 1) ngrid_tgt_p1 = (nlon_tgt + 1) * (nlat_tgt + 1) - maxxgrid = self.get_maxxgrid() + maxxgrid = cls.get_maxxgrid() nlon_src_t = ctypes.c_int nlat_src_t = ctypes.c_int @@ -75,7 +115,7 @@ def create_xgrid_2dx2d_order1( j_tgt = np.zeros(maxxgrid, dtype=np.int32) xarea = np.zeros(maxxgrid, dtype=np.float64) - _create_xgrid = self.cfms.cFMS_create_xgrid_2dx2d_order1 + _create_xgrid = cls.lib.cFMS_create_xgrid_2dx2d_order1 _create_xgrid.restype = ctypes.c_int _create_xgrid.argtypes = [ @@ -129,22 +169,3 @@ def create_xgrid_2dx2d_order1( "xarea": xarea[:nxgrid], } - def horiz_interp_init(self, ninterp: int = None): - _cfms_horiz_interp_init = self.cfms.cFMS_horiz_interp_init - - ninterp_c, ninterp_t = ctypes.c_int(ninterp), ctypes.POINTER(ctypes.c_int) - - _cfms_horiz_interp_init.argtypes = [ninterp_t] - _cfms_horiz_interp_init.restype = None - - _cfms_horiz_interp_init(ctypes.byref(ninterp_c)) - - def set_current_interp(self, interp_id: int = None): - _cfms_set_current_interp = self.cfms.cFMS_set_current_interp - - interp_id_c, interp_id_t = ctypes.c_int(interp_id), ctypes.POINTER(ctypes.c_int) - - _cfms_set_current_interp.argtypes = [interp_id_t] - _cfms_set_current_interp.restype = None - - _cfms_set_current_interp(ctypes.byref(interp_id_c)) diff --git a/pyfms/py_mpp/py_mpp.py b/pyfms/py_mpp/py_mpp.py index e02ee2e..3b220a8 100644 --- a/pyfms/py_mpp/py_mpp.py +++ b/pyfms/py_mpp/py_mpp.py @@ -12,14 +12,27 @@ ) -class pyFMS_mpp: - - def __init__(self, cFMS: ctypes.CDLL = None): - self.cFMS = cFMS +class mpp(): + + __libpath: str = None + __lib: ctypes.CDLL = None + + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath """ - Subroutine: declare_pelist - This method is written specifically to accommodate a MPI restriction that requires a parent communicator to create a child communicator. In other words: a pelist cannot go off and declare a communicator, @@ -37,26 +50,28 @@ def __init__(self, cFMS: ctypes.CDLL = None): set to the result of the call """ + @classmethod def declare_pelist( - self, - pelist: NDArray, - name: Optional[str] = None, - commID: Optional[int] = None, - ) -> int | None: - _cfms_declare_pelist = self.cFMS.cFMS_declare_pelist + cls, + pelist: list[int], + name: str = None, + ) -> int: - pelist_p, pelist_t = setarray_Cint32(pelist) + _cfms_declare_pelist = cls.lib.cFMS_declare_pelist + + commID = 0 + + pelist_p = np.array(pelist, dtype=np.int32) + pelist_t = np.ctypeslib.ndpointer(dtype=np.int32, shape=(pelist_p.shape)) name_c, name_t = set_Cchar(name) commID_c, commID_t = setscalar_Cint32(commID) _cfms_declare_pelist.argtypes = [pelist_t, name_t, commID_t] _cfms_declare_pelist.restype = None - + _cfms_declare_pelist(pelist_p, name_c, commID_c) - if commID is not None: - commID = commID_c.value - return commID + return commID_c.value """ Subroutine: pyfms_error @@ -66,12 +81,13 @@ def declare_pelist( Returns: No return """ - def pyfms_error(self, errortype: int, errormsg: Optional[str] = None): + @classmethod + def error(cls, errortype: int, errormsg: str = None): # truncating string if errormsg is not None: errormsg = errormsg[:128] - _cfms_error = self.cFMS.cFMS_error + _cfms_error = cls.lib.cFMS_error errortype_c, errortype_t = setscalar_Cint32(errortype) errormsg_c, errormsg_t = set_Cchar(errormsg) @@ -92,16 +108,22 @@ def pyfms_error(self, errortype: int, errormsg: Optional[str] = None): Returns: NDArray containing pelist """ + @classmethod def get_current_pelist( - self, - name: Optional[str] = None, - commID: Optional[int] = None, - ) -> NDArray: + cls, + get_name: str = None, + get_commID: bool = False, + ) -> (NDArray, Optional[int], Optional[str]): - npes = ctypes.c_int.in_dll(self.cFMS, "cFMS_pelist_npes") - pelist = np.empty(shape=npes.value, dtype=np.int32, order="C") + commID = 0 if get_commID else None + name = None + #if get_name: name="NAME" - _cfms_get_current_pelist = self.cFMS.cFMS_get_current_pelist + + npes = ctypes.c_int.in_dll(cls.lib, "cFMS_pelist_npes") + pelist = np.empty(shape=npes.value, dtype=np.int32) + + _cfms_get_current_pelist = cls.lib.cFMS_get_current_pelist pelist_p, pelist_t = setarray_Cint32(pelist) name_c, name_t = set_Cchar(name) @@ -119,16 +141,18 @@ def get_current_pelist( # return commID, name - return pelist - + if get_commID: return pelist.tolist(), commID_c.value + else: return pelist.tolist() + """ Function: npes Returns: number of pes in use """ - def npes(self) -> int: - _cfms_npes = self.cFMS.cFMS_npes + @classmethod + def npes(cls) -> int: + _cfms_npes = cls.lib.cFMS_npes _cfms_npes.restype = ctypes.c_int32 @@ -140,8 +164,9 @@ def npes(self) -> int: Returns: pe number of calling pe """ - def pe(self) -> int: - _cfms_pe = self.cFMS.cFMS_pe + @classmethod + def pe(cls) -> int: + _cfms_pe = cls.lib.cFMS_pe _cfms_pe.restype = ctypes.c_int32 @@ -158,15 +183,40 @@ def pe(self) -> int: Returns: No return """ + @classmethod def set_current_pelist( - self, pelist: Optional[NDArray] = None, no_sync: Optional[bool] = None + cls, pelist: list[int] = None, no_sync: bool = None ): - _cfms_set_current_pelist = self.cFMS.cFMS_set_current_pelist - - pelist_p, pelist_t = setarray_Cint32(pelist) + _cfms_set_current_pelist = cls.lib.cFMS_set_current_pelist + + if pelist is not None: + pelist_p = np.array(pelist, dtype=np.int32) + pelist_t = np.ctypeslib.ndpointer(dtype=np.int32, shape=pelist_p.shape) + else: + pelist_p = None + pelist_t = ctypes.POINTER(ctypes.c_int) no_sync_c, no_sync_t = setscalar_Cbool(no_sync) _cfms_set_current_pelist.argtypes = [pelist_t, no_sync_t] _cfms_set_current_pelist.restype = None _cfms_set_current_pelist(pelist_p, no_sync_c) + + + """ + Subroutine: pyfms_set_pelist_npes + + This method is used to set a npes variable of the cFMS module it wraps + """ + + @classmethod + def set_pelist_npes(cls, npes_in: int): + _cfms_set_npes = cls.lib.cFMS_set_pelist_npes + + npes_in_c, npes_in_t = setscalar_Cint32(npes_in) + + _cfms_set_npes.argtypes = [npes_in_t] + _cfms_set_npes.restype = None + + _cfms_set_npes(npes_in_c) + diff --git a/pyfms/py_mpp/py_mpp_domains.py b/pyfms/py_mpp/py_mpp_domains.py index dbf7ae3..22a3049 100644 --- a/pyfms/py_mpp/py_mpp_domains.py +++ b/pyfms/py_mpp/py_mpp_domains.py @@ -13,37 +13,73 @@ ) -class pyDomainData: - def __init__( - self, - xbegin=0, - xend=0, - ybegin=0, - yend=0, - xsize=0, - xmax_size=0, - ysize=0, - ymax_size=0, - x_is_global=False, - y_is_global=False, - tile_count=0, - ): - self.xbegin = ctypes.c_int(xbegin) - self.xend = ctypes.c_int(xend) - self.ybegin = ctypes.c_int(ybegin) - self.yend = ctypes.c_int(yend) - self.xsize = ctypes.c_int(xsize) - self.xmax_size = ctypes.c_int(xmax_size) - self.ysize = ctypes.c_int(ysize) - self.ymax_size = ctypes.c_int(ymax_size) - self.x_is_global = ctypes.c_bool(x_is_global) - self.y_is_global = ctypes.c_bool(y_is_global) - self.tile_count = ctypes.c_int(tile_count) - - -class pyFMS_mpp_domains: - def __init__(self, cFMS: ctypes.CDLL = None): - self.cFMS = cFMS +class mpp_domains: + + GLOBAL_DATA_DOMAIN: int = None + BGRID_NE: int = None + CGRID_NE: int = None + DGRID_NE: int = None + AGRID: int = None + FOLD_SOUTH_EDGE: int = None + FOLD_WEST_EDGE: int = None + FOLD_EAST_EDGE: int = None + CYCLIC_GLOBAL_DOMAIN: int = None + NUPDATE: int = None + EUPDATE: int = None + XUPDATE: int = None + YUPDATE: int = None + NORTH: int = None + NORTH_EAST: int = None + EAST: int = None + SOUTH_EAST: int = None + CORNER: int = None + CENTER: int = None + SOUTH: int = None + SOUTH_WEST: int = None + + __libpath: str = None + __lib: ctypes.CDLL = None + + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath + + @classmethod + def init(cls): + cls.GLOBAL_DATA_DOMAIN = ctypes.c_int.in_dll(cls.lib, "GLOBAL_DATA_DOMAIN") + cls.BGRID_NE = ctypes.c_int.in_dll(cls.lib, "BGRID_NE") + cls.CGRID_NE = ctypes.c_int.in_dll(cls.lib, "CGRID_NE") + cls.DGRID_NE = ctypes.c_int.in_dll(cls.lib, "DGRID_NE") + cls.AGRID = ctypes.c_int.in_dll(cls.lib, "AGRID") + cls.FOLD_SOUTH_EDGE = ctypes.c_int.in_dll(cls.lib, "FOLD_SOUTH_EDGE") + cls.FOLD_WEST_EDGE = ctypes.c_int.in_dll(cls.lib, "FOLD_WEST_EDGE") + cls.FOLD_EAST_EDGE = ctypes.c_int.in_dll(cls.lib, "FOLD_EAST_EDGE") + cls.CYCLIC_GLOBAL_DOMAIN = ctypes.c_int.in_dll(cls.lib, "CYCLIC_GLOBAL_DOMAIN") + cls.NUPDATE = ctypes.c_int.in_dll(cls.lib, "NUPDATE") + cls.EUPDATE = ctypes.c_int.in_dll(cls.lib, "EUPDATE") + cls.XUPDATE = ctypes.c_int.in_dll(cls.lib, "XUPDATE") + cls.YUPDATE = ctypes.c_int.in_dll(cls.lib, "YUPDATE") + cls.NORTH = ctypes.c_int.in_dll(cls.lib, "NORTH") + cls.NORTH_EAST = ctypes.c_int.in_dll(cls.lib, "NORTH_EAST") + cls.EAST = ctypes.c_int.in_dll(cls.lib, "EAST") + cls.SOUTH_EAST = ctypes.c_int.in_dll(cls.lib, "SOUTH_EAST") + cls.CORNER = ctypes.c_int.in_dll(cls.lib, "CORNER") + cls.CENTER = ctypes.c_int.in_dll(cls.lib, "CENTER") + cls.SOUTH = ctypes.c_int.in_dll(cls.lib, "SOUTH") + cls.SOUTH_WEST = ctypes.c_int.in_dll(cls.lib, "SOUTH_WEST") + cls.WEST = ctypes.c_int.in_dll(cls.lib, "WEST") + cls.NORTH_WEST = ctypes.c_int.in_dll(cls.lib, "NORTH_WEST") """ Subroutine: define_domains @@ -57,53 +93,59 @@ def __init__(self, cFMS: ctypes.CDLL = None): to the result of the method to update their values. """ + @classmethod def define_domains( - self, + cls, global_indices: list[int], layout: list[int], - domain_id: Optional[int] = None, - pelist: Optional[NDArray] = None, - xflags: Optional[int] = None, - yflags: Optional[int] = None, - xhalo: Optional[int] = None, - yhalo: Optional[int] = None, - xextent: Optional[NDArray] = None, - yextent: Optional[NDArray] = None, - maskmap: Optional[NDArray[np.bool_]] = None, - name: Optional[str] = None, - symmetry: Optional[bool] = None, - memory_size: Optional[NDArray] = None, - whalo: Optional[int] = None, - ehalo: Optional[int] = None, - shalo: Optional[int] = None, - nhalo: Optional[int] = None, - is_mosaic: Optional[bool] = None, - tile_count: Optional[int] = None, - tile_id: Optional[int] = None, - complete: Optional[bool] = None, - x_cyclic_offset: Optional[int] = None, - y_cyclic_offset: Optional[int] = None, + domain_id: int = None, + pelist: list[int] = None, + xflags: int = None, + yflags: int = None, + xhalo: int = None, + yhalo: int = None, + xextent: list[int] = None, + yextent: list[int] = None, + maskmap: list[list[np.bool_]] = None, + name: str = None, + symmetry: bool = None, + memory_size: list[int] = None, + whalo: int = None, + ehalo: int = None, + shalo: int = None, + nhalo: int = None, + is_mosaic: bool = None, + tile_count: int = None, + tile_id: int = None, + complete: bool = None, + x_cyclic_offset: int = None, + y_cyclic_offset: int = None, ): - _cfms_define_domains = self.cFMS.cFMS_define_domains + _cfms_define_domains = cls.lib.cFMS_define_domains global_indices_arr = np.array(global_indices, dtype=np.int32) layout_arr = np.array(layout, dtype=np.int32) - + pelist_arr = np.array(pelist, dtype=np.int32) if pelist is not None else None + xextent_arr = np.array(xextent, dtype=np.int32) if xextent is not None else None + yextent_arr = np.array(yextent, dtype=np.int32) if yextent is not None else None + maskmap_arr = np.array(maskmap, dtype=np.bool_) if maskmap is not None else None + memory_size_arr = np.array(memory_size, dtype=np.int32) if memory_size is not None else None + global_indices_p, global_indices_t = setarray_Cint32(global_indices_arr) layout_p, layout_t = setarray_Cint32(layout_arr) domain_id_c, domain_id_t = setscalar_Cint32(domain_id) - pelist_p, pelist_t = setarray_Cint32(pelist) + pelist_p, pelist_t = setarray_Cint32(pelist_arr) xflags_c, xflags_t = setscalar_Cint32(xflags) yflags_c, yflags_t = setscalar_Cint32(yflags) xhalo_c, xhalo_t = setscalar_Cint32(xhalo) yhalo_c, yhalo_t = setscalar_Cint32(yhalo) - xextent_p, xextent_t = setarray_Cint32(xextent) - yextent_p, yextent_t = setarray_Cint32(yextent) - maskmap_p, maskmap_t = setarray_Cbool(maskmap) + xextent_p, xextent_t = setarray_Cint32(xextent_arr) + yextent_p, yextent_t = setarray_Cint32(yextent_arr) + maskmap_p, maskmap_t = setarray_Cbool(maskmap_arr) name_c, name_t = set_Cchar(name) symmetry_c, symmetry_t = setscalar_Cbool(symmetry) - memory_size_p, memory_size_t = setarray_Cint32(memory_size) + memory_size_p, memory_size_t = setarray_Cint32(memory_size_arr) whalo_c, whalo_t = setscalar_Cint32(whalo) ehalo_c, ehalo_t = setscalar_Cint32(ehalo) shalo_c, shalo_t = setscalar_Cint32(shalo) @@ -114,7 +156,7 @@ def define_domains( complete_c, complete_t = setscalar_Cbool(complete) x_cyclic_offset_c, x_cyclic_offset_t = setscalar_Cint32(x_cyclic_offset) y_cyclic_offset_c, y_cyclic_offset_t = setscalar_Cint32(y_cyclic_offset) - + _cfms_define_domains.argtypes = [ global_indices_t, layout_t, @@ -171,6 +213,10 @@ def define_domains( y_cyclic_offset_c, ) + return pyDomain(domain_id=domain_id, + layout=layout, + tile=tile_id) + """ Subroutine: define_io_domains @@ -179,8 +225,9 @@ def define_domains( Returns: No return """ - def define_io_domain(self, io_layout: list[int], domain_id: Optional[int] = None): - _cfms_define_io_domain = self.cFMS.cFMS_define_io_domain + @classmethod + def define_io_domain(cls, io_layout: list[int], domain_id: int = None): + _cfms_define_io_domain = cls.lib.cFMS_define_io_domain io_layout_arr = np.array(io_layout, dtype=np.int32) @@ -200,8 +247,9 @@ def define_io_domain(self, io_layout: list[int], domain_id: Optional[int] = None Returns: A NDArray containing the layout """ + @classmethod def define_layout( - self, + cls, global_indices: list[int], ndivs: int, ) -> list: @@ -210,7 +258,7 @@ def define_layout( global_indices_arr = np.array(global_indices, dtype=np.int32) - _cfms_define_layout = self.cFMS.cFMS_define_layout + _cfms_define_layout = cls.lib.cFMS_define_layout global_indices_p, global_indices_t = setarray_Cint32(global_indices_arr) ndivs_c, ndivs_t = setscalar_Cint32(ndivs) @@ -231,39 +279,51 @@ def define_layout( Returns: No return """ + @classmethod def define_nest_domains( - self, + cls, num_nest: int, ntiles: int, - nest_level: NDArray, - tile_fine: NDArray, - tile_coarse: NDArray, - istart_coarse: NDArray, - icount_coarse: NDArray, - jstart_coarse: NDArray, - jcount_coarse: NDArray, - npes_nest_tile: NDArray, - x_refine: NDArray, - y_refine: NDArray, - nest_domain_id: Optional[int] = None, - domain_id: Optional[int] = None, - extra_halo: Optional[int] = None, - name: Optional[str] = None, + nest_level: list[int], + tile_fine: list[int], + tile_coarse: list[int], + istart_coarse: list[int], + icount_coarse: list[int], + jstart_coarse: list[int], + jcount_coarse: list[int], + npes_nest_tile: list[int], + x_refine: list[int], + y_refine: list[int], + nest_domain_id: int = None, + domain_id: int = None, + extra_halo: int = None, + name: str = None, ): - _cfms_define_nest_domain = self.cFMS.cFMS_define_nest_domains - + _cfms_define_nest_domain = cls.lib.cFMS_define_nest_domains + + nest_level_arr = np.array(nest_level, dtype=np.int32) + tile_fine_arr = np.array(tile_fine, dtype=np.int32) + tile_coarse_arr = np.array(tile_coarse, dtype=np.int32) + istart_coarse_arr = np.array(istart_coarse, dtype=np.int32) + jstart_coarse_arr = np.array(jstart_coarse, dtype=np.int32) + icount_coarse_arr = np.array(icount_coarse, dtype=np.int32) + jcount_coarse_arr = np.array(jcount_coarse, dtype=np.int32) + npes_nest_tile_arr = np.array(npes_nest_tile, dtype=np.int32) + x_refine_arr = np.array(x_refine, dtype=np.int32) + y_refine_arr = np.array(y_refine, dtype=np.int32) + num_nest_p, num_nest_t = setscalar_Cint32(num_nest) ntiles_c, ntiles_t = setscalar_Cint32(ntiles) - nest_level_p, nest_level_t = setarray_Cint32(nest_level) - tile_fine_p, tile_fine_t = setarray_Cint32(tile_fine) - tile_coarse_p, tile_coarse_t = setarray_Cint32(tile_coarse) - istart_coarse_p, istart_coarse_t = setarray_Cint32(istart_coarse) - icount_coarse_p, icount_coarse_t = setarray_Cint32(icount_coarse) - jstart_coarse_p, jstart_coarse_t = setarray_Cint32(jstart_coarse) - jcount_coarse_p, jcount_coarse_t = setarray_Cint32(jcount_coarse) - npes_nest_tile_p, npes_nest_tile_t = setarray_Cint32(npes_nest_tile) - x_refine_p, x_refine_t = setarray_Cint32(x_refine) - y_refine_p, y_refine_t = setarray_Cint32(y_refine) + nest_level_p, nest_level_t = setarray_Cint32(nest_level_arr) + tile_fine_p, tile_fine_t = setarray_Cint32(tile_fine_arr) + tile_coarse_p, tile_coarse_t = setarray_Cint32(tile_coarse_arr) + istart_coarse_p, istart_coarse_t = setarray_Cint32(istart_coarse_arr) + icount_coarse_p, icount_coarse_t = setarray_Cint32(icount_coarse_arr) + jstart_coarse_p, jstart_coarse_t = setarray_Cint32(jstart_coarse_arr) + jcount_coarse_p, jcount_coarse_t = setarray_Cint32(jcount_coarse_arr) + npes_nest_tile_p, npes_nest_tile_t = setarray_Cint32(npes_nest_tile_arr) + x_refine_p, x_refine_t = setarray_Cint32(x_refine_arr) + y_refine_p, y_refine_t = setarray_Cint32(y_refine_arr) nest_domain_id_c, nest_domain_id_t = setscalar_Cint32(nest_domain_id) domain_id_c, domain_id_t = setscalar_Cint32(domain_id) extra_halo_c, extra_halo_t = setscalar_Cint32(extra_halo) @@ -317,8 +377,9 @@ def define_nest_domains( Returns: Boolean """ - def domain_is_initialized(self, domain_id: Optional[int] = None) -> bool: - _cfms_domain_is_initialized = self.cFMS.cFMS_domain_is_initialized + @classmethod + def domain_is_initialized(cls, domain_id: int = None) -> bool: + _cfms_domain_is_initialized = cls.lib.cFMS_domain_is_initialized domain_id_c, domain_id_t = setscalar_Cint32(domain_id) @@ -341,80 +402,17 @@ def domain_is_initialized(self, domain_id: Optional[int] = None) -> bool: which were passed, overwriting the passed value. """ + @classmethod def get_compute_domain( - self, - domain_data: pyDomainData, - domain_id: Optional[int] = None, - position: Optional[int] = None, - whalo: Optional[int] = None, - shalo: Optional[int] = None, + cls, + domain_id: int = None, + position: int = None, + tile_count: int = None, + whalo: int = None, + shalo: int = None, ): - _cfms_get_compute_domain = self.cFMS.cFMS_get_compute_domain - - domain_id_c, domain_id_t = setscalar_Cint32(domain_id) - xbegin_c, xbegin_t = setscalar_Cint32(domain_data.xbegin) - xend_c, xend_t = setscalar_Cint32(domain_data.xend) - ybegin_c, ybegin_t = setscalar_Cint32(domain_data.ybegin) - yend_c, yend_t = setscalar_Cint32(domain_data.yend) - xsize_c, xsize_t = setscalar_Cint32(domain_data.xsize) - xmax_size_c, xmax_size_t = setscalar_Cint32(domain_data.xmax_size) - ysize_c, ysize_t = setscalar_Cint32(domain_data.ysize) - ymax_size_c, ymax_size_t = setscalar_Cint32(domain_data.ymax_size) - x_is_global_c, x_is_global_t = setscalar_Cbool(domain_data.x_is_global) - y_is_global_c, y_is_global_t = setscalar_Cbool(domain_data.y_is_global) - tile_count_c, tile_count_t = setscalar_Cint32(domain_data.tile_count) - position_c, position_t = setscalar_Cint32(position) - whalo_c, whalo_t = setscalar_Cint32(whalo) - shalo_c, shalo_t = setscalar_Cint32(shalo) - - _cfms_get_compute_domain.argtypes = [ - domain_id_t, - xbegin_t, - xend_t, - ybegin_t, - yend_t, - xsize_t, - xmax_size_t, - ysize_t, - ymax_size_t, - x_is_global_t, - y_is_global_t, - tile_count_t, - position_t, - whalo_t, - shalo_t, - ] - _cfms_get_compute_domain.restype = None - - _cfms_get_compute_domain( - domain_id_c, - xbegin_c, - xend_c, - ybegin_c, - yend_c, - xsize_c, - xmax_size_c, - ysize_c, - ymax_size_c, - x_is_global_c, - y_is_global_c, - tile_count_c, - position_c, - whalo_c, - shalo_c, - ) - - def get_compute_domain2( - self, - domain_id: int | None = None, - position: int | None = None, - tile_count: int | None = None, - whalo: int | None = None, - shalo: int | None = None, - ): - - _cfms_get_compute_domain = self.cFMS.cFMS_get_compute_domain + _cfms_get_compute_domain = cls.lib.cFMS_get_compute_domain default_i = 0 default_b = False @@ -447,7 +445,7 @@ def get_compute_domain2( y_is_global_c = y_is_global_t(default_b) domain_id_c = domain_id_t(domain_id) if domain_id is not None else None tile_count_c = tile_count_t(tile_count) if tile_count is not None else None - position_c = position_t(position) if tile_count is not None else None + position_c = position_t(position) if position is not None else None whalo_c = whalo_t(whalo) if whalo is not None else None shalo_c = shalo_t(shalo) if shalo is not None else None @@ -517,49 +515,70 @@ def get_compute_domain2( which were passed, overwriting the passed value. """ + @classmethod def get_data_domain( - self, - domain_data: pyDomainData, - domain_id: Optional[int] = None, - position: Optional[int] = None, - whalo: Optional[int] = None, - shalo: Optional[int] = None, + cls, + domain_id: int = None, + position: int = None, + tile_count: int = None, + whalo: int = None, + shalo: int = None, ): - _cfms_get_data_domain = self.cFMS.cFMS_get_data_domain + _cfms_get_data_domain = cls.lib.cFMS_get_data_domain - domain_id_c, domain_id_t = setscalar_Cint32(domain_id) - xbegin_c, xbegin_t = setscalar_Cint32(domain_data.xbegin) - xend_c, xend_t = setscalar_Cint32(domain_data.xend) - ybegin_c, ybegin_t = setscalar_Cint32(domain_data.ybegin) - yend_c, yend_t = setscalar_Cint32(domain_data.yend) - xsize_c, xsize_t = setscalar_Cint32(domain_data.xsize) - xmax_size_c, xmax_size_t = setscalar_Cint32(domain_data.xmax_size) - ysize_c, ysize_t = setscalar_Cint32(domain_data.ysize) - ymax_size_c, ymax_size_t = setscalar_Cint32(domain_data.ymax_size) - x_is_global_c, x_is_global_t = setscalar_Cbool(domain_data.x_is_global) - y_is_global_c, y_is_global_t = setscalar_Cbool(domain_data.y_is_global) - tile_count_c, tile_count_t = setscalar_Cint32(domain_data.tile_count) - position_c, position_t = setscalar_Cint32(position) - whalo_c, whalo_t = setscalar_Cint32(whalo) - shalo_c, shalo_t = setscalar_Cint32(shalo) + default_i = 0 + default_b = False + + domain_id_t = ctypes.c_int + xbegin_t = ctypes.c_int + xend_t = ctypes.c_int + ybegin_t = ctypes.c_int + yend_t = ctypes.c_int + xsize_t = ctypes.c_int + xmax_size_t = ctypes.c_int + ysize_t = ctypes.c_int + ymax_size_t = ctypes.c_int + x_is_global_t = ctypes.c_bool + y_is_global_t = ctypes.c_bool + tile_count_t = ctypes.c_int + position_t = ctypes.c_int + whalo_t = ctypes.c_int + shalo_t = ctypes.c_int + + xbegin_c = xbegin_t(default_i) + xend_c = xend_t(default_i) + ybegin_c = ybegin_t(default_i) + yend_c = yend_t(default_i) + xsize_c = xsize_t(default_i) + xmax_size_c = xmax_size_t(default_i) + ysize_c = ysize_t(default_i) + ymax_size_c = ymax_size_t(default_i) + x_is_global_c = x_is_global_t(default_b) + y_is_global_c = y_is_global_t(default_b) + domain_id_c = domain_id_t(domain_id) if domain_id is not None else None + tile_count_c = tile_count_t(tile_count) if tile_count is not None else None + position_c = position_t(position) if position is not None else None + whalo_c = whalo_t(whalo) if whalo is not None else None + shalo_c = shalo_t(shalo) if shalo is not None else None _cfms_get_data_domain.argtypes = [ - domain_id_t, - xbegin_t, - xend_t, - ybegin_t, - yend_t, - xsize_t, - xmax_size_t, - ysize_t, - ymax_size_t, - x_is_global_t, - y_is_global_t, - tile_count_t, - position_t, - whalo_t, - shalo_t, + ctypes.POINTER(domain_id_t), + ctypes.POINTER(xbegin_t), + ctypes.POINTER(xend_t), + ctypes.POINTER(ybegin_t), + ctypes.POINTER(yend_t), + ctypes.POINTER(xsize_t), + ctypes.POINTER(xmax_size_t), + ctypes.POINTER(ysize_t), + ctypes.POINTER(ymax_size_t), + ctypes.POINTER(x_is_global_t), + ctypes.POINTER(y_is_global_t), + ctypes.POINTER(tile_count_t), + ctypes.POINTER(position_t), + ctypes.POINTER(whalo_t), + ctypes.POINTER(shalo_t), ] + _cfms_get_data_domain.restype = None _cfms_get_data_domain( @@ -580,6 +599,20 @@ def get_data_domain( shalo_c, ) + return dict( + domain_id=domain_id_c.value, + xbegin=xbegin_c.value, + ybegin=ybegin_c.value, + xend=xend_c.value, + yend=yend_c.value, + xsize=xsize_c.value, + ysize=ysize_c.value, + xmax_size=xmax_size_c.value, + ymax_size=ymax_size_c.value, + x_is_global=x_is_global_c.value, + y_is_global=y_is_global_c.value, + ) + """ Subroutine: get_domain_name @@ -591,8 +624,9 @@ def get_data_domain( its value as well. """ - def get_domain_name(self, domain_id: Optional[int] = None) -> str: - _cfms_get_domain_name = self.cFMS.cFMS_get_domain_name + @classmethod + def get_domain_name(cls, domain_id: int = None) -> str: + _cfms_get_domain_name = cls.lib.cFMS_get_domain_name domain_name = "" @@ -614,11 +648,12 @@ def get_domain_name(self, domain_id: Optional[int] = None) -> str: Returns: NDArray with layout info """ - def get_layout(self, domain_id: Optional[int] = None) -> NDArray: + @classmethod + def get_layout(cls, domain_id: int = None) -> list[int]: layout = np.empty(shape=2, dtype=np.int32, order="C") - _cfms_get_layout = self.cFMS.cFMS_get_layout + _cfms_get_layout = cls.lib.cFMS_get_layout layout_p, layout_t = setarray_Cint32(layout) domain_id_c, domain_id_t = setscalar_Cint32(domain_id) @@ -628,7 +663,7 @@ def get_layout(self, domain_id: Optional[int] = None) -> NDArray: _cfms_get_layout(layout_p, domain_id_c) - return layout + return layout_p.tolist() """ Subroutine: get_domain_pelist @@ -636,12 +671,13 @@ def get_layout(self, domain_id: Optional[int] = None) -> NDArray: Returns: NDArray containing pelist """ - def get_domain_pelist(self, domain_id: Optional[int]) -> NDArray: + @classmethod + def get_domain_pelist(cls, domain_id: Optional[int]) -> NDArray: - npes = ctypes.c_int.in_dll(self.cFMS, "cFMS_pelist_npes") + npes = ctypes.c_int.in_dll(cls.lib, "cFMS_pelist_npes") pelist = np.empty(shape=npes.value, dtype=np.int32, order="C") - _cfms_get_domain_pelist = self.cFMS.cFMS_get_domain_pelist + _cfms_get_domain_pelist = cls.lib.cFMS_get_domain_pelist pelist_p, pelist_t = setarray_Cint32(pelist) domain_id_c, domain_id_t = setscalar_Cint32(domain_id) @@ -651,7 +687,7 @@ def get_domain_pelist(self, domain_id: Optional[int]) -> NDArray: _cfms_get_domain_pelist(pelist_p, domain_id_c) - return pelist + return pelist_p """ Subroutine: set_compute_domain @@ -670,8 +706,9 @@ def get_domain_pelist(self, domain_id: Optional[int]) -> NDArray: which were passed, overwriting the passed value. """ + @classmethod def set_compute_domain( - self, + cls, xbegin: Optional[int] = None, xend: Optional[int] = None, ybegin: Optional[int] = None, @@ -685,7 +722,7 @@ def set_compute_domain( whalo: Optional[int] = None, shalo: Optional[int] = None, ): - _cfms_set_compute_domain = self.cFMS.cFMS_set_compute_domain + _cfms_set_compute_domain = cls.lib.cFMS_set_compute_domain domain_id_c, domain_id_t = setscalar_Cint32(domain_id) xbegin_c, xbegin_t = setscalar_Cint32(xbegin) @@ -738,8 +775,9 @@ def set_compute_domain( to domain_id """ - def set_current_domain(self, domain_id: Optional[int] = None): - _cfms_set_current_domain = self.cFMS.cFMS_set_current_domain + @classmethod + def set_current_domain(cls, domain_id: Optional[int] = None): + _cfms_set_current_domain = cls.lib.cFMS_set_current_domain domain_id_c, domain_id_t = setscalar_Cint32(domain_id) @@ -755,8 +793,9 @@ def set_current_domain(self, domain_id: Optional[int] = None): to nest_domain_id """ - def set_current_nest_domain(self, nest_domain_id: Optional[int] = None): - _cfms_set_current_nest_domain = self.cFMS.cFMS_set_current_nest_domain + @classmethod + def set_current_nest_domain(cls, nest_domain_id: Optional[int] = None): + _cfms_set_current_nest_domain = cls.lib.cFMS_set_current_nest_domain nest_domain_id_c, nest_domain_id_t = setscalar_Cint32(nest_domain_id) @@ -778,8 +817,9 @@ def set_current_nest_domain(self, nest_domain_id: Optional[int] = None): which were passed, overwriting the passed value. """ + @classmethod def set_data_domain( - self, + cls, xbegin: Optional[int] = None, xend: Optional[int] = None, ybegin: Optional[int] = None, @@ -793,7 +833,7 @@ def set_data_domain( whalo: Optional[int] = None, shalo: Optional[int] = None, ): - _cfms_set_data_domain = self.cFMS.cFMS_set_data_domain + _cfms_set_data_domain = cls.lib.cFMS_set_data_domain domain_id_c, domain_id_t = setscalar_Cint32(domain_id) xbegin_c, xbegin_t = setscalar_Cint32(xbegin) @@ -856,8 +896,9 @@ def set_data_domain( which were passed, overwriting the passed value. """ + @classmethod def set_global_domain( - self, + cls, xbegin: Optional[int] = None, xend: Optional[int] = None, ybegin: Optional[int] = None, @@ -869,7 +910,7 @@ def set_global_domain( whalo: Optional[int] = None, shalo: Optional[int] = None, ): - _cfms_set_global_domain = self.cFMS.cFMS_set_global_domain + _cfms_set_global_domain = cls.lib.cFMS_set_global_domain domain_id_c, domain_id_t = setscalar_Cint32(domain_id) xbegin_c, xbegin_t = setscalar_Cint32(xbegin) @@ -910,257 +951,59 @@ def set_global_domain( ) -class pyDomain: - def __init__( - self, - mpp_domains_obj: pyFMS_mpp_domains, - global_indices: list[int], - layout: list[int], - domain_id: Optional[int] = None, - pelist: Optional[NDArray] = None, - xflags: Optional[int] = None, - yflags: Optional[int] = None, - xhalo: Optional[int] = None, - yhalo: Optional[int] = None, - xextent: Optional[NDArray] = None, - yextent: Optional[NDArray] = None, - maskmap: Optional[NDArray[np.bool_]] = None, - name: Optional[str] = None, - symmetry: Optional[bool] = None, - memory_size: Optional[NDArray] = None, - whalo: Optional[int] = None, - ehalo: Optional[int] = None, - shalo: Optional[int] = None, - nhalo: Optional[int] = None, - is_mosaic: Optional[bool] = None, - tile_count: Optional[int] = None, - tile_id: Optional[int] = None, - complete: Optional[bool] = None, - x_cyclic_offset: Optional[int] = None, - y_cyclic_offset: Optional[int] = None, - ): - self.mpp_domains_obj = mpp_domains_obj - self.global_indices = global_indices - self.layout = layout - self.domain_id = domain_id - self.pelist = pelist - self.xflags = xflags - self.yflags = yflags - self.xhalo = xhalo - self.yhalo = yhalo - self.xextent = xextent - self.yextent = yextent - self.maskmap = maskmap - self.name = name - self.symmetry = symmetry - self.memory_size = memory_size - self.whalo = whalo - self.ehalo = ehalo - self.shalo = shalo - self.nhalo = nhalo - self.is_mosaic = is_mosaic - self.tile_count = tile_count - self.tile_id = tile_id - self.complete = complete - self.x_cyclic_offset = x_cyclic_offset - self.y_cyclic_offset = y_cyclic_offset - self.compute_domain = pyDomainData() - self.data_domain = pyDomainData() - - self.mpp_domains_obj.define_domains( - global_indices=self.global_indices, - layout=self.layout, - domain_id=self.domain_id, - pelist=self.pelist, - xflags=self.xflags, - yflags=self.yflags, - xhalo=self.xhalo, - yhalo=self.yhalo, - xextent=self.xextent, - yextent=self.yextent, - maskmap=self.maskmap, - name=self.name, - symmetry=self.symmetry, - memory_size=self.memory_size, - whalo=self.whalo, - ehalo=self.ehalo, - shalo=self.shalo, - nhalo=self.nhalo, - is_mosaic=self.is_mosaic, - tile_count=self.tile_count, - tile_id=self.tile_id, - complete=self.complete, - x_cyclic_offset=self.x_cyclic_offset, - y_cyclic_offset=self.y_cyclic_offset, - ) - self.mpp_domains_obj.get_compute_domain( - domain_data=self.compute_domain, - domain_id=self.domain_id, - whalo=self.whalo, - shalo=self.shalo, - ) - self.mpp_domains_obj.get_data_domain( - domain_data=self.data_domain, - domain_id=self.domain_id, - whalo=self.whalo, - shalo=self.shalo, - ) - - def set_compute_domain( - self, - xbegin: Optional[int] = None, - xend: Optional[int] = None, - ybegin: Optional[int] = None, - yend: Optional[int] = None, - xsize: Optional[int] = None, - ysize: Optional[int] = None, - x_is_global: Optional[bool] = None, - y_is_global: Optional[bool] = None, - tile_count: Optional[int] = None, - domain_id: Optional[int] = None, - whalo: Optional[int] = None, - shalo: Optional[int] = None, - ): - self.mpp_domains_obj.set_compute_domain( - xbegin=xbegin, - xend=xend, - ybegin=ybegin, - yend=yend, - xsize=xsize, - ysize=ysize, - x_is_global=x_is_global, - y_is_global=y_is_global, - tile_count=tile_count, - domain_id=domain_id, - whalo=whalo, - shalo=shalo, - ) - - self.mpp_domains_obj.get_compute_domain( - domain_data=self.compute_domain, - domain_id=self.domain_id, - whalo=self.whalo, - shalo=self.shalo, - ) - - def set_data_domain( - self, - xbegin: Optional[int] = None, - xend: Optional[int] = None, - ybegin: Optional[int] = None, - yend: Optional[int] = None, - xsize: Optional[int] = None, - ysize: Optional[int] = None, - x_is_global: Optional[bool] = None, - y_is_global: Optional[bool] = None, - tile_count: Optional[int] = None, - domain_id: Optional[int] = None, - whalo: Optional[int] = None, - shalo: Optional[int] = None, - ): - self.mpp_domains_obj.set_data_domain( - xbegin=xbegin, - xend=xend, - ybegin=ybegin, - yend=yend, - xsize=xsize, - ysize=ysize, - x_is_global=x_is_global, - y_is_global=y_is_global, - tile_count=tile_count, - domain_id=domain_id, - whalo=whalo, - shalo=shalo, - ) - - self.mpp_domains_obj.get_data_domain( - domain_data=self.data_domain, - domain_id=self.domain_id, - whalo=self.whalo, - shalo=self.shalo, - ) - - def set_global_domain( - self, - xbegin: Optional[int] = None, - xend: Optional[int] = None, - ybegin: Optional[int] = None, - yend: Optional[int] = None, - xsize: Optional[int] = None, - ysize: Optional[int] = None, - tile_count: Optional[int] = None, - domain_id: Optional[int] = None, - whalo: Optional[int] = None, - shalo: Optional[int] = None, - ): - self.mpp_domains_obj.set_global_domain( - xbegin=xbegin, - xend=xend, - ybegin=ybegin, - yend=yend, - xsize=xsize, - ysize=ysize, - tile_count=tile_count, - domain_id=domain_id, - whalo=whalo, - shalo=shalo, - ) - - -class pyNestDomain: - def __init__( - self, - mpp_domains_obj: pyFMS_mpp_domains, - num_nest: int, - ntiles: int, - nest_level: NDArray, - tile_fine: NDArray, - tile_coarse: NDArray, - istart_coarse: NDArray, - icount_coarse: NDArray, - jstart_coarse: NDArray, - jcount_coarse: NDArray, - npes_nest_tile: NDArray, - x_refine: NDArray, - y_refine: NDArray, - nest_domain_id: Optional[int] = None, - domain_id: Optional[int] = None, - extra_halo: Optional[int] = None, - name: Optional[str] = None, - ): - self.mpp_domains_obj = mpp_domains_obj - self.num_nest = num_nest - self.ntiles = ntiles - self.nest_level = nest_level - self.tile_fine = tile_fine - self.tile_coarse = tile_coarse - self.istart_coarse = istart_coarse - self.icount_coarse = icount_coarse - self.jstart_coarse = jstart_coarse - self.jcount_coarse = jcount_coarse - self.npes_nest_tile = npes_nest_tile - self.x_refine = x_refine - self.y_refine = y_refine - self.nest_domain_id = nest_domain_id +class pyDomain(): + + def __init__(self, + domain_id: int = None, + isc: int = None, + jsc: int = None, + iec: int = None, + jec: int = None, + isd: int = None, + jsd: int = None, + ied: int = None, + jed: int = None, + tile: int = None, + layout: list[int] = None): self.domain_id = domain_id - self.extra_halo = extra_halo - self.name = name - - self.mpp_domains_obj.define_nest_domains( - num_nest=self.num_nest, - ntiles=self.ntiles, - nest_level=self.nest_level, - tile_fine=self.tile_fine, - tile_coarse=self.tile_coarse, - istart_coarse=self.istart_coarse, - icount_coarse=self.icount_coarse, - jstart_coarse=self.jstart_coarse, - jcount_coarse=self.jcount_coarse, - npes_nest_tile=self.npes_nest_tile, - x_refine=self.x_refine, - y_refine=self.y_refine, - nest_domain_id=self.nest_domain_id, - domain_id=self.domain_id, - extra_halo=self.extra_halo, - name=self.name, - ) + self.isc = isc + self.jsc = jsc + self.iec = iec + self.jec = jec + self.isd = isd + self.jsd = jsd + self.ied = ied + self.jed = jed + self.tile = tile + self.layout = layout + + def update_compute_domain(self, + position: int = None, + tile_count: int = None, + whalo: int = None, + shalo: int = None): + compute = mpp_domains.get_compute_domain(domain_id=self.domain_id, + tile_count=tile_count, + position = position, + whalo=whalo, + shalo=shalo) + self.isc = compute["xbegin"] + self.jsc = compute["ybegin"] + self.iec = compute["xend"] + self.iec = compute["yend"] + + def update_data_domain(self, + position: int = None, + tile_count: int = None, + whalo: int = None, + shalo: int = None): + data = mpp_domains.get_data_domain(domain_id=self.domain_id, + tile_count=tile_count, + position = position, + whalo=whalo, + shalo=shalo) + self.isd = data["xbegin"] + self.jsd = data["ybegin"] + self.ied = data["xend"] + self.jed = data["yend"] + diff --git a/pyfms/pyfms.py b/pyfms/pyfms.py index eba41a1..463b667 100755 --- a/pyfms/pyfms.py +++ b/pyfms/pyfms.py @@ -2,89 +2,57 @@ import ctypes import os -from typing import Optional - +from .py_mpp.py_mpp_domains import mpp_domains from .pyfms_utils.data_handling import set_Cchar, setscalar_Cint32 - -class pyFMS: - def __init__( - self, - cFMS_path: Optional[str] = os.path.dirname(__file__) - + "/../cFMS/cLIBFMS/lib/libcFMS.so", - cFMS: ctypes.CDLL = None, - alt_input_nml_path: str = None, - localcomm: int = None, - ndomain: int = None, - nnest_domain: int = None, - calendar_type: int = None, +class fms: + + __libpath: str = None + __lib: ctypes.CDLL = None + __initialized = False + + NOTE : int = None + WARNING: int = None + FATAL: int = None + THIRTY_DAY_MONTHS: int = None + GREGORIAN: int = None + JULIAN: int = None + NOLEAP: int = None + + @classmethod + def setlib(cls, libpath, lib): + cls.__lib_path = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath + + @classmethod + def init(cls, + alt_input_nml_path: str = None, + localcomm: int = None, + ndomain: int = None, + nnest_domain: int = None, + calendar_type: int = None, ): - self.cFMS_path = cFMS_path - self.cFMS = cFMS - self.alt_input_nml_path = alt_input_nml_path - self.localcomm = localcomm - self.ndomain = ndomain - self.nnest_domain = nnest_domain - self.calendar_type = calendar_type - - if self.cFMS_path is None: - raise ValueError( - "Please define the library file path, e.g., as libFMS(cFMS_path=./cFMS.so)" - ) - - if not os.path.isfile(self.cFMS_path): - raise ValueError(f"Library {self.cFMS_path} does not exist") - - if self.cFMS is None: - self.cFMS = ctypes.cdll.LoadLibrary(self.cFMS_path) - - self.pyfms_init( - self.localcomm, - self.alt_input_nml_path, - self.ndomain, - self.nnest_domain, - self.calendar_type, - ) - - """ - Subroutine: pyfms_end - - Calls the termination routines for all modules in the MPP package. - Termination routine for the fms module. It also calls destructor routines - for the mpp, mpp_domains, and mpp_io modules. If this routine is called - more than once it will return silently. There are no arguments. - """ - - def pyfms_end(self): - _cfms_end = self.cFMS.cFMS_end - - _cfms_end.restype = None - - _cfms_end() - - """ - Subroutine: pyfms_init - - Initializes the FMS module and also calls the initialization routines for - all modules in the MPP package. Will be called automatically if the user - does not call it. - Initialization routine for the fms module. It also calls initialization - routines for the mpp, mpp_domains, and mpp_io modules. Although this - routine will be called automatically by other fms_mod routines, users - should explicitly call fms_init. If this routine is called more than once - it will return silently. There are no arguments. - """ - - def pyfms_init( - self, - localcomm: Optional[int] = None, - alt_input_nml_path: Optional[str] = None, - ndomain: Optional[int] = None, - nnest_domain: Optional[int] = None, - calendar_type: Optional[int] = None, - ): - _cfms_init = self.cFMS.cFMS_init + cls.NOTE = ctypes.c_int.in_dll(cls.lib, "NOTE") + cls.WARNING = ctypes.c_int.in_dll(cls.lib, "WARNING") + cls.FATAL = ctypes.c_int.in_dll(cls.lib, "FATAL") + cls.THIRTY_DAY_MONTHS = ctypes.c_int.in_dll(cls.lib, "THIRTY_DAY_MONTHS") + cls.GREGORIAN = ctypes.c_int.in_dll(cls.lib, "GREGORIAN") + cls.JULIAN = ctypes.c_int.in_dll(cls.lib, "JULIAN") + cls.NOLEAP = ctypes.c_int.in_dll(cls.lib, "NOLEAP") + + _cfms_init = cls.lib.cFMS_init + localcomm_c, localcomm_t = setscalar_Cint32(localcomm) alt_input_nml_path_c, alt_input_nml_path_t = set_Cchar(alt_input_nml_path) ndomain_c, ndomain_t = setscalar_Cint32(ndomain) @@ -107,19 +75,19 @@ def pyfms_init( nnest_domain_c, calendar_type_c, ) + mpp_domains.init() """ - Subroutine: pyfms_set_pelist_npes + Subroutine: pyfms_end - This method is used to set a npes variable of the cFMS module it wraps + Calls the termination routines for all modules in the MPP package. + Termination routine for the fms module. It also calls destructor routines + for the mpp, mpp_domains, and mpp_io modules. If this routine is called + more than once it will return silently. There are no arguments. """ - def set_pelist_npes(self, npes_in: int): - _cfms_set_npes = self.cFMS.cFMS_set_pelist_npes - - npes_in_c, npes_in_t = setscalar_Cint32(npes_in) - - _cfms_set_npes.argtypes = [npes_in_t] - _cfms_set_npes.restype = None - - _cfms_set_npes(npes_in_c) + @classmethod + def end(cls): + _cfms_end = cls.lib.cFMS_end + _cfms_end.restype = None + _cfms_end() diff --git a/pyfms/pyfms_utils/grid_utils.py b/pyfms/pyfms_utils/grid_utils.py index 2cf8251..fed80df 100644 --- a/pyfms/pyfms_utils/grid_utils.py +++ b/pyfms/pyfms_utils/grid_utils.py @@ -4,49 +4,68 @@ import numpy.typing as npt -class GridUtils: - @staticmethod - def get_grid_area( - cfms: ctypes.CDLL, - nlon: int, - nlat: int, - lon: npt.NDArray[np.float64], - lat: npt.NDArray[np.float64], - ) -> npt.NDArray[np.float64]: +class grid_utils(): - ncells = nlon * nlat - ngridpts = (nlon + 1) * (nlat + 1) + __libpath: str = None + __lib: ctypes.CDLL = None + + @classmethod + def setlib(cls, libpath, lib): + cls.__libpath = libpath + cls.__lib = lib + + @classmethod + @property + def lib(cls): + return cls.__lib + + @classmethod + @property + def libpath(cls): + return cls.__libpath - nlon_t = ctypes.c_int - nlat_t = ctypes.c_int - lon_ndp = np.ctypeslib.ndpointer( - dtype=np.float64, shape=(ngridpts), flags="C_CONTIGUOUS" - ) - lat_ndp = np.ctypeslib.ndpointer( - dtype=np.float64, shape=(ngridpts), flags="C_CONTIGUOUS" - ) - area_ndp = np.ctypeslib.ndpointer( - dtype=np.float64, shape=(ncells), flags="C_CONTIGUOUS" - ) - - nlon_c = nlon_t(nlon) - nlat_c = nlat_t(nlat) - area = np.zeros(ncells, dtype=np.float64) - - _get_grid_area = cfms.cFMS_get_grid_area - - _get_grid_area.restype = None - _get_grid_area.argtypes = [ - ctypes.POINTER(nlon_t), - ctypes.POINTER(nlat_t), - lon_ndp, - lat_ndp, - area_ndp, - ] - - nlon_c = nlon_t(nlon) - nlat_c = nlat_t(nlat) - - _get_grid_area(ctypes.byref(nlon_c), ctypes.byref(nlat_c), lon, lat, area) - - return area + @classmethod + def get_grid_area( + cls, + nlon: int, + nlat: int, + lon: npt.NDArray[np.float64], + lat: npt.NDArray[np.float64], + ) -> npt.NDArray[np.float64]: + + ncells = nlon * nlat + ngridpts = (nlon + 1) * (nlat + 1) + + nlon_t = ctypes.c_int + nlat_t = ctypes.c_int + lon_ndp = np.ctypeslib.ndpointer( + dtype=np.float64, shape=(ngridpts), flags="C_CONTIGUOUS" + ) + lat_ndp = np.ctypeslib.ndpointer( + dtype=np.float64, shape=(ngridpts), flags="C_CONTIGUOUS" + ) + area_ndp = np.ctypeslib.ndpointer( + dtype=np.float64, shape=(ncells), flags="C_CONTIGUOUS" + ) + + nlon_c = nlon_t(nlon) + nlat_c = nlat_t(nlat) + area = np.zeros(ncells, dtype=np.float64) + + _get_grid_area = cls.lib.cFMS_get_grid_area + + _get_grid_area.restype = None + _get_grid_area.argtypes = [ + ctypes.POINTER(nlon_t), + ctypes.POINTER(nlat_t), + lon_ndp, + lat_ndp, + area_ndp, + ] + + nlon_c = nlon_t(nlon) + nlat_c = nlat_t(nlat) + + _get_grid_area(ctypes.byref(nlon_c), ctypes.byref(nlat_c), lon, lat, area) + + return area diff --git a/run_tests.sh b/run_tests.sh index a02a022..034e024 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -16,20 +16,20 @@ function run_test() { run_test "pytest tests/test_build.py" -test="tests/test_pyfms.py" -create_input $test -run_test "pytest -m parallel $test" -remove_input $test +#test="tests/test_pyfms.py" +#create_input $test +#run_test "pytest -m parallel $test" +#remove_input $test -test="tests/py_mpp/test_define_domains.py" -create_input $test -run_test "mpirun -n 8 python -m pytest -m 'parallel' $test" -remove_input $test +#test="tests/py_mpp/test_define_domains.py" +#create_input $test +#run_test "mpirun -n 8 python -m pytest -m 'parallel' $test" +#remove_input $test -test="tests/py_mpp/test_getset_domains.py" -create_input $test -run_test "mpirun -n 4 python -m pytest -m 'parallel' tests/py_mpp/test_getset_domains.py" -remove_input $test +#test="tests/py_mpp/test_getset_domains.py" +#create_input $test +#run_test "mpirun -n 4 python -m pytest -m 'parallel' tests/py_mpp/test_getset_domains.py" +#remove_input $test run_test "pytest tests/py_horiz_interp" @@ -39,6 +39,6 @@ remove_input "tests/py_data_override/test_data_override.py" run_test "pytest tests/py_diag_manager/test_generate_files.py" run_test "mpirun -n 1 python -m pytest tests/py_diag_manager/test_diag_manager.py" -remove_input "tests/py_diag_manager/test_diag_manager.py +remove_input "tests/py_diag_manager/test_diag_manager.py" rm -rf INPUT *logfile* *warnfile* diff --git a/testme.py b/testme.py new file mode 100755 index 0000000..3dd7cfc --- /dev/null +++ b/testme.py @@ -0,0 +1,55 @@ +import os +import numpy as np +from mpi4py import MPI +import pyfms + +input_nml = open("input.nml", "w") +input_nml.close() + +cfms = pyfms.cFMS.lib +print(cfms) + +cfms_do = pyfms.data_override.lib +print(cfms_do) + +cfms_fms = pyfms.fms.lib +print(cfms_fms) + +cfms_diag_manager = pyfms.diag_manager.lib +print(cfms_diag_manager) + +cfms_horiz_interp = pyfms.horiz_interp.lib +print(cfms_horiz_interp) + +cfms_grid_utils = pyfms.grid_utils.lib +print(cfms_horiz_interp) + +cfms_mpp = pyfms.mpp.lib +print(cfms_mpp) + +cfms_mpp_domains = pyfms.mpp_domains.lib +print(cfms_mpp_domains) + +pyfms.fms.init(alt_input_nml_path=None, + localcomm=MPI.COMM_WORLD.Get_rank(), + ndomain=1, + nnest_domain=1, + calendar_type=None) + +#pyfms.diag_manager.init() +#cfms_path = pyfms.cFMS.libpath +#cfms_path_do = pyfms.data_override.libpath + + +#assert(id(cfms)==id(cfms_do)) +#assert(cfms_path == cfms_path_do) + +#fake_path = "I/dont/exist" +#pyfms.cFMS.cfms_path = fake_path +#assert(pyfms.cFMS.lib()[0] is not fake_path) + +#pyfms.pyFMS.init( + +#pyfms.data_override.init() + +os.remove("input.nml") diff --git a/tests/py_data_override/test_data_override.py b/tests/py_data_override/test_data_override.py index 6e64825..318a4c8 100644 --- a/tests/py_data_override/test_data_override.py +++ b/tests/py_data_override/test_data_override.py @@ -10,11 +10,6 @@ @pytest.mark.parallel def test_data_override(): - pyfmsobj = pyfms.pyFMS() - cfms = pyfmsobj.cFMS - mpp = pyfms.pyFMS_mpp(cFMS=cfms) - mpp_domains = pyfms.pyFMS_mpp_domains(cFMS=cfms) - ocn_domain_id = 0 nx = 360 ny = 180 @@ -22,14 +17,12 @@ def test_data_override(): ehalo = 2 whalo = 2 shalo = 2 - nhalo = 2 - - global_indices = np.array([0, nx - 1, 0, ny - 1], dtype=np.int32, order="C") - layout = np.array([2, 3], dtype=np.int32, order="C") + nhalo = 2 - mpp_domains.define_domains( - global_indices=global_indices, - layout=layout, + pyfms.fms.init() + pyfms.mpp_domains.define_domains( + global_indices=[0, nx-1, 0, ny-1], + layout=[2,3], ehalo=ehalo, whalo=whalo, shalo=shalo, @@ -37,20 +30,19 @@ def test_data_override(): domain_id=ocn_domain_id, ) - compute_dict = mpp_domains.get_compute_domain2(domain_id=ocn_domain_id) + compute_dict = pyfms.mpp_domains.get_compute_domain(domain_id=ocn_domain_id) xsize = compute_dict["xsize"] ysize = compute_dict["ysize"] - data_override = pyfms.pyDataOverride(cfms) - data_override.init(ocn_domain_id=ocn_domain_id) - data_override.set_time(year=1, month=1, day=3, hour=0, minute=0, second=0, tick=0) + pyfms.data_override.init(ocn_domain_id=ocn_domain_id) + pyfms.data_override.set_time(year=1, month=1, day=3, hour=0, minute=0, second=0, tick=0) - data = data_override.override_scalar( + data = pyfms.data_override.override_scalar( gridname="OCN", fieldname="runoff_scalar", data_type=np.float64 ) assert data == 2.0 - data = data_override.override( + data = pyfms.data_override.override( gridname="OCN", fieldname="runoff_2d", data_shape=(xsize, ysize), @@ -58,7 +50,7 @@ def test_data_override(): ) assert np.all(data == 200.0) - data = data_override.override( + data = pyfms.data_override.override( gridname="OCN", fieldname="runoff_3d", data_shape=(xsize, ysize, nz), @@ -69,7 +61,7 @@ def test_data_override(): ) assert np.all(data == answers) - pyfmsobj.pyfms_end() + pyfms.fms.end() @pytest.mark.remove @@ -80,3 +72,5 @@ def test_remove_files(): assert not os.path.exists("INPUT") assert not os.path.isfile("input.nml") assert not os.path.isfile("data_table.yaml") + + diff --git a/tests/py_diag_manager/test_diag_manager.py b/tests/py_diag_manager/test_diag_manager.py index ce65291..8636251 100644 --- a/tests/py_diag_manager/test_diag_manager.py +++ b/tests/py_diag_manager/test_diag_manager.py @@ -1,7 +1,5 @@ import numpy as np - -from pyfms import DiagManager, pyFMS, pyFMS_mpp_domains - +import pyfms def test_send_data(): @@ -10,13 +8,15 @@ def test_send_data(): NZ = 2 domain_id = 0 - calendar_type = 4 + calendar_type = pyfms.fms.NOLEAP + DIAG_ALL = pyfms.diag_manager.DIAG_ALL + var2_shape = [NX, NY] - var2 = np.empty(shape=(NX, NY), dtype=np.float32) - + var2 = np.empty(shape=var2_shape, dtype=np.float32) + var3_shape = [NX, NY, NZ] - var3 = np.empty(shape=(NX, NY, NZ), dtype=np.float32) + var3 = np.empty(shape=var3_shape, dtype=np.float32) for i in range(NX): for j in range(NY): @@ -27,21 +27,18 @@ def test_send_data(): for j in range(NY): var2[i][j] = i * 10.0 + j * 1.0 - cfms_path = "./cFMS/libcFMS/.libs/libcFMS.so" - - pyfms = pyFMS(cFMS_path=cfms_path, calendar_type=calendar_type) - mpp_domains = pyFMS_mpp_domains(cFMS=pyfms.cFMS) - + pyfms.fms.init() + global_indices = [0, (NX - 1), 0, (NY - 1)] layout = [1, 1] io_layout = [1, 1] - mpp_domains.define_domains( + pyfms.mpp_domains.define_domains( domain_id=domain_id, global_indices=global_indices, layout=layout, ) - mpp_domains.define_io_domain( + pyfms.mpp_domains.define_io_domain( domain_id=domain_id, io_layout=io_layout, ) @@ -50,17 +47,16 @@ def test_send_data(): diag manager init """ - diag_manager = DiagManager(clibFMS=pyfms.cFMS) - diag_manager.init(diag_model_subset=diag_manager.DIAG_ALL) + pyfms.diag_manager.init(diag_model_subset=DIAG_ALL) - mpp_domains.set_current_domain(domain_id=domain_id) + pyfms.mpp_domains.set_current_domain(domain_id=domain_id) """ diag axis init x """ x = np.arange(NX, dtype=np.float64) - id_x = diag_manager.axis_init( + id_x = pyfms.diag_manager.axis_init( name="x", axis_data=x, units="point_E", @@ -74,7 +70,7 @@ def test_send_data(): """ y = np.arange(NY, dtype=np.float64) - id_y = diag_manager.axis_init( + id_y = pyfms.diag_manager.axis_init( name="y", axis_data=y, units="point_N", @@ -89,7 +85,7 @@ def test_send_data(): z = np.arange(NZ, dtype=np.float64) - id_z = diag_manager.axis_init( + id_z = pyfms.diag_manager.axis_init( name="z", axis_data=z, units="point_Z", @@ -104,9 +100,9 @@ def test_send_data(): """ axes_3d = [id_x, id_y, id_z] - range_3d = np.array([-1000.0, 1000.0], dtype=np.float32) + range_3d = [-1000.0, 1000.0] - diag_manager.set_field_init_time( + pyfms.diag_manager.set_field_init_time( year=2, month=1, day=1, @@ -115,7 +111,7 @@ def test_send_data(): second=1, ) - id_var3 = diag_manager.register_field_array( + id_var3 = pyfms.diag_manager.register_field_array( module_name="atm_mod", field_name="var_3d", datatype=np.float32, @@ -125,8 +121,9 @@ def test_send_data(): missing_value=-99.99, range_data=range_3d, ) + - diag_manager.set_field_timestep( + pyfms.diag_manager.set_field_timestep( diag_field_id=id_var3, dseconds=60 * 60, ddays=0, dticks=0 ) @@ -135,9 +132,9 @@ def test_send_data(): """ axes_2d = [id_x, id_y] - range_2d = np.array([-1000.0, 1000.0], dtype=np.float32) + range_2d = [-1000.0, 1000.0] - diag_manager.set_field_init_time( + pyfms.diag_manager.set_field_init_time( year=2, month=1, day=1, @@ -146,7 +143,7 @@ def test_send_data(): second=1, ) - id_var2 = diag_manager.register_field_array( + id_var2 = pyfms.diag_manager.register_field_array( module_name="atm_mod", field_name="var_2d", datatype=np.float32, @@ -157,7 +154,7 @@ def test_send_data(): range_data=range_2d, ) - diag_manager.set_field_timestep( + pyfms.diag_manager.set_field_timestep( diag_field_id=id_var2, dseconds=60 * 60, ddays=0, @@ -168,7 +165,7 @@ def test_send_data(): diag set time end """ - diag_manager.set_time_end( + pyfms.diag_manager.set_time_end( year=2, month=1, day=2, @@ -182,7 +179,7 @@ def test_send_data(): send data """ - diag_manager.send_data( + pyfms.diag_manager.send_data( diag_field_id=id_var3, field_shape=var3_shape, field=var3, @@ -193,27 +190,26 @@ def test_send_data(): var3 = -var3 - diag_manager.advance_field_time(diag_field_id=id_var3) - diag_manager.send_data( + pyfms.diag_manager.advance_field_time(diag_field_id=id_var3) + pyfms.diag_manager.send_data( diag_field_id=id_var3, field_shape=var3_shape, field=var3, ) - diag_manager.send_complete(diag_field_id=id_var3) + pyfms.diag_manager.send_complete(diag_field_id=id_var3) var2 = -var2 - diag_manager.advance_field_time(diag_field_id=id_var2) - diag_manager.send_data( + pyfms.diag_manager.advance_field_time(diag_field_id=id_var2) + pyfms.diag_manager.send_data( diag_field_id=id_var2, field_shape=var2_shape, field=var2, ) - diag_manager.send_complete(diag_field_id=id_var2) - - diag_manager.end() + pyfms.diag_manager.send_complete(diag_field_id=id_var2) - pyfms.pyfms_end() + pyfms.diag_manager.end() + pyfms.fms.end() if __name__ == "__main__": diff --git a/tests/py_horiz_interp/test_horiz_interp.py b/tests/py_horiz_interp/test_horiz_interp.py index 67cbecf..1bbee79 100755 --- a/tests/py_horiz_interp/test_horiz_interp.py +++ b/tests/py_horiz_interp/test_horiz_interp.py @@ -5,9 +5,6 @@ import pyfms -cfms_path = os.path.dirname(__file__) + "/../../cFMS/cLIBFMS/lib/libcFMS.so" - - def test_create_input_nml(): inputnml = open("input.nml", "w") inputnml.close() @@ -16,8 +13,8 @@ def test_create_input_nml(): def test_create_xgrid(): - cfms = pyfms.pyFMS(cFMS_path=cfms_path).cFMS - create_xgrid = pyfms.HorizInterp(cfms=cfms).create_xgrid_2dx2d_order1 + pyfms.fms.init() + create_xgrid = pyfms.horiz_interp.create_xgrid_2dx2d_order1 refine = 1 lon_init = 0.0 @@ -70,8 +67,8 @@ def test_create_xgrid(): ) # answer checking - area = pyfms.GridUtils.get_grid_area( - cfms=cfms, nlon=nlon_src, nlat=nlat_src, lon=lon_src, lat=lat_src + area = pyfms.grid_utils.get_grid_area( + nlon=nlon_src, nlat=nlat_src, lon=lon_src, lat=lat_src ) assert xgrid["nxgrid"] == nlon_src * nlat_src diff --git a/tests/py_mpp/test_define_domains.py b/tests/py_mpp/test_define_domains.py index 08c429f..29e5728 100644 --- a/tests/py_mpp/test_define_domains.py +++ b/tests/py_mpp/test_define_domains.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from pyfms import pyFMS, pyFMS_mpp, pyFMS_mpp_domains +import pyfms @pytest.mark.create @@ -16,190 +16,125 @@ def test_create_input_nml(): @pytest.mark.parallel def test_define_domains(): - NX = 96 - NY = 96 - NX_FINE = 48 - NY_FINE = 48 - X_REFINE = 2 - Y_REFINE = 2 - COARSE_NPES = 4 - FINE_NPES = 4 - ndomain = 2 nnest_domain = 2 - domain_id = 1 - nest_domain_id = 1 - - coarse_global_indices = [0, NX - 1, 0, NY - 1] - coarse_npes = COARSE_NPES - coarse_pelist = np.empty(shape=COARSE_NPES, dtype=np.int32, order="C") + domain_id = 0 + nest_domain_id = 0 + + nx = 96 + ny = 96 + coarse_global_indices = [0, nx - 1, 0, ny - 1] + coarse_npes = 4 + coarse_pelist = list(range(coarse_npes)) coarse_tile_id = 0 - coarse_whalo = 2 - coarse_ehalo = 2 - coarse_shalo = 2 - coarse_nhalo = 2 - coarse_xflags = 3 - coarse_yflags = 2 - is_mosaic = False - symmetry = False - - fine_global_indices = [0, NX_FINE - 1, 0, NY_FINE - 1] - fine_npes = FINE_NPES - fine_pelist = np.empty(shape=FINE_NPES, dtype=np.int32, order="C") - fine_tile_id = 1 - fine_whalo = 2 - fine_ehalo = 2 - fine_shalo = 2 - fine_nhalo = 2 - - cfms_path = "./cFMS/libcFMS/.libs/libcFMS.so" - - assert os.path.exists(cfms_path) - pyfms = pyFMS( - cFMS_path=cfms_path, - ndomain=ndomain, - nnest_domain=nnest_domain, - ) - mpp = pyFMS_mpp(cFMS=pyfms.cFMS) - mpp_domains = pyFMS_mpp_domains(cFMS=pyfms.cFMS) - - assert isinstance(pyfms, pyFMS) + nx_fine = 48 + ny_fine = 48 + fine_global_indices = [0, nx_fine - 1, 0, ny_fine - 1] + fine_npes = 4 + fine_pelist = list(range(fine_npes)) + fine_tile_id = 1 + + pyfms.fms.init(ndomain=ndomain, nnest_domain=nnest_domain) """get global pelist""" - npes = mpp.npes() - pyfms.set_pelist_npes(npes_in=npes) - global_pelist = mpp.get_current_pelist() + pyfms.mpp.set_pelist_npes(npes_in=pyfms.mpp.npes()) + global_pelist = pyfms.mpp.get_current_pelist() """set coarse domain as tile=0""" - for i in range(coarse_npes): - coarse_pelist[i] = global_pelist[i] - name_coarse = "test coarse pelist" - pyfms.set_pelist_npes(npes_in=coarse_npes) - mpp.declare_pelist(pelist=coarse_pelist, name=name_coarse) - - if mpp.pe() in coarse_pelist: - pyfms.set_pelist_npes(coarse_npes) - mpp.set_current_pelist(coarse_pelist) - name = "test coarse domain" - maskmap = np.full(shape=(2, 4), fill_value=True, dtype=np.bool_) + coarse_pelist = global_pelist[:coarse_npes] + pyfms.mpp.set_pelist_npes(npes_in=coarse_npes) + pyfms.mpp.declare_pelist(pelist=coarse_pelist, name="test coarse pelist") - xextent = np.zeros(shape=2, dtype=np.int32, order="C") - yextent = np.zeros(shape=2, dtype=np.int32, order="C") - is_mosaic = False - - ndivs = coarse_npes - - layout = mpp_domains.define_layout( + if pyfms.mpp.pe() in coarse_pelist: + pyfms.mpp.set_pelist_npes(coarse_npes) + pyfms.mpp.set_current_pelist(coarse_pelist) + + layout = pyfms.mpp_domains.define_layout( global_indices=coarse_global_indices, - ndivs=ndivs, + ndivs=coarse_npes, ) - - mpp_domains.define_domains( + + pyfms.mpp_domains.define_domains( global_indices=coarse_global_indices, layout=layout, domain_id=domain_id, pelist=coarse_pelist, - xflags=coarse_xflags, - yflags=coarse_yflags, - xextent=xextent, - yextent=yextent, - maskmap=maskmap, - name=name, - symmetry=symmetry, - whalo=coarse_whalo, - ehalo=coarse_ehalo, - shalo=coarse_shalo, - nhalo=coarse_nhalo, - is_mosaic=is_mosaic, + xflags=pyfms.mpp_domains.WEST, + yflags=pyfms.mpp_domains.SOUTH, + xextent=[nx/2]*4, + yextent=[ny/2]*4, + maskmap=None, #[[True,True],[True,True]], + name="test coarse domain", + symmetry=False, + whalo=2, + ehalo=2, + shalo=2, + nhalo=2, + is_mosaic=False, tile_id=coarse_tile_id, ) - mpp.set_current_pelist() + pyfms.mpp.set_current_pelist() """set fine domain as tile=1""" - name_fine = "test fine pelist" - for i in range(fine_npes): - fine_pelist[i] = global_pelist[COARSE_NPES + i] - pyfms.set_pelist_npes(fine_npes) - mpp.declare_pelist(pelist=fine_pelist, name=name_fine) - - if mpp.pe() in fine_pelist: - pyfms.set_pelist_npes(fine_npes) - mpp.set_current_pelist(pelist=fine_pelist) + fine_pelist = global_pelist[coarse_npes:coarse_npes+fine_npes] + pyfms.mpp.set_pelist_npes(fine_npes) + pyfms.mpp.declare_pelist(pelist=fine_pelist, name="test fine pelist") - name = "test fine domain" - ndivs = FINE_NPES + if pyfms.mpp.pe() in fine_pelist: + pyfms.mpp.set_pelist_npes(fine_npes) + pyfms.mpp.set_current_pelist(pelist=fine_pelist) - layout = mpp_domains.define_layout( + layout = pyfms.mpp_domains.define_layout( global_indices=fine_global_indices, - ndivs=ndivs, + ndivs=fine_npes, ) - mpp_domains.define_domains( + pyfms.mpp_domains.define_domains( global_indices=fine_global_indices, layout=layout, domain_id=domain_id, pelist=fine_pelist, - name=name, - symmetry=symmetry, - whalo=fine_whalo, - ehalo=fine_ehalo, - shalo=fine_shalo, - nhalo=fine_nhalo, - is_mosaic=is_mosaic, + name="test fine domain", + symmetry=False, + whalo=2, + ehalo=2, + shalo=2, + nhalo=2, + is_mosaic=False, tile_id=fine_tile_id, ) + assert pyfms.mpp_domains.domain_is_initialized(domain_id) - mpp.set_current_pelist() - - assert mpp_domains.domain_is_initialized(domain_id) + pyfms.mpp.set_current_pelist() """set nest domain""" - - name = "test nest domain" - num_nest = 1 - ntiles = 2 - nest_level = np.array([1], dtype=np.int32, order="C") - istart_coarse = np.array([24], dtype=np.int32, order="C") - icount_coarse = np.array([24], dtype=np.int32, order="C") - jstart_coarse = np.array([24], dtype=np.int32, order="C") - jcount_coarse = np.array([24], dtype=np.int32, order="C") - npes_nest_tile = np.array([COARSE_NPES, FINE_NPES], dtype=np.int32, order="C") - x_refine = np.array([X_REFINE], dtype=np.int32, order="C") - y_refine = np.array([Y_REFINE], dtype=np.int32, order="C") - tile_fine = np.array([fine_tile_id], dtype=np.int32, order="C") - tile_coarse = np.array([coarse_tile_id], dtype=np.int32, order="C") - nest_domain_id = nest_domain_id - domain_id = domain_id - - mpp_domains.define_nest_domains( - num_nest=num_nest, - ntiles=ntiles, - nest_level=nest_level, - tile_fine=tile_fine, - tile_coarse=tile_coarse, - istart_coarse=istart_coarse, - icount_coarse=icount_coarse, - jstart_coarse=jstart_coarse, - jcount_coarse=jcount_coarse, - npes_nest_tile=npes_nest_tile, - x_refine=x_refine, - y_refine=y_refine, + + pyfms.mpp_domains.define_nest_domains( + num_nest=1, + ntiles=2, + nest_level=[1], + tile_fine=[fine_tile_id], + tile_coarse=[coarse_tile_id], + istart_coarse=[24], + icount_coarse=[24], + jstart_coarse=[24], + jcount_coarse=[24], + npes_nest_tile=[coarse_npes, fine_npes], + x_refine=[2], + y_refine=[2], nest_domain_id=nest_domain_id, domain_id=domain_id, - extra_halo=None, - name=name, + name="test nest domain", ) - mpp.set_current_pelist() - - pyfms.pyfms_end() - - # mpp.pyfms_error(errortype=1) + pyfms.mpp.set_current_pelist() + + pyfms.fms.end() @pytest.mark.remove diff --git a/tests/py_mpp/test_getset_domains.py b/tests/py_mpp/test_getset_domains.py index 8438371..7082f32 100644 --- a/tests/py_mpp/test_getset_domains.py +++ b/tests/py_mpp/test_getset_domains.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from pyfms import pyDomain, pyFMS, pyFMS_mpp, pyFMS_mpp_domains +import pyfms @pytest.mark.create @@ -15,7 +15,9 @@ def test_create_input_nml(): @pytest.mark.parallel def test_getset_domains(): + """ + copied from cFMS global domain * * * * * * * * @@ -26,39 +28,33 @@ def test_getset_domains(): * * * * * * * * """ + domain_id = 0 - ndiv = 4 global_indices = [0, 3, 0, 3] whalo = 2 ehalo = 2 shalo = 2 nhalo = 2 - name = "test domain" - - pyfms = pyFMS(cFMS_path="./cFMS/libcFMS/.libs/libcFMS.so") - mpp = pyFMS_mpp(cFMS=pyfms.cFMS) - mpp_domains = pyFMS_mpp_domains(cFMS=pyfms.cFMS) - + # set domain - layout = mpp_domains.define_layout(global_indices=global_indices, ndivs=ndiv) - - domain = pyDomain( - global_indices=global_indices, - layout=layout, - mpp_domains_obj=mpp_domains, - domain_id=domain_id, - name=name, - whalo=whalo, - ehalo=ehalo, - shalo=shalo, - nhalo=nhalo, + pyfms.fms.init() + + layout = pyfms.mpp_domains.define_layout(global_indices=global_indices, ndivs=4) + + domain = pyfms.mpp_domains.define_domains(global_indices=global_indices, + layout=layout, + domain_id=domain_id, + name="test domain", + whalo=whalo, + ehalo=ehalo, + shalo=shalo, + nhalo=nhalo, ) + + assert(pyfms.mpp_domains.domain_is_initialized(domain_id)) - if not mpp_domains.domain_is_initialized(domain_id): - mpp.pyfms_error(1, "error in setting domain") - - mpp.set_current_pelist() + pyfms.mpp.set_current_pelist() """ flipping the domain: @@ -68,10 +64,10 @@ def test_getset_domains(): pe 3: isc=4, iec=5, jsc=4, jec=5 --> pe 0 """ - isc = np.array([4, 2, 4, 2], dtype=np.int32, order="C") - iec = np.array([5, 3, 5, 3], dtype=np.int32, order="C") - jsc = np.array([4, 4, 2, 2], dtype=np.int32, order="C") - jec = np.array([5, 5, 3, 3], dtype=np.int32, order="C") + isc = [4, 2, 4, 2] + iec = [5, 3, 5, 3] + jsc = [4, 4, 2, 2] + jec = [5, 5, 3, 3] """ pe 0: isd=0, ied=5, jsd=0, jed=5 --> pe 3 @@ -80,77 +76,72 @@ def test_getset_domains(): pe 3: isd=2, ied=7, jsd=2, jed=7 --> pe 0 """ - isd = np.array([2, 0, 2, 0], dtype=np.int32, order="C") - ied = np.array([7, 5, 7, 5], dtype=np.int32, order="C") - jsd = np.array([2, 2, 0, 0], dtype=np.int32, order="C") - jed = np.array([7, 7, 5, 5], dtype=np.int32, order="C") + isd = [2, 0, 2, 0] + ied = [7, 5, 7, 5] + jsd = [2, 2, 0, 0] + jed = [7, 7, 5, 5] - pe = mpp.pe() + pe = pyfms.mpp.pe() tile_count = 0 x_is_global = False y_is_global = False # set compute and data domains - xsize = 2 - ysize = 2 - - domain.set_compute_domain( + pyfms.mpp_domains.set_compute_domain( domain_id=domain_id, xbegin=isc[pe], xend=iec[pe], ybegin=jsc[pe], yend=jec[pe], - xsize=xsize, - ysize=ysize, + xsize=2, + ysize=2, x_is_global=x_is_global, y_is_global=y_is_global, - tile_count=tile_count, whalo=whalo, shalo=shalo, - ) - - xsize = 6 - ysize = 6 - - domain.set_data_domain( + ) + + pyfms.mpp_domains.set_data_domain( domain_id=domain_id, xbegin=isd[pe], xend=ied[pe], ybegin=jsd[pe], yend=jed[pe], - xsize=xsize, - ysize=ysize, + xsize=6, + ysize=6, x_is_global=x_is_global, y_is_global=y_is_global, - tile_count=tile_count, whalo=whalo, shalo=shalo, ) - # get domain - - assert domain.compute_domain.xbegin.value == isc[pe] - assert domain.compute_domain.xend.value == iec[pe] - assert domain.compute_domain.ybegin.value == jsc[pe] - assert domain.compute_domain.yend.value == jec[pe] - assert domain.compute_domain.xsize.value == 2 - assert domain.compute_domain.ysize.value == 2 - assert domain.compute_domain.xmax_size.value == 2 - assert domain.compute_domain.ymax_size.value == 2 - assert domain.compute_domain.x_is_global.value is False - assert domain.compute_domain.y_is_global.value is False - - assert domain.data_domain.xbegin.value == isd[pe] - assert domain.data_domain.xend.value == ied[pe] - assert domain.data_domain.ybegin.value == jsd[pe] - assert domain.data_domain.yend.value == jed[pe] - assert domain.data_domain.xsize.value == 6 - assert domain.data_domain.ysize.value == 6 - assert domain.data_domain.xmax_size.value == 6 - assert domain.data_domain.ymax_size.value == 6 - - pyfms.pyfms_end() + compute = pyfms.mpp_domains.get_compute_domain(domain_id=domain_id, whalo=whalo, shalo=shalo) + data = pyfms.mpp_domains.get_data_domain(domain_id=domain_id, whalo=whalo, shalo=shalo) + + # get domain + + assert compute["xbegin"] == isc[pe] + assert compute["xend"] == iec[pe] + assert compute["ybegin"] == jsc[pe] + assert compute["yend"] == jec[pe] + assert compute["xsize"] == 2 + assert compute["ysize"] == 2 + assert compute["xmax_size"] == 2 + assert compute["ymax_size"] == 2 + assert compute["x_is_global"] is False + assert compute["y_is_global"] is False + + assert data["xbegin"] == isd[pe] + assert data["xend"] == ied[pe] + assert data["ybegin"] == jsd[pe] + assert data["yend"] == jed[pe] + assert data["xsize"] == 6 + assert data["ysize"] == 6 + assert data["xmax_size"] == 6 + assert data["ymax_size"] == 6 + + pyfms.fms.end() @pytest.mark.remove