diff --git a/src/addon/ESMPy/.gitignore b/src/addon/ESMPy/.gitignore index 238fdcd5b7..b3ed4aefa2 100644 --- a/src/addon/ESMPy/.gitignore +++ b/src/addon/ESMPy/.gitignore @@ -2,11 +2,6 @@ ################### *.pyc -# Nose # -######## -*.noseids -nosetests.xml - # Misc # ######## *~ @@ -19,21 +14,16 @@ PET* *.vtk *.csv -# Eclipse # -########### -*.project -*.pydevproject -*.settings - # ESMPy build and docs # ######################## build +dist doc/esmpy_doc -src/ESMF/interface/esmfmkfile.py +src/ESMPy.egg-info examples/data -src/ESMF/test/data +src/esmpy/test/data examples/notebooks/ESMPy-data -src/ESMF/test/regrid_from_file/data +src/esmpy/test/regrid_from_file/data # notebooks # ############# diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile new file mode 100644 index 0000000000..2eb768b263 --- /dev/null +++ b/src/addon/ESMPy/Makefile @@ -0,0 +1,63 @@ +.PHONY: clean install test test_int test_all uninstall + +clean: + rm -rf build || : + rm -rf dist || : + find . -name "*.egg-info" -exec rm -rf {} \; || : + find . -name "*.pyc" -exec rm -f {} \; || : + find . -name "*.log" -exec rm -f {} \; || : + find . -name "*.vtk" -exec rm -f {} \; || : + find . -name "*.pytest_cache" -exec rm -rf {} \; || : + find . -name "*.python-version" -exec rm -f {} \; || : + find . -name "*__pycache__" -exec rm -rf {} \; || : + find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : + find . -name "*.report.json" -exec rm -rf {} \; || : + find . -name "*.test" -exec rm -rf {} \; || : + rm -rf src/esmpy/test/regrid_from_file/data || : + rm -rf examples/data || : + +dust: + find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : + find . -name "*.report.json" -exec rm -rf {} \; || : + find . -name "*.test" -exec rm -rf {} \; || : + +install: + python3 -m pip install . + +download_examples: + python3 examples/test_examples_download.py + +download_regrid_from_file: + python3 src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py + +download: download_examples download_regrid_from_file + +test: + bash src/esmpy/test/test_all.bash + +test_unit: + python3 -m pytest -vs + +test_unit_parallel: + mpiexec -n 4 python3 -vs + +test_examples: + python3 -m pytest -vs examples/test_examples.py + +test_examples_parallel: + mpiexec -n 4 python3 -m pytest -vs examples/test_examples.py + +test_regrid_from_file: + python3 -m pytest -vs src/esmpy/test/regrid_from_file/test_regrid_from_file.py + +test_regrid_from_file_parallel: + mpiexec -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/test_regrid_from_file.py + +test_serial: test_unit test_examples test_regrid_from_file + +test_parallel: test_unit_parallel test_examples_parallel test_regrid_from_file_parallel + +test_all: test_unit test_unit_parallel test_examples test_examples_parallel test_regrid_from_file test_regrid_from_file_parallel + +uninstall: + python3 -m pip uninstall ESMPy diff --git a/src/addon/ESMPy/doc/CoordSys.rst b/src/addon/ESMPy/doc/CoordSys.rst index b3d321f566..c60b52ca6b 100644 --- a/src/addon/ESMPy/doc/CoordSys.rst +++ b/src/addon/ESMPy/doc/CoordSys.rst @@ -2,6 +2,6 @@ CoordSys ~~~~~~~~ -.. autoclass:: ESMF.api.constants.CoordSys +.. autoclass:: esmpy.api.constants.CoordSys :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/ExtrapMethod.rst b/src/addon/ESMPy/doc/ExtrapMethod.rst index ec65fb1edd..203eb2e679 100644 --- a/src/addon/ESMPy/doc/ExtrapMethod.rst +++ b/src/addon/ESMPy/doc/ExtrapMethod.rst @@ -2,6 +2,6 @@ ExtrapMethod ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.ExtrapMethod +.. autoclass:: esmpy.api.constants.ExtrapMethod :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/FileFormat.rst b/src/addon/ESMPy/doc/FileFormat.rst index 7a66198768..0d7c5864bf 100755 --- a/src/addon/ESMPy/doc/FileFormat.rst +++ b/src/addon/ESMPy/doc/FileFormat.rst @@ -2,6 +2,6 @@ FileFormat ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.FileFormat +.. autoclass:: esmpy.api.constants.FileFormat :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/FileMode.rst b/src/addon/ESMPy/doc/FileMode.rst index 28b075b6be..1d2ec75a6d 100644 --- a/src/addon/ESMPy/doc/FileMode.rst +++ b/src/addon/ESMPy/doc/FileMode.rst @@ -2,6 +2,6 @@ FileMode ~~~~~~~~ -.. autoclass:: ESMF.api.constants.FileMode +.. autoclass:: esmpy.api.constants.FileMode :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/GridItem.rst b/src/addon/ESMPy/doc/GridItem.rst index 22690888c7..dcb838c55c 100755 --- a/src/addon/ESMPy/doc/GridItem.rst +++ b/src/addon/ESMPy/doc/GridItem.rst @@ -2,6 +2,6 @@ GridItem ~~~~~~~~ -.. autoclass:: ESMF.api.constants.GridItem +.. autoclass:: esmpy.api.constants.GridItem :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/LineType.rst b/src/addon/ESMPy/doc/LineType.rst index e0c37fd9d8..11cd684536 100644 --- a/src/addon/ESMPy/doc/LineType.rst +++ b/src/addon/ESMPy/doc/LineType.rst @@ -2,6 +2,6 @@ LineType ~~~~~~~~ -.. autoclass:: ESMF.api.constants.LineType +.. autoclass:: esmpy.api.constants.LineType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/LogKind.rst b/src/addon/ESMPy/doc/LogKind.rst index e9a329f9bc..721ef17565 100755 --- a/src/addon/ESMPy/doc/LogKind.rst +++ b/src/addon/ESMPy/doc/LogKind.rst @@ -2,6 +2,6 @@ LogKind ~~~~~~~ -.. autoclass:: ESMF.api.constants.LogKind +.. autoclass:: esmpy.api.constants.LogKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/MeshElemType.rst b/src/addon/ESMPy/doc/MeshElemType.rst index 9338f22562..34357fe187 100755 --- a/src/addon/ESMPy/doc/MeshElemType.rst +++ b/src/addon/ESMPy/doc/MeshElemType.rst @@ -2,6 +2,6 @@ MeshElemType ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.MeshElemType +.. autoclass:: esmpy.api.constants.MeshElemType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/MeshLoc.rst b/src/addon/ESMPy/doc/MeshLoc.rst index 05f3ae3ab5..888c3672a4 100755 --- a/src/addon/ESMPy/doc/MeshLoc.rst +++ b/src/addon/ESMPy/doc/MeshLoc.rst @@ -2,6 +2,6 @@ MeshLoc ~~~~~~~ -.. autoclass:: ESMF.api.constants.MeshLoc +.. autoclass:: esmpy.api.constants.MeshLoc :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/NormType.rst b/src/addon/ESMPy/doc/NormType.rst index 4a80e66d62..d4b6cbaa06 100644 --- a/src/addon/ESMPy/doc/NormType.rst +++ b/src/addon/ESMPy/doc/NormType.rst @@ -2,6 +2,6 @@ NormType ~~~~~~~~ -.. autoclass:: ESMF.api.constants.NormType +.. autoclass:: esmpy.api.constants.NormType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/PoleKind.rst b/src/addon/ESMPy/doc/PoleKind.rst index 20206874d2..590cc25d30 100644 --- a/src/addon/ESMPy/doc/PoleKind.rst +++ b/src/addon/ESMPy/doc/PoleKind.rst @@ -2,6 +2,6 @@ PoleKind ~~~~~~~~ -.. autoclass:: ESMF.api.constants.PoleKind +.. autoclass:: esmpy.api.constants.PoleKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/PoleMethod.rst b/src/addon/ESMPy/doc/PoleMethod.rst index 4be0362658..6d59b56e33 100644 --- a/src/addon/ESMPy/doc/PoleMethod.rst +++ b/src/addon/ESMPy/doc/PoleMethod.rst @@ -2,6 +2,6 @@ PoleMethod ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.PoleMethod +.. autoclass:: esmpy.api.constants.PoleMethod :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/Region.rst b/src/addon/ESMPy/doc/Region.rst index 620d792092..b905f434e8 100755 --- a/src/addon/ESMPy/doc/Region.rst +++ b/src/addon/ESMPy/doc/Region.rst @@ -2,6 +2,6 @@ Region ~~~~~~ -.. autoclass:: ESMF.api.constants.Region +.. autoclass:: esmpy.api.constants.Region :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/RegridMethod.rst b/src/addon/ESMPy/doc/RegridMethod.rst index acef1267c5..fc2e5027d0 100755 --- a/src/addon/ESMPy/doc/RegridMethod.rst +++ b/src/addon/ESMPy/doc/RegridMethod.rst @@ -2,6 +2,6 @@ RegridMethod ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.RegridMethod +.. autoclass:: esmpy.api.constants.RegridMethod :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/StaggerLoc.rst b/src/addon/ESMPy/doc/StaggerLoc.rst index 2e09ba247f..7eac7ae404 100755 --- a/src/addon/ESMPy/doc/StaggerLoc.rst +++ b/src/addon/ESMPy/doc/StaggerLoc.rst @@ -2,6 +2,6 @@ StaggerLoc ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.StaggerLoc +.. autoclass:: esmpy.api.constants.StaggerLoc :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/TypeKind.rst b/src/addon/ESMPy/doc/TypeKind.rst index 3b4c5e944c..378973d3e2 100755 --- a/src/addon/ESMPy/doc/TypeKind.rst +++ b/src/addon/ESMPy/doc/TypeKind.rst @@ -2,6 +2,6 @@ TypeKind ~~~~~~~~ -.. autoclass:: ESMF.api.constants.TypeKind +.. autoclass:: esmpy.api.constants.TypeKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/UnmappedAction.rst b/src/addon/ESMPy/doc/UnmappedAction.rst index a9fe04f401..c09ffaf6f8 100755 --- a/src/addon/ESMPy/doc/UnmappedAction.rst +++ b/src/addon/ESMPy/doc/UnmappedAction.rst @@ -2,6 +2,6 @@ UnmappedAction ~~~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.UnmappedAction +.. autoclass:: esmpy.api.constants.UnmappedAction :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/api.rst b/src/addon/ESMPy/doc/api.rst index c6db0bc048..2daf88a531 100644 --- a/src/addon/ESMPy/doc/api.rst +++ b/src/addon/ESMPy/doc/api.rst @@ -6,25 +6,25 @@ API Classes ------- -ESMPy uses a :class:`~ESMF.api.field.Field` object to represent data variables +ESMPy uses a :class:`~esmpy.api.field.Field` object to represent data variables built on an underlying spatial discretization, which is represented by a -:class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or -:class:`~ESMF.api.locstream.LocStream`. -Regridding between :class:`Fields ` is accomplished with the -:class:`~ESMF.api.regrid.Regrid` class. All of these classes are explained in +:class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or +:class:`~esmpy.api.locstream.LocStream`. +Regridding between :class:`Fields ` is accomplished with the +:class:`~esmpy.api.regrid.Regrid` class. All of these classes are explained in more detail in the sections provided by the links in the following table. -======================================== ============================================================================== -Class Description -======================================== ============================================================================== -:class:`~ESMF.api.esmpymanager.Manager` A manager class to initialize and finalize ESMF -:class:`~ESMF.api.field.Field` A data field built on a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or :class:`~ESMF.api.locstream.LocStream` -:class:`~ESMF.api.grid.Grid` A class to represent a logically rectangular grid -:class:`~ESMF.api.mesh.Mesh` A class to represent an unstructured grid -:class:`~ESMF.api.locstream.LocStream` A class to represent observational data as a collection of disconnected points -:class:`~ESMF.api.regrid.Regrid` The regridding utility -:class:`~ESMF.api.regrid.RegridFromFile` The from file regridding utility -======================================== ============================================================================== +========================================= ============================================================================== +Class Description +========================================= ============================================================================== +:class:`~esmpy.api.esmpymanager.Manager` A manager class to initialize and finalize ESMF +:class:`~esmpy.api.field.Field` A data field built on a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or :class:`~esmpy.api.locstream.LocStream` +:class:`~esmpy.api.grid.Grid` A class to represent a logically rectangular grid +:class:`~esmpy.api.mesh.Mesh` A class to represent an unstructured grid +:class:`~esmpy.api.locstream.LocStream` A class to represent observational data as a collection of disconnected points +:class:`~esmpy.api.regrid.Regrid` The regridding utility +:class:`~esmpy.api.regrid.RegridFromFile` The from file regridding utility +========================================= ============================================================================== --------------- @@ -36,33 +36,33 @@ available options for parameters that expect a variety of specific inputs. The following table lists the available named constants and provides links to pages that further explain the available values. -=========================================================== ============================== -Named constants Description -=========================================================== ============================== -:class:`CoordSys` Specify the coordinate system of a :class:`~ESMF.api.grid.Grid` -:class:`ExtrapMethod` Specify the extrapolation method -:class:`FileFormat` Specify the format of a data file -:class:`FileMode` Specify the mode of a data file -:class:`GridItem` Specify a mask or area item on a :class:`~ESMF.api.grid.Grid` -:class:`LineType` Specify the type of line that connects two points on a sphere -:class:`LogKind` Specify how much logging should be done -:class:`MeshElemType` Specify the type of the :class:`~ESMF.api.mesh.Mesh` elements -:class:`MeshLoc` Specify a nodal or elemental :class:`~ESMF.api.mesh.Mesh` -:class:`NormType` Specify the type of normalization to use for conservative regridding weights -:class:`PoleKind` Specify the type of connection that appears at the poles of the :class:`~ESMF.api.grid.Grid` -:class:`PoleMethod` Specify which type of artificial pole to construct on the source :class:`~ESMF.api.grid.Grid` for regridding -:class:`Region` Specify various regions in the data layout of -:class:`RegridMethod` Specify which interpolation method to use regridding -:class:`StaggerLoc` Specify the position for data in a :class:`~ESMF.api.grid.Grid` cell -:class:`TypeKind` Specify the type and kind of data -:class:`UnmappedAction` Specify which action to take with respect to unmapped destination points -=========================================================== ============================== +============================================================ ============================== +Named constants Description +============================================================ ============================== +:class:`CoordSys` Specify the coordinate system of a :class:`~esmpy.api.grid.Grid` +:class:`ExtrapMethod` Specify the extrapolation method +:class:`FileFormat` Specify the format of a data file +:class:`FileMode` Specify the mode of a data file +:class:`GridItem` Specify a mask or area item on a :class:`~esmpy.api.grid.Grid` +:class:`LineType` Specify the type of line that connects two points on a sphere +:class:`LogKind` Specify how much logging should be done +:class:`MeshElemType` Specify the type of the :class:`~esmpy.api.mesh.Mesh` elements +:class:`MeshLoc` Specify a nodal or elemental :class:`~esmpy.api.mesh.Mesh` +:class:`NormType` Specify the type of normalization to use for conservative regridding weights +:class:`PoleKind` Specify the type of connection that appears at the poles of the :class:`~esmpy.api.grid.Grid` +:class:`PoleMethod` Specify which type of artificial pole to construct on the source :class:`~esmpy.api.grid.Grid` for regridding +:class:`Region` Specify various regions in the data layout of +:class:`RegridMethod` Specify which interpolation method to use regridding +:class:`StaggerLoc` Specify the position for data in a :class:`~esmpy.api.grid.Grid` cell +:class:`TypeKind` Specify the type and kind of data +:class:`UnmappedAction` Specify which action to take with respect to unmapped destination points +============================================================ ============================== ------- Manager ------- -The :class:`~ESMF.api.esmpymanager.Manager` is used by ESMPy to simplify a +The :class:`~esmpy.api.esmpymanager.Manager` is used by ESMPy to simplify a number of low-level calls used by the underlying ESMF framework to allocate resources, enable logging, and control garbage collection. @@ -78,11 +78,11 @@ allocates computational resources in the form of system threads with a lifetime of at least that of the ESMPy execution. In the simplest, and most common case, a PET is equivalent to an MPI process. The number of PETs and the current PET can be queried from the -:class:`~ESMF.api.esmpymanager.Manager`: +:class:`~esmpy.api.esmpymanager.Manager`: .. code:: - mg = ESMF.Manager() + mg = esmpy.Manager() pet_count = mg.pet_count() local_pet = mg.local_pet() @@ -94,11 +94,11 @@ for more information. Logging ~~~~~~~ -The :class:`~ESMF.api.esmpymanager.Manager` is also used to enable logging: +The :class:`~esmpy.api.esmpymanager.Manager` is also used to enable logging: .. code:: - mg = ESMF.Manager(debug=True) + mg = esmpy.Manager(debug=True) local_pet = mg.local_pet The output will be logged in files named PET.ESMF_LogFile. @@ -109,10 +109,10 @@ Memory management The underlying ESMF framework needs to be initialized and finalized once and only once per execution. This is handled internally by the -:class:`~ESMF.api.esmpymanager.Manager` and **does not** require any explicit +:class:`~esmpy.api.esmpymanager.Manager` and **does not** require any explicit user intervention. However, the ESMF garbage collection feature is not triggered until the finalization routine is invoked, which may not happen until the -:class:`~ESMF.api.esmpymanager.Manager` goes out of scope at the end of the +:class:`~esmpy.api.esmpymanager.Manager` goes out of scope at the end of the program execution. If memory deallocation of ESMPy @@ -121,12 +121,12 @@ objects is required *prior* to the end of the program, the class level .. code:: - mg = ESMF.Manager() + mg = esmpy.Manager() mg.destroy() -This is commonly required when reusing a :class:`~ESMF.api.regrid.Regrid` object -to interpolate data between many :class:`~ESMF.api.field.Field` pairs. +This is commonly required when reusing a :class:`~esmpy.api.regrid.Regrid` object +to interpolate data between many :class:`~esmpy.api.field.Field` pairs. ~~~~~~~~~~~~~~~~~ MOAB Mesh backend @@ -147,9 +147,9 @@ Spatial Discretization Objects ------------------------------ There are three different objects used for spatial coordinate representation: -:class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, and :class:`~ESMF.api.locstream.LocStream`. :class:`Grids ` are used to represent logically rectangular -grids, :class:`Meshes ` are used for unstructured collections of polygons, and -:class:`LocStreams ` are used for unstructured collections of individual points. These +:class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, and :class:`~esmpy.api.locstream.LocStream`. :class:`Grids ` are used to represent logically rectangular +grids, :class:`Meshes ` are used for unstructured collections of polygons, and +:class:`LocStreams ` are used for unstructured collections of individual points. These objects are nearly identical counterparts to the objects of the same name in ESMF, with some simplifications for ease of use in the Python environment. @@ -157,9 +157,9 @@ ESMF, with some simplifications for ease of use in the Python environment. Grid ~~~~ -The :class:`~ESMF.api.grid.Grid` is used to represent the geometry and discretization of logically -rectangular physical grids. The :class:`~ESMF.api.grid.Grid` can also hold information that can used in -calculations involving the :class:`~ESMF.api.grid.Grid`, like a mask or the cell areas. Refer to the Grid Class of the +The :class:`~esmpy.api.grid.Grid` is used to represent the geometry and discretization of logically +rectangular physical grids. The :class:`~esmpy.api.grid.Grid` can also hold information that can used in +calculations involving the :class:`~esmpy.api.grid.Grid`, like a mask or the cell areas. Refer to the Grid Class of the `ESMF Reference Manual `_ for more information. ++++++++++ @@ -169,103 +169,103 @@ Staggering Staggering is a finite difference technique in which the values of different physical quantities are placed at different locations within a grid cell. -The ESMF :class:`~ESMF.api.grid.Grid` class supports a variety of stagger locations, including cell +The ESMF :class:`~esmpy.api.grid.Grid` class supports a variety of stagger locations, including cell centers, corners, and edge centers. The default stagger location in ESMF is the -cell center, and cell counts in :class:`~ESMF.api.grid.Grid` are based on this assumption. Combinations +cell center, and cell counts in :class:`~esmpy.api.grid.Grid` are based on this assumption. Combinations of the 2D ESMF stagger locations are sufficient to specify any of the Arakawa staggers. ESMF also supports staggering in 3D and higher dimensions. There are shortcuts for standard staggers, and interfaces through which users can create custom staggers. -As a default the ESMF :class:`~ESMF.api.grid.Grid` class provides symmetric staggering, so that cell +As a default the ESMF :class:`~esmpy.api.grid.Grid` class provides symmetric staggering, so that cell centers are enclosed by cell perimeter (e.g. corner) stagger locations. This means the coordinate arrays for stagger locations other than the center will have an additional element of padding in order to enclose the cell center locations. However, to achieve other types of staggering, the user may alter or eliminate this padding by using the appropriate options when adding coordinates -to a :class:`~ESMF.api.grid.Grid`. +to a :class:`~esmpy.api.grid.Grid`. -:class:`~ESMF.api.grid.Grid` staggers are indicated using -:class:`StaggerLoc`. +:class:`~esmpy.api.grid.Grid` staggers are indicated using +:class:`StaggerLoc`. .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER) + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER) +++++++++++++++++++++ Spherical Coordinates +++++++++++++++++++++ -In the case that the :class:`~ESMF.api.grid.Grid` is on a sphere (coord_sys = :class:`ESMF.api.constants.CoordSys.SPH_DEG` or -:class:`ESMF.api.constants.CoordSys.SPH_RAD`) then the coordinates given in the :class:`~ESMF.api.grid.Grid` are interpreted +In the case that the :class:`~esmpy.api.grid.Grid` is on a sphere (coord_sys = :class:`esmpy.api.constants.CoordSys.SPH_DEG` or +:class:`esmpy.api.constants.CoordSys.SPH_RAD`) then the coordinates given in the :class:`~esmpy.api.grid.Grid` are interpreted as latitude and longitude values. The coordinates can either be in degrees or -radians as indicated by the ``coord_sys`` flag set during :class:`~ESMF.api.grid.Grid` creation. As is +radians as indicated by the ``coord_sys`` flag set during :class:`~esmpy.api.grid.Grid` creation. As is true with many global models, this application currently assumes the latitude and longitude refer to positions on a perfect sphere. -The :class:`~ESMF.api.grid.Grid` coordinate system is represented using -:class:`CoordSys`. +The :class:`~esmpy.api.grid.Grid` coordinate system is represented using +:class:`CoordSys`. .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) +++++++++++ Periodicity +++++++++++ -A periodic connection can be specified when building :class:`Grids ` in spherical +A periodic connection can be specified when building :class:`Grids ` in spherical coordinates. The ``num_peri_dims`` parameter indicates the total number of periodic dimensions and ``periodic_dim`` is used to identify which dimensions should be considered periodic. There must always be at least one non-periodic -dimension. For example, to create a global latitude-longitude :class:`~ESMF.api.grid.Grid` there would +dimension. For example, to create a global latitude-longitude :class:`~esmpy.api.grid.Grid` there would be one periodic dimension, dimension 0 (longitude). .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG, + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG, num_peri_dims=1, periodic_dim=0) +++++++++++++++ Pole Generation +++++++++++++++ -The :class:`~ESMF.api.grid.Grid` can generate an artificial pole by using the ``pole_dim`` parameter. This +The :class:`~esmpy.api.grid.Grid` can generate an artificial pole by using the ``pole_dim`` parameter. This can be helpful for regridding operations to smooth out the interpolated values in the polar region. For the example of creating a global latitude-longitude -:class:`~ESMF.api.grid.Grid`, the pole dimension would be 1 (latitude). +:class:`~esmpy.api.grid.Grid`, the pole dimension would be 1 (latitude). .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG, + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG, num_peri_dims=1, periodic_dim=0, pole_dim=1) +++++++ Masking +++++++ -Masking is the process used to mark parts of a :class:`~ESMF.api.grid.Grid` to be ignored during an -operation. Marking :class:`~ESMF.api.grid.Grid` cells as masked can affect the :class:`~ESMF.api.field.Field` values that are +Masking is the process used to mark parts of a :class:`~esmpy.api.grid.Grid` to be ignored during an +operation. Marking :class:`~esmpy.api.grid.Grid` cells as masked can affect the :class:`~esmpy.api.field.Field` values that are represented by those cells. Masking is specified by assigning an integer value -to a :class:`~ESMF.api.grid.Grid` cell. This allows many different masks to be defined on the same :class:`~ESMF.api.grid.Grid`, -any combination of which may be also activated on the :class:`~ESMF.api.field.Field` by specifying the -corresponding integer values. The activation of :class:`~ESMF.api.field.Field` masks with respect to the -underlying :class:`~ESMF.api.grid.Grid` mask is handled by :class:`~ESMF.api.regrid.Regrid`, and a more +to a :class:`~esmpy.api.grid.Grid` cell. This allows many different masks to be defined on the same :class:`~esmpy.api.grid.Grid`, +any combination of which may be also activated on the :class:`~esmpy.api.field.Field` by specifying the +corresponding integer values. The activation of :class:`~esmpy.api.field.Field` masks with respect to the +underlying :class:`~esmpy.api.grid.Grid` mask is handled by :class:`~esmpy.api.regrid.Regrid`, and a more general discussion of masking is covered in the :ref:`masking ` section. .. code:: In [1]: import numpy as np - ...: import ESMF - ...: grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - ...: coord_sys=ESMF.CoordSys.SPH_DEG, + ...: import esmpy + ...: grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + ...: coord_sys=esmpy.CoordSys.SPH_DEG, ...: num_peri_dims=1, periodic_dim=0, pole_dim=1) ...: - ...: mask = grid.add_item(ESMF.GridItem.MASK, staggerloc=ESMF.StaggerLoc.CENTER) + ...: mask = grid.add_item(esmpy.GridItem.MASK, staggerloc=esmpy.StaggerLoc.CENTER) ...: mask ...: Out[1]: @@ -277,29 +277,29 @@ section. Cell Areas ++++++++++ -:class:`~ESMF.api.grid.Grid` cell areas can be calculated by ESMPy. Space must first be allocated for +:class:`~esmpy.api.grid.Grid` cell areas can be calculated by ESMPy. Space must first be allocated for this calculation by adding an -:class:`~ESMF.api.constants.GridItem.AREA` item to the :class:`~ESMF.api.grid.Grid`. -Then a :class:`~ESMF.api.field.Field` must be created, and the -:class:`~ESMF.api.field.Field.get_area()` function called. +:class:`~esmpy.api.constants.GridItem.AREA` item to the :class:`~esmpy.api.grid.Grid`. +Then a :class:`~esmpy.api.field.Field` must be created, and the +:class:`~esmpy.api.field.Field.get_area()` function called. -.. Note:: The :class:`~ESMF.api.grid.Grid` area calculation assumes the :class:`~ESMF.api.grid.Grid` is a unit sphere. +.. Note:: The :class:`~esmpy.api.grid.Grid` area calculation assumes the :class:`~esmpy.api.grid.Grid` is a unit sphere. -:class:`~ESMF.api.grid.Grid` cell areas may also be set to user-defined values -after the :class:`~ESMF.api.constants.GridItem.AREA` item has -been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. +:class:`~esmpy.api.grid.Grid` cell areas may also be set to user-defined values +after the :class:`~esmpy.api.constants.GridItem.AREA` item has +been allocated and retrieved using :class:`~esmpy.api.grid.Grid.get_item()`. .. code:: - In [1]: grid = ESMF.Grid(np.array([3,4]), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], - ...: coord_sys=ESMF.CoordSys.SPH_DEG, + In [1]: grid = esmpy.Grid(np.array([3,4]), staggerloc=[esmpy.StaggerLoc.CENTER, esmpy.StaggerLoc.CORNER], + ...: coord_sys=esmpy.CoordSys.SPH_DEG, ...: num_peri_dims=1, periodic_dim=0, pole_dim=1) ...: ...: ...: gridLon = grid.get_coords(0) ...: gridLat = grid.get_coords(1) - ...: gridLonCorner = grid.get_coords(0, staggerloc=ESMF.StaggerLoc.CORNER) - ...: gridLatCorner = grid.get_coords(1, staggerloc=ESMF.StaggerLoc.CORNER) + ...: gridLonCorner = grid.get_coords(0, staggerloc=esmpy.StaggerLoc.CORNER) + ...: gridLatCorner = grid.get_coords(1, staggerloc=esmpy.StaggerLoc.CORNER) ...: ...: lon = np.linspace(-120,120,3) ...: lat = np.linspace(-67.5, 67.5,4) @@ -314,7 +314,7 @@ been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. ...: gridLonCorner[:] = lonm_corner ...: gridLatCorner[:] = latm_corner ...: - ...: field = ESMF.Field(grid) + ...: field = esmpy.Field(grid) ...: field.get_area() ...: field.data ...: @@ -327,101 +327,101 @@ been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. Mesh ~~~~ -A :class:`~ESMF.api.mesh.Mesh` is an object for representing unstructured grids. +A :class:`~esmpy.api.mesh.Mesh` is an object for representing unstructured grids. Refer to the Mesh Class of the `ESMF Reference Manual `_ for more information. -A :class:`~ESMF.api.mesh.Mesh` is constructed of *nodes* and *elements*. A node, also known as a vertex -or corner, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a single point. An element, -also known as a cell, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a small +A :class:`~esmpy.api.mesh.Mesh` is constructed of *nodes* and *elements*. A node, also known as a vertex +or corner, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a single point. An element, +also known as a cell, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a small region of space. Elements are described in terms of a connected set of nodes which represent locations along their boundaries. -:class:`~ESMF.api.field.Field` data may be located on either the nodes or elements of a :class:`~ESMF.api.mesh.Mesh`. :class:`Fields ` -created on a :class:`~ESMF.api.mesh.Mesh` can also be used as either the source or destination or both +:class:`~esmpy.api.field.Field` data may be located on either the nodes or elements of a :class:`~esmpy.api.mesh.Mesh`. :class:`Fields ` +created on a :class:`~esmpy.api.mesh.Mesh` can also be used as either the source or destination or both of a regridding operation. -The dimension of a :class:`~ESMF.api.mesh.Mesh` in ESMF is specified with two parameters: the +The dimension of a :class:`~esmpy.api.mesh.Mesh` in ESMF is specified with two parameters: the *parametric* dimension and the *spatial* dimension. -The parametric dimension of a :class:`~ESMF.api.mesh.Mesh` is the dimension of the topology of the :class:`~ESMF.api.mesh.Mesh`. -This can be thought of as the dimension of the elements which make up the :class:`~ESMF.api.mesh.Mesh`. -For example, a :class:`~ESMF.api.mesh.Mesh` composed of triangles would have a parametric dimension of -2, and a :class:`~ESMF.api.mesh.Mesh` composed of tetrahedra would have a parametric dimension of 3. +The parametric dimension of a :class:`~esmpy.api.mesh.Mesh` is the dimension of the topology of the :class:`~esmpy.api.mesh.Mesh`. +This can be thought of as the dimension of the elements which make up the :class:`~esmpy.api.mesh.Mesh`. +For example, a :class:`~esmpy.api.mesh.Mesh` composed of triangles would have a parametric dimension of +2, and a :class:`~esmpy.api.mesh.Mesh` composed of tetrahedra would have a parametric dimension of 3. -The spatial dimension of a :class:`~ESMF.api.mesh.Mesh` is the dimension of the space in which the :class:`~ESMF.api.mesh.Mesh` +The spatial dimension of a :class:`~esmpy.api.mesh.Mesh` is the dimension of the space in which the :class:`~esmpy.api.mesh.Mesh` is embedded. In other words, it is the number of coordinate dimensions needed to -describe the location of the nodes making up the :class:`~ESMF.api.mesh.Mesh`. +describe the location of the nodes making up the :class:`~esmpy.api.mesh.Mesh`. -For example, a :class:`~ESMF.api.mesh.Mesh` constructed of squares on a plane would have a parametric -dimension of 2 and a spatial dimension of 2. If that same :class:`~ESMF.api.mesh.Mesh` were used to -represent the 2D surface of a sphere, then the :class:`~ESMF.api.mesh.Mesh` would still have a +For example, a :class:`~esmpy.api.mesh.Mesh` constructed of squares on a plane would have a parametric +dimension of 2 and a spatial dimension of 2. If that same :class:`~esmpy.api.mesh.Mesh` were used to +represent the 2D surface of a sphere, then the :class:`~esmpy.api.mesh.Mesh` would still have a parametric dimension of 2, but now its spatial dimension would be 3. -Only :class:`Meshes ` whose number of coordinate dimensions (spatial dimension) is 2 or 3 -are supported. The dimension of the elements in a :class:`~ESMF.api.mesh.Mesh` (parametric dimension) must +Only :class:`Meshes ` whose number of coordinate dimensions (spatial dimension) is 2 or 3 +are supported. The dimension of the elements in a :class:`~esmpy.api.mesh.Mesh` (parametric dimension) must be less than or equal to the spatial dimension, but also must be either 2 or 3. -This means that a :class:`~ESMF.api.mesh.Mesh` may be either 2D elements in 2D space, 3D elements in 3D +This means that a :class:`~esmpy.api.mesh.Mesh` may be either 2D elements in 2D space, 3D elements in 3D space, or a manifold constructed of 2D elements embedded in 3D space. For a parametric dimension of 2, the native supported element types are triangles and quadrilaterals. In addition to these, ESMF supports 2D polygons with any number of sides. Internally these are represented as sets of triangles, but to the user should behave like any other element. For a parametric dimension -of 3, the supported element types are tetrahedrons and hexahedrons. The :class:`~ESMF.api.mesh.Mesh` +of 3, the supported element types are tetrahedrons and hexahedrons. The :class:`~esmpy.api.mesh.Mesh` supports any combination of element types within a particular dimension, but -types from different dimensions may not be mixed. For example, a :class:`~ESMF.api.mesh.Mesh` cannot be +types from different dimensions may not be mixed. For example, a :class:`~esmpy.api.mesh.Mesh` cannot be constructed of both quadrilaterals and tetrahedra. +++++++++++++ Mesh Creation +++++++++++++ -To create a :class:`~ESMF.api.mesh.Mesh` we need to set some properties of the :class:`~ESMF.api.mesh.Mesh` as a whole, some -properties of each node in the :class:`~ESMF.api.mesh.Mesh` and then some properties of each element +To create a :class:`~esmpy.api.mesh.Mesh` we need to set some properties of the :class:`~esmpy.api.mesh.Mesh` as a whole, some +properties of each node in the :class:`~esmpy.api.mesh.Mesh` and then some properties of each element which connects the nodes. -For the :class:`~ESMF.api.mesh.Mesh` as a whole we set its parametric dimension and spatial dimension. -A :class:`Mesh's ` parametric dimension can be thought of as the dimension of the elements -which make up the :class:`~ESMF.api.mesh.Mesh`. A :class:`Mesh's ` spatial dimension, on the other hand, is the +For the :class:`~esmpy.api.mesh.Mesh` as a whole we set its parametric dimension and spatial dimension. +A :class:`Mesh's ` parametric dimension can be thought of as the dimension of the elements +which make up the :class:`~esmpy.api.mesh.Mesh`. A :class:`Mesh's ` spatial dimension, on the other hand, is the number of coordinate dimensions needed to describe the location of the nodes -making up the :class:`~ESMF.api.mesh.Mesh`. +making up the :class:`~esmpy.api.mesh.Mesh`. -The structure of the per node and element information used to create a :class:`~ESMF.api.mesh.Mesh` is -influenced by the :class:`~ESMF.api.mesh.Mesh` distribution strategy. The :class:`~ESMF.api.mesh.Mesh` class is distributed by +The structure of the per node and element information used to create a :class:`~esmpy.api.mesh.Mesh` is +influenced by the :class:`~esmpy.api.mesh.Mesh` distribution strategy. The :class:`~esmpy.api.mesh.Mesh` class is distributed by elements. This means that a node must be present on any PET that contains an element associated with that node, but not on any other PET (a node can't be on a PET without an element "home"). Since a node may be used by two or more elements located on different PETs, a node may be duplicated on multiple PETs. When a node is duplicated in this manner, one and only one of the PETs that contain the node must "own" the node. The user sets -this ownership when they define the nodes during :class:`~ESMF.api.mesh.Mesh` -creation. When a :class:`~ESMF.api.field.Field` is created on a -:class:`~ESMF.api.mesh.Mesh` (i.e. on the :class:`~ESMF.api.mesh.Mesh` nodes), -on each PET the :class:`~ESMF.api.field.Field` is only +this ownership when they define the nodes during :class:`~esmpy.api.mesh.Mesh` +creation. When a :class:`~esmpy.api.field.Field` is created on a +:class:`~esmpy.api.mesh.Mesh` (i.e. on the :class:`~esmpy.api.mesh.Mesh` nodes), +on each PET the :class:`~esmpy.api.field.Field` is only created on the nodes which are owned by that PET. This means that the size -of the :class:`~ESMF.api.field.Field` memory on the PET can be smaller than the -number of nodes used to create the :class:`~ESMF.api.mesh.Mesh` on that PET. +of the :class:`~esmpy.api.field.Field` memory on the PET can be smaller than the +number of nodes used to create the :class:`~esmpy.api.mesh.Mesh` on that PET. -Three properties need to be defined for each :class:`~ESMF.api.mesh.Mesh` node: the global id of the node +Three properties need to be defined for each :class:`~esmpy.api.mesh.Mesh` node: the global id of the node (``node_ids``), node coordinates (``node_coords``), and which PET owns the node (``node_owners``). The node id is a unique (across all PETs) integer attached to the particular node. It is used to indicate which nodes are the same when -connecting together pieces of the :class:`~ESMF.api.mesh.Mesh` on different PETs. The node -coordinates indicate the location of a node in space and are used in the :class:`~ESMF.api.regrid.Regrid` +connecting together pieces of the :class:`~esmpy.api.mesh.Mesh` on different PETs. The node +coordinates indicate the location of a node in space and are used in the :class:`~esmpy.api.regrid.Regrid` functionality when interpolating. The node owner indicates which PET is in -charge of the node. This is used when creating a :class:`~ESMF.api.field.Field` on the :class:`~ESMF.api.mesh.Mesh` to indicate -which PET should contain a :class:`~ESMF.api.field.Field` location for the data. +charge of the node. This is used when creating a :class:`~esmpy.api.field.Field` on the :class:`~esmpy.api.mesh.Mesh` to indicate +which PET should contain a :class:`~esmpy.api.field.Field` location for the data. -Three properties need to be defined for each :class:`~ESMF.api.mesh.Mesh` element: the global id of the +Three properties need to be defined for each :class:`~esmpy.api.mesh.Mesh` element: the global id of the element (``element_ids``), the topology type of the element (``element_types``), and which nodes are connected together to form the element (``element_conn``). The element id is a unique (across all PETs) integer attached to the particular element. The element type describes the topology of the element (e.g. a triangle vs. a quadrilateral). The range of choices for the topology of -the elements in a :class:`~ESMF.api.mesh.Mesh` are restricted by the :class:`Mesh's ` parametric dimension (e.g. a -:class:`~ESMF.api.mesh.Mesh` can't contain a 2D element like a triangle, when its parametric dimension +the elements in a :class:`~esmpy.api.mesh.Mesh` are restricted by the :class:`Mesh's ` parametric dimension (e.g. a +:class:`~esmpy.api.mesh.Mesh` can't contain a 2D element like a triangle, when its parametric dimension is 3D), but it can contain any combination of elements appropriate to its dimension. In particular, in 2D ESMF supports two native element types triangle and quadrilateral, but also provides support for polygons with any number of @@ -433,7 +433,7 @@ which nodes are to be connected together to form the element. The number of nodes connected together for each element is implied by the elements topology type (``element_types``). It is IMPORTANT to note, that the entries in this list are NOT the global ids of the nodes, but are indices into the PET local lists -of node info used in the :class:`~ESMF.api.mesh.Mesh` creation. In other words, the element connectivity +of node info used in the :class:`~esmpy.api.mesh.Mesh` creation. In other words, the element connectivity isn't specified in terms of the global list of nodes, but instead is specified in terms of the locally described node info. One other important point about connectivities is that the order of the nodes in the connectivity list of an @@ -441,9 +441,9 @@ element is important. In general, when specifying an element with parametric dimension 2, the nodes should be given in counterclockwise order around the element. -The three step :class:`~ESMF.api.mesh.Mesh` creation process starts with a call to the :class:`~ESMF.api.mesh.Mesh` constructor. -It is then followed by the :class:`~ESMF.api.mesh.Mesh.add_nodes()` call to -specify nodes, and then the :class:`~ESMF.api.mesh.Mesh.add_elements()` call to +The three step :class:`~esmpy.api.mesh.Mesh` creation process starts with a call to the :class:`~esmpy.api.mesh.Mesh` constructor. +It is then followed by the :class:`~esmpy.api.mesh.Mesh.add_nodes()` call to +specify nodes, and then the :class:`~esmpy.api.mesh.Mesh.add_elements()` call to specify elements. .. code:: @@ -466,7 +466,7 @@ specify elements. # Element Ids in centers # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) num_node = 12 num_elem = 5 @@ -488,9 +488,9 @@ specify elements. nodeOwner = np.zeros(num_node) elemId = np.array([1,2,3,4,5]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI, 5, 6]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI, 5, 6]) elemConn=np.array([0,1,4,3, # elem id 1 1,2,4, # elem id 2 @@ -506,24 +506,24 @@ specify elements. Masking +++++++ -There are two types of masking available in :class:`~ESMF.api.mesh.Mesh`: node masking and element +There are two types of masking available in :class:`~esmpy.api.mesh.Mesh`: node masking and element masking. These both work in a similar manner, but vary slightly in the details -of setting the mask information during :class:`~ESMF.api.mesh.Mesh` creation. +of setting the mask information during :class:`~esmpy.api.mesh.Mesh` creation. For node masking, the mask information is set using the ``node_mask`` parameter. -When a :class:`~ESMF.api.regrid.Regrid` object is created the mask values arguments ``src_mask_values`` and +When a :class:`~esmpy.api.regrid.Regrid` object is created the mask values arguments ``src_mask_values`` and ``dst_mask_values`` can then be used to indicate which particular values set in the ``node_mask`` array indicate that the node should be masked. For example, if -``dst_mask_values`` has been set to 1, then any node in the destination :class:`~ESMF.api.mesh.Mesh` whose +``dst_mask_values`` has been set to 1, then any node in the destination :class:`~esmpy.api.mesh.Mesh` whose corresponding ``node_mask`` value is 1 will be masked out (a node with any other value than 1 will not be masked). For element masking, the mask information is set using the ``element_mask`` -parameter when adding elements to the :class:`~ESMF.api.mesh.Mesh`. In a similar manner to node masking, -the mask values parameters to :class:`~ESMF.api.regrid.Regrid`, ``src_mask_values`` and ``dst_mask_values`` +parameter when adding elements to the :class:`~esmpy.api.mesh.Mesh`. In a similar manner to node masking, +the mask values parameters to :class:`~esmpy.api.regrid.Regrid`, ``src_mask_values`` and ``dst_mask_values`` can then be used to indicate which particular values set in the ``element_mask`` array indicate that the element should be masked. For example, if -``dst_mask_values`` has been set to 1, then any element in the destination :class:`~ESMF.api.mesh.Mesh` +``dst_mask_values`` has been set to 1, then any element in the destination :class:`~esmpy.api.mesh.Mesh` whose corresponding ``element_mask`` value is 1 will be masked out (an element with any other value than 1 will not be masked). @@ -531,21 +531,21 @@ with any other value than 1 will not be masked). Areas +++++ -:class:`~ESMF.api.mesh.Mesh` cell areas can be specified using the ``element_areas`` parameter to -:class:`~ESMF.api.mesh.Mesh.add_elements()`. +:class:`~esmpy.api.mesh.Mesh` cell areas can be specified using the ``element_areas`` parameter to +:class:`~esmpy.api.mesh.Mesh.add_elements()`. If cell areas are not specified by the user they can be calculated by ESMPy -using :class:`~ESMF.api.field.Field.get_area()`. +using :class:`~esmpy.api.field.Field.get_area()`. ~~~~~~~~~ LocStream ~~~~~~~~~ -A :class:`~ESMF.api.locstream.LocStream` can be used to represent the locations of a set of -data points. For example, in the data assimilation world, :class:`LocStreams ` can be used +A :class:`~esmpy.api.locstream.LocStream` can be used to represent the locations of a set of +data points. For example, in the data assimilation world, :class:`LocStreams ` can be used to represent a set of observations. The values of the data points are stored -within a :class:`~ESMF.api.field.Field` created using the :class:`~ESMF.api.locstream.LocStream`. +within a :class:`~esmpy.api.field.Field` created using the :class:`~esmpy.api.locstream.LocStream`. Refer to the LocStream Class of the `ESMF Reference Manual `_ for more information. @@ -556,26 +556,26 @@ called *keys*. A key is essentially a list of point descriptors, one for each da point. They may hold other information besides the coordinates - a mask, for example. They may also hold a second set of coordinates. Keys are referenced by name. Each key must contain the same number of elements as there are data points -in the :class:`~ESMF.api.locstream.LocStream`. While there is no assumption in the ordering of the points, +in the :class:`~esmpy.api.locstream.LocStream`. While there is no assumption in the ordering of the points, the order chosen must be maintained in each of the keys. -A :class:`~ESMF.api.locstream.LocStream` can be very large. Data assimilation systems might use :class:`LocStreams ` -with up to :math:`10^8` observations, so efficiency is critical. :class:`LocStreams ` can be +A :class:`~esmpy.api.locstream.LocStream` can be very large. Data assimilation systems might use :class:`LocStreams ` +with up to :math:`10^8` observations, so efficiency is critical. :class:`LocStreams ` can be created from file. -A :class:`~ESMF.api.locstream.LocStream` is similar to a :class:`~ESMF.api.mesh.Mesh` in that both are collections of irregularly -positioned points. However, the two structures differ because a :class:`~ESMF.api.mesh.Mesh` also has +A :class:`~esmpy.api.locstream.LocStream` is similar to a :class:`~esmpy.api.mesh.Mesh` in that both are collections of irregularly +positioned points. However, the two structures differ because a :class:`~esmpy.api.mesh.Mesh` also has connectivity: each data point represents either a center or corner of a cell. -There is no requirement that the points in a :class:`~ESMF.api.locstream.LocStream` have connectivity, in +There is no requirement that the points in a :class:`~esmpy.api.locstream.LocStream` have connectivity, in fact there is no requirement that any two points have any particular spatial relationship at all. .. code:: - locstream = ESMF.LocStream(16, coord_sys=coord_sys) + locstream = esmpy.LocStream(16, coord_sys=coord_sys) deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180 locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad] @@ -592,17 +592,17 @@ Create a Grid or Mesh from File File Formats ~~~~~~~~~~~~ -ESMPy can create :class:`~ESMF.api.grid.Grid` or :class:`~ESMF.api.mesh.Mesh` objects from NetCDF files in a variety -of formats. A :class:`~ESMF.api.mesh.Mesh` can be created from files in :class:`~ESMF.api.constants.FileFormat.SCRIP`, :class:`~ESMF.api.constants.FileFormat.ESMFMESH`, and :class:`~ESMF.api.constants.FileFormat.UGRID` -formats. :class:`~ESMF.api.grid.Grid` files can be in :class:`~ESMF.api.constants.FileFormat.SCRIP` and :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` format. +ESMPy can create :class:`~esmpy.api.grid.Grid` or :class:`~esmpy.api.mesh.Mesh` objects from NetCDF files in a variety +of formats. A :class:`~esmpy.api.mesh.Mesh` can be created from files in :class:`~esmpy.api.constants.FileFormat.SCRIP`, :class:`~esmpy.api.constants.FileFormat.ESMFMESH`, and :class:`~esmpy.api.constants.FileFormat.UGRID` +formats. :class:`~esmpy.api.grid.Grid` files can be in :class:`~esmpy.api.constants.FileFormat.SCRIP` and :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` format. +++++ SCRIP +++++ .. _scrip: -This file format is used by the :class:`~ESMF.api.constants.FileFormat.SCRIP` :cite:`ref:SCRIP`, package, grid files that -work with that package should also work here. :class:`~ESMF.api.constants.FileFormat.SCRIP` format files are +This file format is used by the :class:`~esmpy.api.constants.FileFormat.SCRIP` :cite:`ref:SCRIP`, package, grid files that +work with that package should also work here. :class:`~esmpy.api.constants.FileFormat.SCRIP` format files are capable of storing either 2D logically rectangular grids or 2D unstructured grids. More information can be found in the `ESMF Reference Manual `_. @@ -612,10 +612,10 @@ ESMFMESH ++++++++ .. _esmfmesh: -ESMF has a custom unstructured grid file format for describing :class:`Meshes `. -This format is more compatible than the :class:`~ESMF.api.constants.FileFormat.SCRIP` format with the methods -used to create a :class:`~ESMF.api.mesh.Mesh` object, so less conversion needs to be done to -create a :class:`~ESMF.api.mesh.Mesh`. The :class:`~ESMF.api.constants.FileFormat.ESMFMESH` format is thus more efficient than :class:`~ESMF.api.constants.FileFormat.SCRIP` when +ESMF has a custom unstructured grid file format for describing :class:`Meshes `. +This format is more compatible than the :class:`~esmpy.api.constants.FileFormat.SCRIP` format with the methods +used to create a :class:`~esmpy.api.mesh.Mesh` object, so less conversion needs to be done to +create a :class:`~esmpy.api.mesh.Mesh`. The :class:`~esmpy.api.constants.FileFormat.ESMFMESH` format is thus more efficient than :class:`~esmpy.api.constants.FileFormat.SCRIP` when used with ESMPy. More information can be found in the `ESMF Reference Manual `_. @@ -624,9 +624,9 @@ GRIDSPEC ++++++++ .. _gridspec: -:class:`~ESMF.api.constants.FileFormat.GRIDSPEC` is an extension to the Climate and Forecast (CF) metadata +:class:`~esmpy.api.constants.FileFormat.GRIDSPEC` is an extension to the Climate and Forecast (CF) metadata conventions for the representation of gridded data for Earth System -Models. ESMPy supports NetCDF files that follow the CF :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` +Models. ESMPy supports NetCDF files that follow the CF :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` convention to support logically rectangular lat/lon grids. More information can be found in the `ESMF Reference Manual `_. @@ -636,9 +636,9 @@ UGRID +++++ .. _ugrid: -:class:`~ESMF.api.constants.FileFormat.UGRID` is an extension to the CF metadata +:class:`~esmpy.api.constants.FileFormat.UGRID` is an extension to the CF metadata conventions for the unstructured grid data model. ESMPy support -NetCDF files that follow the CF :class:`~ESMF.api.constants.FileFormat.UGRID` convention for unstructured grids. +NetCDF files that follow the CF :class:`~esmpy.api.constants.FileFormat.UGRID` convention for unstructured grids. More information can be found in the `ESMF Reference Manual `_. @@ -646,18 +646,18 @@ More information can be found in the Meshes from File ~~~~~~~~~~~~~~~~ -When creating a :class:`~ESMF.api.mesh.Mesh` from a :class:`~ESMF.api.constants.FileFormat.SCRIP` format file, there are a number of -options to control the output :class:`~ESMF.api.mesh.Mesh`. The data is located at the center -of the grid cell in a :class:`~ESMF.api.constants.FileFormat.SCRIP` grid. Therefore, when the :class:`~ESMF.api.mesh.Mesh` will be +When creating a :class:`~esmpy.api.mesh.Mesh` from a :class:`~esmpy.api.constants.FileFormat.SCRIP` format file, there are a number of +options to control the output :class:`~esmpy.api.mesh.Mesh`. The data is located at the center +of the grid cell in a :class:`~esmpy.api.constants.FileFormat.SCRIP` grid. Therefore, when the :class:`~esmpy.api.mesh.Mesh` will be part of a conservative regridding operation, the ``convert_to_dual`` flag must be set to True to properly generate coordinates at the the cell corners. -A :class:`~ESMF.api.mesh.Mesh` may also be created with boolean flags to specify whether or not to -add an area property to the :class:`~ESMF.api.mesh.Mesh` ``add_user_area``, or to add a mask +A :class:`~esmpy.api.mesh.Mesh` may also be created with boolean flags to specify whether or not to +add an area property to the :class:`~esmpy.api.mesh.Mesh` ``add_user_area``, or to add a mask ``add_mask`` held by the NetCDF variable indicated in the optional argument, -``varname``. These argument are only valid for :class:`~ESMF.api.constants.FileFormat.UGRID` formatted files. -The mask generated for a :class:`~ESMF.api.mesh.Mesh` created from file will +``varname``. These argument are only valid for :class:`~esmpy.api.constants.FileFormat.UGRID` formatted files. +The mask generated for a :class:`~esmpy.api.mesh.Mesh` created from file will have 0 for the masked values and 1 for the unmasked values. ~~~~~~~~~~~~~~~ @@ -665,22 +665,22 @@ Grids from File ~~~~~~~~~~~~~~~ A number of optional boolean arguments are also supported to create a -structured :class:`~ESMF.api.grid.Grid` from a file. These include ``is_sphere`` to indicate whether +structured :class:`~esmpy.api.grid.Grid` from a file. These include ``is_sphere`` to indicate whether the grid is spherical or regional, ``add_corner_stagger`` to add the corner -stagger information to the :class:`~ESMF.api.grid.Grid` for conservative regridding, and +stagger information to the :class:`~esmpy.api.grid.Grid` for conservative regridding, and ``add_user_area`` to specify whether to read in the cell area from the NetCDF file or to calculate them. -For :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` formated files +For :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` formated files there is the ``add_mask`` optional argument to add a mask held by the NetCDF variable indicated in optional argument, ``varname``, and the ``coord_names`` argument to specify the longitude -and latitude variable names in a :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` file containing multiple sets of +and latitude variable names in a :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` file containing multiple sets of coordinates. -For :class:`~ESMF.api.constants.FileFormat.SCRIP` formated files the integer array ``grid_imask`` is used to mask out grid cells which should not participate in the regridding. +For :class:`~esmpy.api.constants.FileFormat.SCRIP` formated files the integer array ``grid_imask`` is used to mask out grid cells which should not participate in the regridding. -The mask generated for a :class:`~ESMF.api.grid.Grid` created from +The mask generated for a :class:`~esmpy.api.grid.Grid` created from file (any format) will have 0 for the masked values and 1 for the unmasked values. @@ -694,20 +694,20 @@ More information can be found on these options in the `ESMF Reference Manual `_. -====================================================== =============================================== -Class Description -====================================================== =============================================== -:class:`~ESMF.api.constants.RegridMethod.BILINEAR` Linear regridding in two dimensions -:class:`~ESMF.api.constants.RegridMethod.PATCH` Higher-order least squares method -:class:`~ESMF.api.constants.RegridMethod.NEAREST_STOD` Nearest source point used for each destination -:class:`~ESMF.api.constants.RegridMethod.NEAREST_DTOS` Nearest destination point used for each source -:class:`~ESMF.api.constants.RegridMethod.CONSERVE` First-order conservative -:class:`~ESMF.api.constants.RegridMethod.CONSERVE_2ND` Second-order conservative -:class:`~ESMF.api.constants.NormType` Normalization options for integral conservation -:class:`~ESMF.api.constants.LineType` Line types for spherical and Cartesian space -:class:`~ESMF.api.constants.UnmappedAction` Unmapped destination point handling options -:class:`~ESMF.api.constants.CoordSys` Spherical grids and pole handling -====================================================== =============================================== +======================================================= =============================================== +Class Description +======================================================= =============================================== +:class:`~esmpy.api.constants.RegridMethod.BILINEAR` Linear regridding in two dimensions +:class:`~esmpy.api.constants.RegridMethod.PATCH` Higher-order least squares method +:class:`~esmpy.api.constants.RegridMethod.NEAREST_STOD` Nearest source point used for each destination +:class:`~esmpy.api.constants.RegridMethod.NEAREST_DTOS` Nearest destination point used for each source +:class:`~esmpy.api.constants.RegridMethod.CONSERVE` First-order conservative +:class:`~esmpy.api.constants.RegridMethod.CONSERVE_2ND` Second-order conservative +:class:`~esmpy.api.constants.NormType` Normalization options for integral conservation +:class:`~esmpy.api.constants.LineType` Line types for spherical and Cartesian space +:class:`~esmpy.api.constants.UnmappedAction` Unmapped destination point handling options +:class:`~esmpy.api.constants.CoordSys` Spherical grids and pole handling +======================================================= =============================================== ~~~~~~~~~~~~~~~~~~ Great Circle Cells @@ -737,21 +737,21 @@ Masking ------- .. _masking: -Masking is the process whereby parts of a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` can be marked to be ignored -during an operation, such as when they are used in regridding. Masking can be used on a :class:`~ESMF.api.field.Field` +Masking is the process whereby parts of a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` can be marked to be ignored +during an operation, such as when they are used in regridding. Masking can be used on a :class:`~esmpy.api.field.Field` created from a regridding source to indicate that certain portions should not be used to generate regridded data. This is useful, for example, if a portion of the source contains unusable values. -Masking can also be used on a :class:`~ESMF.api.field.Field` created from a regridding destination to indicate that a certain +Masking can also be used on a :class:`~esmpy.api.field.Field` created from a regridding destination to indicate that a certain portion should not receive regridded data. This is useful, for example, when part of the destination isn't being used (e.g. the land portion of an ocean grid). -The user may mask out points in the source :class:`~ESMF.api.field.Field` or destination :class:`~ESMF.api.field.Field` or both. To do masking the user -sets mask information in the :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or :class:`~ESMF.api.locstream.LocStream` upon -which the :class:`Fields ` passed into the :class:`~ESMF.api.regrid.Regrid` call are built. The ``src_mask_values`` and +The user may mask out points in the source :class:`~esmpy.api.field.Field` or destination :class:`~esmpy.api.field.Field` or both. To do masking the user +sets mask information in the :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or :class:`~esmpy.api.locstream.LocStream` upon +which the :class:`Fields ` passed into the :class:`~esmpy.api.regrid.Regrid` call are built. The ``src_mask_values`` and ``dst_mask_values`` arguments to that call can then be used to specify which values in that mask information indicate that a location should be masked out. For example, if ``dst_mask_values`` is set to [1,2], then any -location that has a value of 1 or 2 in the mask information of the :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` upon which -the destination :class:`~ESMF.api.field.Field` is built will be masked out. +location that has a value of 1 or 2 in the mask information of the :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` upon which +the destination :class:`~esmpy.api.field.Field` is built will be masked out. Masking behavior differs slightly between regridding methods. For non-conservative regridding methods (e.g. bilinear or high-order patch), masking is done on points. For these methods, masking a destination @@ -763,28 +763,29 @@ Masking a destination cell means that the cell won't participate in regridding. Similarly, masking a source cell means that the cell won't participate in regridding. For any type of interpolation method (conservative or non-conservative) the masking is set on the location upon which the -:class:`Fields ` passed into the regridding call are built. -For example, if :class:`Fields ` built on -:class:`StaggerLoc.CENTER ` are passed into -:class:`~ESMF.api.regrid.Regrid` -then the masking should also be set on :class:`StaggerLoc.CENTER `. - -The mask generated for a :class:`~ESMF.api.grid.Grid`, -:class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` created +:class:`Fields ` passed into the regridding call are built. +For example, if :class:`Fields ` built on +:class:`StaggerLoc.CENTER ` are passed into +:class:`~esmpy.api.regrid.Regrid` +then the masking should also be set on :class:`StaggerLoc.CENTER `. + +The mask generated for a :class:`~esmpy.api.grid.Grid`, +:class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` created from file will have 0 for the masked values and 1 for the unmasked values. -.. Note:: The :class:`Region.SELECT ` flag to the -``zero_region`` parameter of :class:`~ESMF.api.regrid.Regrid` can be used to -maintain :class:`Fields ` values on locations that do not +.. Note:: The :class:`Region.SELECT ` flag to the +``zero_region`` parameter of :class:`~esmpy.api.regrid.Regrid` can be used to +maintain :class:`Fields ` values on locations that do not participate in the regridding operation. This is useful when setting an uninitialized value to help identify masked locations within the -:class:`Fields ` data. +:class:`Fields ` data. + -------------------------- Numpy Slicing and Indexing -------------------------- -Numpy arrays are used to represent :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` and :class:`~ESMF.api.locstream.LocStream` coordinates and :class:`~ESMF.api.field.Field` data, +Numpy arrays are used to represent :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` and :class:`~esmpy.api.locstream.LocStream` coordinates and :class:`~esmpy.api.field.Field` data, among other things. Standard numpy conventions for array indexing and slicing can be expected. There are some exceptions when it comes to fancy indexing, index arrays, and multi-dimensional slicing. Significant effort has @@ -795,9 +796,9 @@ It is very important to remember that all indexing and slicing operations apply **ONLY** to the ESMPy level objects, and these operations do not propagate down to the lower-level Fortran- and C-based representations of the ESMF objects. One example of where this could come up is when passing -a :class:`~ESMF.api.field.Field` slice into regridding. The entire original :class:`~ESMF.api.field.Field` will still be run +a :class:`~esmpy.api.field.Field` slice into regridding. The entire original :class:`~esmpy.api.field.Field` will still be run through the ESMF regridding engine, and only the appropriate portion of -the :class:`~ESMF.api.field.Field` slice will be updated with the regridded values. +the :class:`~esmpy.api.field.Field` slice will be updated with the regridded values. ~~~~~~~~~~~~~~~~~~ Dimension Ordering @@ -815,9 +816,9 @@ Dimension Ordering .. code:: In [1]: import numpy as np - ...: import ESMF + ...: import esmpy ...: - ...: grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER) + ...: grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER) ...: ...: gridLon = grid.get_coords(0) ...: gridLat = grid.get_coords(1) @@ -831,7 +832,7 @@ Dimension Ordering ...: gridLat[:] = latm ...: - In [2]: grid.coords[ESMF.StaggerLoc.CENTER][0].shape + In [2]: grid.coords[esmpy.StaggerLoc.CENTER][0].shape Out[2]: (3, 4) In [3]: lon.shape @@ -840,19 +841,19 @@ Dimension Ordering In [4]: lat.shape Out[4]: (4,) - In [5]: grid.coords[ESMF.StaggerLoc.CENTER][0] + In [5]: grid.coords[esmpy.StaggerLoc.CENTER][0] Out[5]: array([[-120., -120., -120., -120.], [ 0., 0., 0., 0.], [ 120., 120., 120., 120.]]) - In [6]: grid.coords[ESMF.StaggerLoc.CENTER][1] + In [6]: grid.coords[esmpy.StaggerLoc.CENTER][1] Out[6]: array([[-67.5, -22.5, 22.5, 67.5], [-67.5, -22.5, 22.5, 67.5], [-67.5, -22.5, 22.5, 67.5]]) - In [7]: field = ESMF.Field(grid, ndbounds=[10]) # create a Field with a time dimension + In [7]: field = esmpy.Field(grid, ndbounds=[10]) # create a Field with a time dimension In [8]: field.data.shape Out[8]: (3, 4, 10) @@ -870,15 +871,15 @@ environment to be utilized by the ESMPy user with little use of specialized parallel programming techniques. ESMPy objects will be distributed across the available computing resources with -no additional parameters required. The :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, :class:`~ESMF.api.locstream.LocStream`, and :class:`~ESMF.api.field.Field` classes +no additional parameters required. The :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, :class:`~esmpy.api.locstream.LocStream`, and :class:`~esmpy.api.field.Field` classes will all be transparently "parallelized" with no need for user calls to a -message passing interface. Likewise, the :class:`~ESMF.api.regrid.Regrid` class will compute and apply +message passing interface. Likewise, the :class:`~esmpy.api.regrid.Regrid` class will compute and apply the interpolation weights using all available computing resources with no need for user intervention. -However, it is useful to remember that resulting :class:`~ESMF.api.field.Field` values will only be +However, it is useful to remember that resulting :class:`~esmpy.api.field.Field` values will only be accessible on certain PETs. The mpi4py package may be necessary for post -processing tasks that require access to global :class:`~ESMF.api.field.Field` values. +processing tasks that require access to global :class:`~esmpy.api.field.Field` values. ~~~~~~~~~~~~~~~~~~~~ mpirun vs. MPI.Spawn diff --git a/src/addon/ESMPy/doc/conf.py b/src/addon/ESMPy/doc/conf.py index f14df17791..3d482edae5 100644 --- a/src/addon/ESMPy/doc/conf.py +++ b/src/addon/ESMPy/doc/conf.py @@ -18,7 +18,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('../src')) -import ESMF +import esmpy # -- General configuration ----------------------------------------------------- @@ -58,7 +58,7 @@ # built documents. # # The full version, including alpha/beta/rc tags. -release = ESMF.__release__ +release = esmpy.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/addon/ESMPy/doc/examples.rst b/src/addon/ESMPy/doc/examples.rst index 4363274b6a..06e8c522ec 100644 --- a/src/addon/ESMPy/doc/examples.rst +++ b/src/addon/ESMPy/doc/examples.rst @@ -13,57 +13,57 @@ Regridding Helper Functions --------------------------- The following code snippets demonstrate how to build all of the pieces -necessary to regrid data between :class:`Fields ` built on -:class:`Grids `, :class:`Meshes ` -and :class:`LocStreams `. +necessary to regrid data between :class:`Fields ` built on +:class:`Grids `, :class:`Meshes ` +and :class:`LocStreams `. ~~~~~~~~~~~~~~~~ LocStream Create ~~~~~~~~~~~~~~~~ -.. literalinclude:: ../src/ESMF/util/locstream_utilities.py +.. literalinclude:: ../src/esmpy/util/locstream_utilities.py :pyobject: create_locstream_spherical_16 ~~~~~~~~~~~~~~~~~~~~~~~~~ LocStream Create Parallel ~~~~~~~~~~~~~~~~~~~~~~~~~ -.. literalinclude:: ../src/ESMF/util/locstream_utilities.py +.. literalinclude:: ../src/esmpy/util/locstream_utilities.py :pyobject: create_locstream_spherical_16_parallel ~~~~~~~~~~~~~~~~ Create a 2D Grid ~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates ~~~~~~~~~~~~~~~~ Create a 3D Grid ~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates_3d ~~~~~~~~~~~~~~~~~~~~~~ Create a Periodic Grid ~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates_periodic ~~~~~~~~~~~~~~~~~~~~~~~ Create a 5 Element Mesh ~~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/mesh_utilities.py + .. literalinclude:: ../src/esmpy/util/mesh_utilities.py :pyobject: mesh_create_5 ~~~~~~~~~~~~~~ Create a Field ~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/test/test_api/test_field.py + .. literalinclude:: ../src/esmpy/test/test_api/test_field.py :pyobject: TestField.create_field @@ -71,7 +71,7 @@ Create a Field Initialize an Analytic Field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: initialize_field_grid_periodic @@ -79,7 +79,7 @@ Initialize an Analytic Field Run ESMPy Regridding ~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/test/test_api/test_regrid.py + .. literalinclude:: ../src/esmpy/test/test_api/test_regrid.py :pyobject: TestRegrid.run_regridding @@ -87,7 +87,7 @@ Run ESMPy Regridding Compute Field Mass ~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: compute_mass_grid @@ -96,9 +96,9 @@ Regridding ---------- The following stand alone scripts demonstrate how to use regridding between -:class:`Fields ` built on -:class:`Grids `, :class:`Meshes ` -and :class:`LocStreams `. These scripts +:class:`Fields ` built on +:class:`Grids `, :class:`Meshes ` +and :class:`LocStreams `. These scripts can be run in serial or parallel with no modification. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/addon/ESMPy/doc/field.rst b/src/addon/ESMPy/doc/field.rst index 6b1f42fc60..f1644ce199 100644 --- a/src/addon/ESMPy/doc/field.rst +++ b/src/addon/ESMPy/doc/field.rst @@ -2,7 +2,7 @@ Field ~~~~~ -.. autoclass:: ESMF.api.field.Field +.. autoclass:: esmpy.api.field.Field :members: copy, destroy, get_area, read, data, grid, lower_bounds, name, ndbounds, rank, staggerloc, type, upper_bounds, xd diff --git a/src/addon/ESMPy/doc/grid.rst b/src/addon/ESMPy/doc/grid.rst index f6f0b4249f..e399592494 100644 --- a/src/addon/ESMPy/doc/grid.rst +++ b/src/addon/ESMPy/doc/grid.rst @@ -2,7 +2,7 @@ Grid ~~~~ -.. autoclass:: ESMF.api.grid.Grid +.. autoclass:: esmpy.api.grid.Grid :members: add_coords, add_item, copy, destroy, get_coords, get_item, area, areatype, coords, coord_sys, has_corners, lower_bounds, mask, max_index, num_peri_dims, periodic_dim, pole_dim, diff --git a/src/addon/ESMPy/doc/install.rst b/src/addon/ESMPy/doc/install.rst index 7c767bcccd..fa514d782f 100644 --- a/src/addon/ESMPy/doc/install.rst +++ b/src/addon/ESMPy/doc/install.rst @@ -9,15 +9,15 @@ Requirements The following packages are *required* to work with ESMPy: * `ESMF installation `_ -* `python `_ +* `python `_, minimum version 3.7 * `numpy `_ The following packages are *optional*: -* ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file +* ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file - NetCDF must be built as a shared library for ESMPy installation to succeed * `mpi4py `_- python bindings to MPI, needed to run some of the parallel regridding examples -* `nose `_ - for nose testing +* `pytest `_ - for testing ---------------- Getting the code @@ -27,7 +27,7 @@ The ESMPy source code can be downloaded from the `ESMF git repository `_. The `ESMF User's Guide `_ -contains information on building and installing ESMF. +contains information on building and installing esmpy. The `ESMF Reference Manual `_ contains information on the architecture of ESMF, example code, and details of the API (Application Programming @@ -59,40 +59,24 @@ Development versions can be found in the ``esmpy_dev`` channel: Installing ESMPy from Source ---------------------------- -When installing from source, ESMPy requires a pointer to a file named esmf.mk -that is generated during an ESMF installation. The path of this file is: +When installing from source, ESMPy uses `pip `_ +to build and install the package. This requires setting an environment variable +pointing to a file named esmf.mk that is generated during an ESMF installation. +The path of this file is: .. code:: /lib/libO>//esmf.mk -If the ``ESMFMKFILE`` flag is set when building ESMPy then it will not need to be -referenced again. If not, an environment variable of the same name must be set -with the path to the esmf.mk file every time a new shell is initiated. - -ESMPy can be installed in a custom location using the -``--prefix``, ``--home``, or ``--install-base`` flags to the install command. If this -is done, then this location needs to be added to the ``PYTHONPATH`` environment -variable every time a new shell is initiated. If a -custom install location is not specified, ESMPy will be installed in the -standard Python package installation directory on that particular machine. +If ``ESMFMKFILE`` is set when building ESMPy then it will not need to be +referenced again. An installation of ESMPy in the default location for Python packages can be done with the following command issued from the top level ESMPy directory: .. code:: - python setup.py build --ESMFMKFILE=/esmf.mk install - -- custom install location: - -.. code:: - - python setup.py build --ESMFMKFILE=/esmf.mk - - python setup.py install --prefix= - - setenv PYTHONPATH /lib/\*/site_packages + python3 -m pip install . Please contact esmf_support@ucar.edu with any questions. @@ -104,47 +88,41 @@ To use ESMPy in an external program, import it with: .. code:: - import ESMF + import esmpy ---------- Validation ---------- -The ESMPy testing is done with the nose package, both in serial and -parallel. The nose commands are wrapped in the following ESMPy targets: +The ESMPy testing is done with the pytest package, both in serial and +parallel. Basic unit tests can be run with the following command: .. code:: - python setup.py test + python3 -m pytest + +There are a few other pytest targets available for a wider range of testing if +greater test coverage is desired: - python setup.py test_examples +.. code:: - python setup.py test_regrid_from_file + make test_unit - python setup.py test_parallel + make test_examples - python setup.py test_examples_parallel + make test_unit_parallel - python setup.py test_regrid_from_file_parallel + make test_examples_parallel + + make test_regrid_from_file .. Note:: - The ``regrid_from_file`` tests can take up a lot of memory and bandwidth. - The ``test_regrid_from_file_dryrun`` command will simply download the test - files without actually running them (allowing the stress on the machine to - be applied to bandwidth first, and then memory). - -Alternatively, individual tests can be run with nose using the following format: - -.. code:: - - nosetests : - -e.g. - -.. code:: - - nosetests src/ESMF/test/test_api/test_regrid.py:TestRegrid.test_field_regrid + The ``regrid_from_file`` and ``example`` tests can take up a lot of memory + and bandwidth. The ``download_regrid_from_file`` and ``download_examples`` + commands will simply download the test files without actually running them + (allowing the stress on the machine to be applied to bandwidth first, and + then memory). ----------- Limitations @@ -157,20 +135,18 @@ to ESMF offline and integrated regridding capabilities. - ESMPy cannot use an ESMF installation that is built with external LAPACK support. - Coordinates cannot be retrieved from the elements of a - :class:`~ESMF.api.mesh.Mesh`. This can affect the ability to set - :class:`~ESMF.api.field.Field` values on a source :class:`~ESMF.api.mesh.Mesh` + :class:`~esmpy.api.mesh.Mesh`. This can affect the ability to set + :class:`~esmpy.api.field.Field` values on a source :class:`~esmpy.api.mesh.Mesh` created from file when using conservative regridding. -- Multi-tile :class:`~ESMF.api.grid.Grid` support is limited to cubed-sphere +- Multi-tile :class:`~esmpy.api.grid.Grid` support is limited to cubed-sphere grids created on 6 processors. A cubed-sphere grid can be created on any number of processors, but only when it is created on 6 processors will the coordinates be retrievable for the entire object. A - :class:`~ESMF.api.field.Field` created from a cubed-sphere - :class:`~ESMF.api.grid.Grid` cannot be written to file in parallel. -- There is no ``FieldBundle`` class, only single :class:`Fields `. + :class:`~esmpy.api.field.Field` created from a cubed-sphere + :class:`~esmpy.api.grid.Grid` cannot be written to file in parallel. +- There is no ``FieldBundle`` class, only single :class:`Fields `. Testing related: - Nightly regression testing is limited to a small subset of the ESMF test platforms, including Darwin and Linux running gfortran with openMPI. - - diff --git a/src/addon/ESMPy/doc/intro.rst b/src/addon/ESMPy/doc/intro.rst index dd618cfc8c..ce4ee2b2ca 100644 --- a/src/addon/ESMPy/doc/intro.rst +++ b/src/addon/ESMPy/doc/intro.rst @@ -2,7 +2,7 @@ Overview -------- -.. automodule:: ESMF +.. automodule:: esmpy --------------- Important Links @@ -28,4 +28,3 @@ Information on these can be found in the `_. Please contact esmf_support@ucar.edu with any questions or problems. - diff --git a/src/addon/ESMPy/doc/locstream.rst b/src/addon/ESMPy/doc/locstream.rst index 1a0f414a12..79a784a206 100644 --- a/src/addon/ESMPy/doc/locstream.rst +++ b/src/addon/ESMPy/doc/locstream.rst @@ -2,5 +2,5 @@ LocStream ~~~~~~~~~ -.. autoclass:: ESMF.api.locstream.LocStream +.. autoclass:: esmpy.api.locstream.LocStream :members: copy, destroy, lower_bounds, name, rank, size, upper_bounds diff --git a/src/addon/ESMPy/doc/manager.rst b/src/addon/ESMPy/doc/manager.rst index fc28fd9656..5b3fa31648 100644 --- a/src/addon/ESMPy/doc/manager.rst +++ b/src/addon/ESMPy/doc/manager.rst @@ -2,5 +2,5 @@ Manager ~~~~~~~ -.. autoclass:: ESMF.api.esmpymanager.Manager +.. autoclass:: esmpy.api.esmpymanager.Manager :members: local_pet, moab, pet_count, barrier, set_moab \ No newline at end of file diff --git a/src/addon/ESMPy/doc/mesh.rst b/src/addon/ESMPy/doc/mesh.rst index 28b6a4f546..7c2b38399e 100644 --- a/src/addon/ESMPy/doc/mesh.rst +++ b/src/addon/ESMPy/doc/mesh.rst @@ -2,6 +2,6 @@ Mesh ~~~~ -.. autoclass:: ESMF.api.mesh.Mesh +.. autoclass:: esmpy.api.mesh.Mesh :members: copy, destroy, add_elements, add_nodes, free_memory, get_coords, area, coords, coord_sys, mask, rank, size, size_owned \ No newline at end of file diff --git a/src/addon/ESMPy/doc/regrid.rst b/src/addon/ESMPy/doc/regrid.rst index 9fe086690f..f647deb5cf 100644 --- a/src/addon/ESMPy/doc/regrid.rst +++ b/src/addon/ESMPy/doc/regrid.rst @@ -2,5 +2,5 @@ Regrid ~~~~~~ -.. autoclass:: ESMF.api.regrid.Regrid +.. autoclass:: esmpy.api.regrid.Regrid :members: copy, destroy, __call__, get_factors, get_weights_dict diff --git a/src/addon/ESMPy/doc/regridfromfile.rst b/src/addon/ESMPy/doc/regridfromfile.rst index 66d9ea9705..ed5af263f9 100644 --- a/src/addon/ESMPy/doc/regridfromfile.rst +++ b/src/addon/ESMPy/doc/regridfromfile.rst @@ -2,5 +2,5 @@ RegridFromFile ~~~~~~~~~~~~~~ -.. autoclass:: ESMF.api.regrid.RegridFromFile +.. autoclass:: esmpy.api.regrid.RegridFromFile :members: copy, destroy, __call__ diff --git a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py index c5cc0a3672..ee54fa2b0b 100644 --- a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py +++ b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py @@ -7,46 +7,47 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging when debug=True -mg = ESMF.Manager(debug=False) +mg = esmpy.Manager(debug=False) -# if ESMF.pet_count() != 6: +# if esmpy.pet_count() != 6: # print ("ESMPy cubed sphere regridding example requires 6 processors") # import sys; sys.exit(0) grid1 = "examples/data/ll1deg_grid.nc" # Create a cubed sphere grid with 20 elements per tile -srcgrid = ESMF.Grid(tilesize=20, name="cubed_sphere") +regDecompPTile = numpy.array([[2,2,1,1,1,1],[2,2,2,2,2,2]], dtype=numpy.int32) +srcgrid = esmpy.Grid(tilesize=20, regDecompPTile = regDecompPTile, name="cubed_sphere") # create an regular lat lon grid from file -dstgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(srcgrid, name='srcfield', staggerloc=ESMF.StaggerLoc.CENTER) -srcfracfield = ESMF.Field(srcgrid, name='srcfracfield', staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name='srcfield', staggerloc=esmpy.StaggerLoc.CENTER) +srcfracfield = esmpy.Field(srcgrid, name='srcfracfield', staggerloc=esmpy.StaggerLoc.CENTER) # create a field on the center stagger locations of the destination grid -dstfield = ESMF.Field(dstgrid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(dstgrid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER) -dstfracfield = ESMF.Field(dstgrid, name='dstfracfield', staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(dstgrid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER) +dstfracfield = esmpy.Field(dstgrid, name='dstfracfield', staggerloc=esmpy.StaggerLoc.CENTER) # initialize the fields [lon,lat] = [0, 1] deg2rad = 3.14/180. -gridLon = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) x = numpy.cos(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) y = numpy.sin(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) @@ -54,8 +55,8 @@ srcfield.data[...] = 200.0 + x + y + z -gridLon = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) x = numpy.cos(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) y = numpy.sin(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) @@ -68,18 +69,18 @@ # write regridding weights to file import os filename = "esmpy_example_weight_file_cs.nc" -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: if os.path.isfile(os.path.join(os.getcwd(), filename)): os.remove(os.path.join(os.getcwd(), filename)) mg.barrier() -regrid = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) +regrid = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) mg.barrier() -regrid = ESMF.RegridFromFile(srcfield, dstfield, filename=filename) +regrid = esmpy.RegridFromFile(srcfield, dstfield, filename=filename) # do the regridding from source to destination field mg.barrier() @@ -97,13 +98,13 @@ maxrelerr = numpy.max(numpy.abs(dstfield.data - xctfield.data) / numpy.abs(xctfield.data)) # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) maxrelerr = helpers.reduce_val(maxrelerr, op=constants.Reduce.MAX) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy cubed sphere regridding example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py deleted file mode 100644 index 5bfbf8d32f..0000000000 --- a/src/addon/ESMPy/examples/exampletest.py +++ /dev/null @@ -1,72 +0,0 @@ -# $Id$ - -""" -examples test file -""" -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - -from ESMF.test.base import TestBase, attr -import ESMF.api.constants as constants - -class TestExamples(TestBase): - - def test_helloworld(self): - from . import hello_world - - # # ESMF IO does not work in mpiuni mode - # def test_cubed_sphere_to_mesh_regrid(self): - # if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - # raise SkipTest('ESMF must be built with MPI for test') - # else: - # from . import cubed_sphere_to_mesh_regrid - - # ESMF IO does not work in mpiuni mode - # only example, not in documentation - def test_field_read(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import field_read - - # only example, not in documentation - def test_grid_create_peridim_mask(self): - from . import grid_create_peridim_mask - - def test_grid_locstream_regrid(self): - from . import grid_locstream_regrid - - def test_locstream_grid_regrid(self): - from . import locstream_grid_regrid - - def test_mesh_locstream_regrid(self): - from . import mesh_locstream_regrid - - # ESMF IO does not work in mpiuni mode - def test_read_write_weight_file(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import read_write_weight_file - - # ESMF IO does not work in mpiuni mode - def test_regrid_from_file(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import regrid_from_file - - # only example, not in documentation - @attr('slow') - def test_tripole_regrid(self): - from . import tripole_regrid - - # only example, not in documentation - def test_ugrid_latlon_regrid(self): - from . import ugrid_latlon_regrid - - # only example, not in documentation - def test_ungridded_dimension_regrid(self): - from . import ungridded_dimension_regrid diff --git a/src/addon/ESMPy/examples/field_read.py b/src/addon/ESMPy/examples/field_read.py index c69060e989..d09e536606 100644 --- a/src/addon/ESMPy/examples/field_read.py +++ b/src/addon/ESMPy/examples/field_read.py @@ -7,45 +7,45 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "so_Omon_GISS-E2.nc")) # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy # This call enables debug logging -esmpy = ESMF.Manager(debug=True) +esmpy.Manager(debug=True) datafile = "examples/data/so_Omon_GISS-E2.nc" gridfile = "examples/data/ll1deg_grid.nc" # Create a grid from a GRIDSPEC formatted file -srcgrid = ESMF.Grid(filename=datafile, filetype=ESMF.FileFormat.GRIDSPEC) +srcgrid = esmpy.Grid(filename=datafile, filetype=esmpy.FileFormat.GRIDSPEC) # Create a field on the center stagger locations of the source grid with # ungridded dimensions large enough to receive the data from file # dimensions follow Fortran index order: lon, lat, level, time -srcfield = ESMF.Field(srcgrid, staggerloc=ESMF.StaggerLoc.CENTER, ndbounds=[33, 2]) +srcfield = esmpy.Field(srcgrid, staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) # Read the field data into the data structure srcfield.read(filename=datafile, variable="so", timeslice=2) # Create a 1 degree latlon grid -dstgrid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP) # Create a field on the center stagger locations of the latlon grid, also with # ungridded dimensions large enough to recieve the data from the source field -dstfield = ESMF.Field(dstgrid, name='dstfield', meshloc=ESMF.StaggerLoc.CENTER, +dstfield = esmpy.Field(dstgrid, name='dstfield', meshloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) dstfield.data[...] = 1e20 # Create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # Do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) # Output the results from one processor only -if ESMF.local_pet() == 0: print ("ESMPy Field Data Regridding Example Finished Successfully") \ No newline at end of file +if esmpy.local_pet() == 0: print ("ESMPy Field Data Regridding Example Finished Successfully") diff --git a/src/addon/ESMPy/examples/grid_create_peridim_mask.py b/src/addon/ESMPy/examples/grid_create_peridim_mask.py index bae26f869d..04553bf3b2 100644 --- a/src/addon/ESMPy/examples/grid_create_peridim_mask.py +++ b/src/addon/ESMPy/examples/grid_create_peridim_mask.py @@ -7,19 +7,19 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants gridfile = "examples/data/ll2.5deg_grid.nc" # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) # Create the source grid from memory with periodic dimension specified. [lat,lon] = [1,0] @@ -27,51 +27,51 @@ lats = numpy.arange( 0, 360, 360./70.) lons = numpy.arange(-90., 90.1, 180./140.) max_index = numpy.array([lons.size, lats.size]) -srcgrid = ESMF.Grid(max_index, coord_sys=ESMF.CoordSys.SPH_DEG, coord_typekind=ESMF.TypeKind.R4, +srcgrid = esmpy.Grid(max_index, coord_sys=esmpy.CoordSys.SPH_DEG, coord_typekind=esmpy.TypeKind.R4, num_peri_dims=1, periodic_dim=1, pole_dim=0) # Add coordinates to the source grid. -srcgrid.add_coords(staggerloc=[ESMF.StaggerLoc.CENTER]) +srcgrid.add_coords(staggerloc=[esmpy.StaggerLoc.CENTER]) # Get and set the source grid coordinates. gridCoordLat = srcgrid.get_coords(lat) gridCoordLon = srcgrid.get_coords(lon) -lons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -lats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +lons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +lats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] gridCoordLat[...] = lats_par.reshape(1, lats_par.size) gridCoordLon[...] = lons_par.reshape(lons_par.size, 1) # Add a mask to the source grid -mask = srcgrid.add_item(ESMF.GridItem.MASK) +mask = srcgrid.add_item(esmpy.GridItem.MASK) dx=gridCoordLon-max_index[0]/2.0 dy=gridCoordLat-max_index[1]/2.0 mask[...] = 0 mask[numpy.where(numpy.sqrt(dx*dx+dy*dy) < 10.0)] = 2 # Create a field on the centers of the source grid with the mask applied. -srcfield = ESMF.Field(srcgrid, name="srcfield", staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name="srcfield", staggerloc=esmpy.StaggerLoc.CENTER) srcfield.data[...] = 0 # Create a destination grid from a SCRIP formatted file. -dstgrid = ESMF.Grid(filename=gridfile, - filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=gridfile, + filetype=esmpy.FileFormat.SCRIP) # Create a field on the centers of the destination grid. -dstfield = ESMF.Field(dstgrid, name="dstfield", staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name="dstfield", staggerloc=esmpy.StaggerLoc.CENTER) missing_val = 1000 dstfield.data[...] = missing_val # Regrid from source grid to destination grid. -regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, +regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=numpy.array([2], dtype=numpy.int32), - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) -dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=esmpy.Region.SELECT) dgridCoordLat = dstgrid.get_coords(lat) dstmaskedlats = dgridCoordLat[numpy.where(dstfield.data == missing_val)] @@ -79,9 +79,9 @@ masked_values = dstmaskedlats.size # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: masked_values = helpers.reduce_val(dstmaskedlats.size, op=constants.Reduce.SUM) -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: assert (masked_values > 0) print ("Successfully created a grid with masking and switched periodic dimensions for regridding!") diff --git a/src/addon/ESMPy/examples/grid_locstream_regrid.py b/src/addon/ESMPy/examples/grid_locstream_regrid.py index ffcdf7b535..a9d58b139f 100644 --- a/src/addon/ESMPy/examples/grid_locstream_regrid.py +++ b/src/addon/ESMPy/examples/grid_locstream_regrid.py @@ -6,42 +6,34 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -ESMF.Manager(debug=True) +esmpy.Manager(debug=True) -from ESMF.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel -coord_sys=ESMF.CoordSys.SPH_DEG +from esmpy.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel +coord_sys=esmpy.CoordSys.SPH_DEG domask=True -if ESMF.pet_count() == 1: +if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) + locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) grid1 = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # create a field -srcfield = ESMF.Field(grid, name='srcfield') +srcfield = esmpy.Field(grid, name='srcfield') -dstfield = ESMF.Field(locstream, name='dstfield') -xctfield = ESMF.Field(locstream, name='xctfield') +dstfield = esmpy.Field(locstream, name='dstfield') +xctfield = esmpy.Field(locstream, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -53,9 +45,9 @@ gridXCoord = locstream["ESMF:Lon"] gridYCoord = locstream["ESMF:Lat"] -if coord_sys == ESMF.CoordSys.SPH_DEG: +if coord_sys == esmpy.CoordSys.SPH_DEG: xctfield.data[...] = 10.0 + numpy.cos(gridXCoord * deg2rad) ** 2 + numpy.cos(2 * gridYCoord * deg2rad) -elif coord_sys == ESMF.CoordSys.SPH_RAD: +elif coord_sys == esmpy.CoordSys.SPH_RAD: xctfield.data[...] = 10.0 + numpy.cos(gridXCoord) ** 2 + numpy.cos(2 * gridYCoord) else: raise ValueError("coordsys value does not work in this example") @@ -67,13 +59,13 @@ if domask: dst_mask_values=numpy.array([0]) -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, dst_mask_values=dst_mask_values) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # compute the mean relative error num_nodes = numpy.prod(xctfield.data.shape[:]) @@ -89,12 +81,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid LocStream Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/hello_world.py b/src/addon/ESMPy/examples/hello_world.py index c5fa2dc174..412da2e2f3 100644 --- a/src/addon/ESMPy/examples/hello_world.py +++ b/src/addon/ESMPy/examples/hello_world.py @@ -1,6 +1,6 @@ -import ESMF +import esmpy # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) -print ("Hello ESMPy World from PET (processor) {0}!".format(ESMF.local_pet())) \ No newline at end of file +print ("Hello ESMPy World from PET (processor) {0}!".format(esmpy.local_pet())) \ No newline at end of file diff --git a/src/addon/ESMPy/examples/locstream_grid_regrid.py b/src/addon/ESMPy/examples/locstream_grid_regrid.py index e09db8956b..7a53c1273f 100644 --- a/src/addon/ESMPy/examples/locstream_grid_regrid.py +++ b/src/addon/ESMPy/examples/locstream_grid_regrid.py @@ -6,42 +6,34 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -ESMF.Manager(debug=True) +esmpy.Manager(debug=True) grid1 = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) -from ESMF.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel -coord_sys=ESMF.CoordSys.SPH_DEG +from esmpy.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel +coord_sys=esmpy.CoordSys.SPH_DEG domask=True -if ESMF.pet_count() == 1: +if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) + locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) # create a field -srcfield = ESMF.Field(locstream, name='srcfield') +srcfield = esmpy.Field(locstream, name='srcfield') -dstfield = ESMF.Field(grid, name='dstfield') -xctfield = ESMF.Field(grid, name='xctfield') +dstfield = esmpy.Field(grid, name='dstfield') +xctfield = esmpy.Field(grid, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -49,9 +41,9 @@ gridXCoord = locstream["ESMF:Lon"] gridYCoord = locstream["ESMF:Lat"] -if coord_sys == ESMF.CoordSys.SPH_DEG: +if coord_sys == esmpy.CoordSys.SPH_DEG: srcfield.data[...] = 10.0 + numpy.cos(gridXCoord * deg2rad) ** 2 + numpy.cos(2 * gridYCoord * deg2rad) -elif coord_sys == ESMF.CoordSys.SPH_RAD: +elif coord_sys == esmpy.CoordSys.SPH_RAD: srcfield.data[...] = 10.0 + numpy.cos(gridXCoord) ** 2 + numpy.cos(2 * gridYCoord) else: raise ValueError("coordsys value does not apply in this example") @@ -68,13 +60,13 @@ if domask: mask_values=numpy.array([0]) -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.NEAREST_DTOS, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.NEAREST_DTOS, + unmapped_action=esmpy.UnmappedAction.ERROR, src_mask_values=mask_values) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # compute the mean relative error from operator import mul @@ -91,12 +83,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy LocStream Grid Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/mesh_locstream_regrid.py b/src/addon/ESMPy/examples/mesh_locstream_regrid.py index c707a6c56e..69dfb6bc02 100644 --- a/src/addon/ESMPy/examples/mesh_locstream_regrid.py +++ b/src/addon/ESMPy/examples/mesh_locstream_regrid.py @@ -1,37 +1,29 @@ # This example demonstrates how to regrid between a mesh and a locstream. -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -# ESMF.Manager(debug=True) +# esmpy.Manager(debug=True) -from ESMF.util.mesh_utilities import mesh_create_5, mesh_create_5_parallel -from ESMF.util.locstream_utilities import create_locstream_16, create_locstream_16_parallel -if ESMF.pet_count() == 1: +from esmpy.util.mesh_utilities import mesh_create_5, mesh_create_5_parallel +from esmpy.util.locstream_utilities import create_locstream_16, create_locstream_16_parallel +if esmpy.pet_count() == 1: mesh, _, _, _, _, _ = mesh_create_5() locstream = create_locstream_16() else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - mesh, _, _, _, _ = mesh_create_5_parallel() - locstream = create_locstream_16_parallel() + mesh, _, _, _, _ = mesh_create_5_parallel() + locstream = create_locstream_16_parallel() # create a field -srcfield = ESMF.Field(mesh, name='srcfield')#, meshloc=ESMF.MeshLoc.ELEMENT) +srcfield = esmpy.Field(mesh, name='srcfield')#, meshloc=esmpy.MeshLoc.ELEMENT) # create a field on the locstream -dstfield = ESMF.Field(locstream, name='dstfield') -xctfield = ESMF.Field(locstream, name='xctfield') +dstfield = esmpy.Field(locstream, name='dstfield') +xctfield = esmpy.Field(locstream, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -49,8 +41,8 @@ # create an object to regrid data from the source to the destination field # TODO: this example seems to fail occasionally with UnmappedAction.ERROR, probably due to a tolerance issue - ask Bob -regrid = ESMF.Regrid(srcfield=srcfield, dstfield=dstfield, regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield=srcfield, dstfield=dstfield, regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) @@ -65,12 +57,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid Mesh Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/mpi_spawn_regrid.py b/src/addon/ESMPy/examples/mpi_spawn_regrid.py index 9541f15ccd..ea838a121f 100644 --- a/src/addon/ESMPy/examples/mpi_spawn_regrid.py +++ b/src/addon/ESMPy/examples/mpi_spawn_regrid.py @@ -11,7 +11,7 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) @@ -21,7 +21,7 @@ def regrid(): try: - import ESMF + import esmpy except: raise ImportError("ESMF is not available on this machine") @@ -29,45 +29,45 @@ def regrid(): grid2 = "examples/data/mpas_uniform_10242_dual_counterclockwise.nc" # Create a uniform global latlon grid from a SCRIP formatted file - grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) + grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # NOTE: corners are needed for conservative regridding - # grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, + # grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, # add_corner_stagger=True) # create a field on the center stagger locations of the source grid - srcfield = ESMF.Field(grid, name='srcfield', - staggerloc=ESMF.StaggerLoc.CENTER) + srcfield = esmpy.Field(grid, name='srcfield', + staggerloc=esmpy.StaggerLoc.CENTER) # create an ESMF formatted unstructured mesh with clockwise cells removed - mesh = ESMF.Mesh(filename=grid2, filetype=ESMF.FileFormat.ESMFMESH) + mesh = esmpy.Mesh(filename=grid2, filetype=esmpy.FileFormat.ESMFMESH) # create a field on the nodes of the destination mesh - dstfield = ESMF.Field(mesh, name='dstfield', meshloc=ESMF.MeshLoc.NODE) - xctfield = ESMF.Field(mesh, name='xctfield', meshloc=ESMF.MeshLoc.NODE) + dstfield = esmpy.Field(mesh, name='dstfield', meshloc=esmpy.MeshLoc.NODE) + xctfield = esmpy.Field(mesh, name='xctfield', meshloc=esmpy.MeshLoc.NODE) # NOTE: Field must be built on elements of Mesh for conservative regridding - # dstfield = ESMF.Field(mesh, name='dstfield', meshloc=ESMF.MeshLoc.ELEMENT) - # xctfield = ESMF.Field(mesh, name='xctfield', meshloc=ESMF.MeshLoc.ELEMENT) + # dstfield = esmpy.Field(mesh, name='dstfield', meshloc=esmpy.MeshLoc.ELEMENT) + # xctfield = esmpy.Field(mesh, name='xctfield', meshloc=esmpy.MeshLoc.ELEMENT) # initialize the fields [lon, lat] = [0, 1] deg2rad = 3.14159 / 180 - gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) - gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) + gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) + gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) srcfield.data[...] = 10.0 + (gridXCoord * deg2rad) ** 2 + ( gridYCoord * deg2rad) ** 2 - gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) - gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) + gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) + gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 10.0 + (gridXCoord * deg2rad) ** 2 + ( gridYCoord * deg2rad) ** 2 dstfield.data[...] = 1e20 # create an object to regrid data from the source to the destination field - regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) # do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) diff --git a/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb b/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb index 3a827a6134..dad0644086 100644 --- a/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb +++ b/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb @@ -22,11 +22,11 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np\n", "\n", "# pull in some extra ESMF symbols for the sake of brevity\n", - "from ESMF import Grid, Mesh, LocStream, Field, Regrid, RegridFromFile" + "from esmpy import Grid, Mesh, LocStream, Field, Regrid, RegridFromFile" ] }, { @@ -51,7 +51,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"))" ] @@ -67,7 +67,7 @@ "gridfile = os.path.join(DD, \"ll1deg_grid.nc\")\n", "\n", "# Create a grid from a SCRIP formatted file\n", - "grid = Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "grid = Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -84,11 +84,11 @@ "outputs": [], "source": [ "# Environment Canada CMIP5 climate data\n", - "grid_CanCM = ESMF.Grid(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"),\n", - " filetype=ESMF.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"tas\")\n", + "grid_CanCM = esmpy.Grid(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"),\n", + " filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"tas\")\n", "\n", "timeslice = 12\n", - "field = ESMF.Field(grid_CanCM, ndbounds=[timeslice])\n", + "field = esmpy.Field(grid_CanCM, ndbounds=[timeslice])\n", "\n", "field.read(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"), \n", " variable=\"tas\", timeslice=timeslice)" @@ -101,7 +101,7 @@ "outputs": [], "source": [ "# create a target field on latlon 1 degree grid, with space for time dimension\n", - "target_field = ESMF.Field(grid, ndbounds=[timeslice])" + "target_field = esmpy.Field(grid, ndbounds=[timeslice])" ] }, { @@ -125,8 +125,8 @@ "outputs": [], "source": [ "# generate weights, note that masks read from file generally use 0 to represent masked values and 1 for non masked\n", - "regrid = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, dst_mask_values=[0])" + "regrid = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, dst_mask_values=[0])" ] }, { @@ -136,8 +136,8 @@ "outputs": [], "source": [ "# also generation a reverse Regrid to bring the data back to the original grid (for error measurement)\n", - "regrid_T= ESMF.Regrid(target_field, field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, src_mask_values=[0])" + "regrid_T= esmpy.Regrid(target_field, field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, src_mask_values=[0])" ] }, { @@ -154,8 +154,8 @@ "outputs": [], "source": [ "# Apply the weights in the Regrid/Regrid_T to regrid data from field to target_field and then back to field\n", - "target_field = regrid(field, target_field, zero_region=ESMF.Region.SELECT)\n", - "solution_CanCM = regrid_T(target_field, field, zero_region=ESMF.Region.SELECT)" + "target_field = regrid(field, target_field, zero_region=esmpy.Region.SELECT)\n", + "solution_CanCM = regrid_T(target_field, field, zero_region=esmpy.Region.SELECT)" ] }, { @@ -248,8 +248,8 @@ "!{cmd}\n", "\n", "# generate weights and output them to a file\n", - "rf1 = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, filename=weightfile)" + "rf1 = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, filename=weightfile)" ] }, { @@ -292,8 +292,8 @@ "source": [ "# generate weights and output them to a file \n", "routehandlefile = \"CanCMtoLatLon1deg.rh\"\n", - "rf2 = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, rh_filename=routehandlefile)" + "rf2 = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, rh_filename=routehandlefile)" ] }, { @@ -302,8 +302,8 @@ "metadata": {}, "outputs": [], "source": [ - "rf1 = ESMF.RegridFromFile(field, target_field, filename=weightfile)\n", - "rf2 = ESMF.RegridFromFile(field, target_field, rh_filename=routehandlefile)" + "rf1 = esmpy.RegridFromFile(field, target_field, filename=weightfile)\n", + "rf2 = esmpy.RegridFromFile(field, target_field, rh_filename=routehandlefile)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb b/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb index 1786e289ba..24836d9864 100644 --- a/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb +++ b/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np" ] }, @@ -55,7 +55,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"ll2.5deg_grid.nc\"))" ] @@ -73,10 +73,10 @@ "metadata": {}, "outputs": [], "source": [ - "srcgrid = ESMF.Grid(filename=os.path.join(DD, \"ll1deg_grid.nc\"),\n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)\n", - "dstgrid = ESMF.Grid(filename=os.path.join(DD, \"ll2.5deg_grid.nc\"), \n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "srcgrid = esmpy.Grid(filename=os.path.join(DD, \"ll1deg_grid.nc\"),\n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)\n", + "dstgrid = esmpy.Grid(filename=os.path.join(DD, \"ll2.5deg_grid.nc\"), \n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -92,8 +92,8 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(srcgrid)\n", - "dstfield = ESMF.Field(dstgrid)" + "srcfield = esmpy.Field(srcgrid)\n", + "dstfield = esmpy.Field(dstgrid)" ] }, { @@ -125,7 +125,7 @@ "metadata": {}, "outputs": [], "source": [ - "regridS2D = ESMF.Regrid(srcfield, dstfield)" + "regridS2D = esmpy.Regrid(srcfield, dstfield)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb b/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb index cb2363b691..529a3b28df 100644 --- a/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb +++ b/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb @@ -25,8 +25,8 @@ ], "source": [ "import numpy as np\n", - "import ESMF\n", - "ESMF.__version__" + "import esmpy\n", + "esmpy.__version__" ] }, { @@ -84,9 +84,9 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid = ESMF.Grid(np.array([20,20]), \n", - " staggerloc = ESMF.StaggerLoc.CENTER,\n", - " coord_sys = ESMF.CoordSys.SPH_DEG)\n", + "sourcegrid = esmpy.Grid(np.array([20,20]), \n", + " staggerloc = esmpy.StaggerLoc.CENTER,\n", + " coord_sys = esmpy.CoordSys.SPH_DEG)\n", "\n", "source_lon = sourcegrid.get_coords(0)\n", "source_lat = sourcegrid.get_coords(1)\n", @@ -106,12 +106,12 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid.add_coords(staggerloc = ESMF.StaggerLoc.CORNER_VCENTER)\n", + "sourcegrid.add_coords(staggerloc = esmpy.StaggerLoc.CORNER_VCENTER)\n", "\n", "source_lat_b = sourcegrid.get_coords(coord_dim = 1, \n", - " staggerloc = ESMF.StaggerLoc.CORNER)\n", + " staggerloc = esmpy.StaggerLoc.CORNER)\n", "source_lon_b = sourcegrid.get_coords(coord_dim = 0, \n", - " staggerloc = ESMF.StaggerLoc.CORNER)\n", + " staggerloc = esmpy.StaggerLoc.CORNER)\n", "\n", "source_lon_b[...], source_lat_b[...] = np.meshgrid(lon_b, lat_b)" ] @@ -221,7 +221,7 @@ } ], "source": [ - "sourcegridareafield = ESMF.Field(sourcegrid)\n", + "sourcegridareafield = esmpy.Field(sourcegrid)\n", "sourcegridareafield.get_area()\n", "sourcegridareafield.data" ] diff --git a/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb b/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb index 26dfe8c341..ed244bfe6e 100644 --- a/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb +++ b/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb @@ -24,7 +24,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np" ] }, @@ -50,7 +50,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"ne30np4_esmf.nc\"))\n", "cache_data_file(os.path.join(DD, \"so_Omon_GISS-E2.nc\"))" @@ -77,8 +77,8 @@ } ], "source": [ - "ESMF.Manager(debug=True)\n", - "print(ESMF.local_pet(), ESMF.pet_count())" + "esmpy.Manager(debug=True)\n", + "print(esmpy.local_pet(), esmpy.pet_count())" ] }, { @@ -105,8 +105,8 @@ "outputs": [], "source": [ "gridfile = \"ll1deg_grid.nc\"\n", - "grid = ESMF.Grid(filename=os.path.join(DD, gridfile),\n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "grid = esmpy.Grid(filename=os.path.join(DD, gridfile),\n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -126,7 +126,7 @@ "# ESMPy follows ESMF/Fortran/Mathematics convention for indices in order lon, lat\n", "lon = 0\n", "lat = 1\n", - "print (grid.coords[ESMF.StaggerLoc.CENTER][lon].shape)" + "print (grid.coords[esmpy.StaggerLoc.CENTER][lon].shape)" ] }, { @@ -160,9 +160,9 @@ ], "source": [ "# Coordinates are stored as numpy arrays, basic slicing capabilites are available\n", - "print (type(grid.coords[ESMF.StaggerLoc.CENTER][lon]))\n", + "print (type(grid.coords[esmpy.StaggerLoc.CENTER][lon]))\n", "\n", - "print (grid.coords[ESMF.StaggerLoc.CENTER][lon][2:4])\n" + "print (grid.coords[esmpy.StaggerLoc.CENTER][lon][2:4])\n" ] }, { @@ -219,11 +219,11 @@ "outputs": [], "source": [ "max_index = np.array([360, 179])\n", - "grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.EDGE1, ESMF.StaggerLoc.EDGE2, ESMF.StaggerLoc.CORNER], \n", - " coord_sys=ESMF.CoordSys.SPH_DEG, \n", - " coord_typekind=ESMF.TypeKind.R4, \n", + "grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER, esmpy.StaggerLoc.EDGE1, esmpy.StaggerLoc.EDGE2, esmpy.StaggerLoc.CORNER], \n", + " coord_sys=esmpy.CoordSys.SPH_DEG, \n", + " coord_typekind=esmpy.TypeKind.R4, \n", " num_peri_dims = 1,\n", - " pole_kind=[ESMF.PoleKind.MONOPOLE, ESMF.PoleKind.BIPOLE])\n", + " pole_kind=[esmpy.PoleKind.MONOPOLE, esmpy.PoleKind.BIPOLE])\n", "\n", "gridLonCenter = grid.get_coords(0)\n", "gridLatCenter = grid.get_coords(1)\n", @@ -291,7 +291,7 @@ "source": [ "# cubed-sphere grid is represented as an unstructured Mesh\n", "meshfile = \"ne30np4_esmf.nc\"\n", - "mesh = ESMF.Mesh(filename=os.path.join(DD, meshfile), filetype=ESMF.FileFormat.ESMFMESH)\n", + "mesh = esmpy.Mesh(filename=os.path.join(DD, meshfile), filetype=esmpy.FileFormat.ESMFMESH)\n", "# print(mesh)" ] }, @@ -358,7 +358,7 @@ "metadata": {}, "outputs": [], "source": [ - "meshinmem = ESMF.Mesh(parametric_dim=2, spatial_dim=2)\n", + "meshinmem = esmpy.Mesh(parametric_dim=2, spatial_dim=2)\n", "\n", "num_node = 12\n", "num_elem = 5\n", @@ -369,8 +369,8 @@ "nodeOwner = np.zeros(num_node)\n", "\n", "elemId = np.array([1,2,3,4,5])\n", - "elemType=np.array([ESMF.MeshElemType.QUAD,ESMF.MeshElemType.TRI,\n", - " ESMF.MeshElemType.TRI, 5, 6])\n", + "elemType=np.array([esmpy.MeshElemType.QUAD,esmpy.MeshElemType.TRI,\n", + " esmpy.MeshElemType.TRI, 5, 6])\n", " \n", "elemConn=np.array([0,1,4,3, 1,2,4, 2,5,4, 3,4,8,7,6, 4,5,11,10,9,8])\n", "\n", @@ -443,7 +443,7 @@ ], "source": [ "# locstreams can currently only be created in memory\n", - "locstream = ESMF.LocStream(16)\n", + "locstream = esmpy.LocStream(16)\n", "\n", "locstream[\"ESMF:X\"] = [0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0]\n", "locstream[\"ESMF:Y\"] = [0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 4.0, 4.0, 4.0, 4.0]\n", @@ -504,7 +504,7 @@ } ], "source": [ - "locstream = ESMF.LocStream(10, coord_sys=ESMF.CoordSys.SPH_RAD)\n", + "locstream = esmpy.LocStream(10, coord_sys=esmpy.CoordSys.SPH_RAD)\n", "\n", "locstream[\"ESMF:Lon\"] = np.linspace(0, 2*np.pi, 10).tolist()\n", "locstream[\"ESMF:Lat\"] = np.linspace(np.pi/-2.0, np.pi/2.0, 10).tolist()\n", @@ -596,9 +596,9 @@ } ], "source": [ - "field_grid = ESMF.Field(grid, name=\"field_grid\", typekind=ESMF.TypeKind.I8, staggerloc=ESMF.StaggerLoc.CORNER)\n", - "field_mesh = ESMF.Field(mesh, name=\"field_mesh\", typekind=ESMF.TypeKind.R4, meshloc=ESMF.MeshLoc.ELEMENT)\n", - "field_locs = ESMF.Field(locstream, name=\"field_locs\", typekind=ESMF.TypeKind.R4)\n", + "field_grid = esmpy.Field(grid, name=\"field_grid\", typekind=esmpy.TypeKind.I8, staggerloc=esmpy.StaggerLoc.CORNER)\n", + "field_mesh = esmpy.Field(mesh, name=\"field_mesh\", typekind=esmpy.TypeKind.R4, meshloc=esmpy.MeshLoc.ELEMENT)\n", + "field_locs = esmpy.Field(locstream, name=\"field_locs\", typekind=esmpy.TypeKind.R4)\n", "print(field_locs)" ] }, @@ -616,11 +616,11 @@ "outputs": [], "source": [ "# NASA-GISS sea water salinity data with 33 vertical layers and 2 timesteps\n", - "grid_so = ESMF.Grid(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"),\n", - " filetype=ESMF.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"so\")\n", + "grid_so = esmpy.Grid(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"),\n", + " filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"so\")\n", "\n", "timeslice = 12\n", - "field_so = ESMF.Field(grid_so, ndbounds=[33, 2])\n", + "field_so = esmpy.Field(grid_so, ndbounds=[33, 2])\n", "\n", "field_so.read(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"), \n", " variable=\"so\", timeslice=2)" diff --git a/src/addon/ESMPy/examples/notebooks/Periodic.ipynb b/src/addon/ESMPy/examples/notebooks/Periodic.ipynb index d25ea1f429..05c74f2ed6 100644 --- a/src/addon/ESMPy/examples/notebooks/Periodic.ipynb +++ b/src/addon/ESMPy/examples/notebooks/Periodic.ipynb @@ -16,7 +16,7 @@ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "import ESMF" + "import esmpy" ] }, { @@ -118,9 +118,9 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid = ESMF.Grid(np.array([lon_in.size, lat_in.size]), \n", - " staggerloc = [ESMF.StaggerLoc.CENTER],\n", - " coord_sys = ESMF.CoordSys.SPH_DEG,\n", + "sourcegrid = esmpy.Grid(np.array([lon_in.size, lat_in.size]), \n", + " staggerloc = [esmpy.StaggerLoc.CENTER],\n", + " coord_sys = esmpy.CoordSys.SPH_DEG,\n", " num_peri_dims = 1)\n", "\n", "source_lon = sourcegrid.get_coords(0)\n", @@ -155,9 +155,9 @@ "metadata": {}, "outputs": [], "source": [ - "destgrid = ESMF.Grid(np.array([lon_out.size, lat_out.size]), \n", - " staggerloc = [ESMF.StaggerLoc.CENTER],\n", - " coord_sys = ESMF.CoordSys.SPH_DEG,\n", + "destgrid = esmpy.Grid(np.array([lon_out.size, lat_out.size]), \n", + " staggerloc = [esmpy.StaggerLoc.CENTER],\n", + " coord_sys = esmpy.CoordSys.SPH_DEG,\n", " num_peri_dims = 1)\n", "\n", "\n", @@ -173,8 +173,8 @@ "metadata": {}, "outputs": [], "source": [ - "sourcefield = ESMF.Field(sourcegrid)\n", - "destfield = ESMF.Field(destgrid)" + "sourcefield = esmpy.Field(sourcegrid)\n", + "destfield = esmpy.Field(destgrid)" ] }, { @@ -183,9 +183,9 @@ "metadata": {}, "outputs": [], "source": [ - "regrid_bi = ESMF.Regrid(sourcefield, destfield, \n", - " regrid_method = ESMF.RegridMethod.BILINEAR, \n", - " unmapped_action = ESMF.UnmappedAction.ERROR)" + "regrid_bi = esmpy.Regrid(sourcefield, destfield, \n", + " regrid_method = esmpy.RegridMethod.BILINEAR, \n", + " unmapped_action = esmpy.UnmappedAction.ERROR)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb b/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb index 5286787a27..88feeb6d8c 100644 --- a/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb +++ b/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy" ] }, @@ -60,7 +60,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "# cache_data_file(os.path.join(DD, \"aggregAtlanticESTOFS.nc\"))\n", "os.system(\"wget https://www.dropbox.com/s/ke5mdukbjwyqaru/aggregAtlanticESTOFS.nc\")\n", @@ -82,7 +82,7 @@ "outputs": [], "source": [ "gridfile = \"ESMPy-data/ll1deg_grid.nc\"\n", - "grid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, is_sphere=True)" + "grid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, is_sphere=True)" ] }, { @@ -99,7 +99,7 @@ "outputs": [], "source": [ "meshfile = \"ESMPy-data/aggregAtlanticESTOFS.nc\"\n", - "mesh = ESMF.Mesh(filename=meshfile, filetype=ESMF.FileFormat.UGRID, meshname='adcirc_mesh')" + "mesh = esmpy.Mesh(filename=meshfile, filetype=esmpy.FileFormat.UGRID, meshname='adcirc_mesh')" ] }, { @@ -115,20 +115,20 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE)\n", + "srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE)\n", "\n", - "dstfield = ESMF.Field(grid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER)\n", - "xctfield = ESMF.Field(grid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER)\n", + "dstfield = esmpy.Field(grid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER)\n", + "xctfield = esmpy.Field(grid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER)\n", "\n", "[lon, lat] = [0, 1]\n", "\n", - "srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=ESMF.MeshLoc.NODE)\n", - "srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=ESMF.MeshLoc.NODE)\n", + "srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=esmpy.MeshLoc.NODE)\n", + "srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=esmpy.MeshLoc.NODE)\n", "srcfield.data[...] = 2.0 + numpy.cos(numpy.radians(srcgridYCoord)[...])**2 * \\\n", " numpy.cos(2.0*numpy.radians(srcgridXCoord)[...])\n", "\n", - "dstgridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "dstgridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "dstgridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "dstgridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "xctfield.data[...] = 2.0 + numpy.cos(numpy.radians(dstgridYCoord)[...])**2 * \\\n", " numpy.cos(2.0*numpy.radians(dstgridXCoord)[...])\n", "\n", @@ -149,11 +149,11 @@ "metadata": {}, "outputs": [], "source": [ - "regrid = ESMF.Regrid(srcfield, dstfield,\n", - " regrid_method=ESMF.RegridMethod.BILINEAR,\n", - " unmapped_action=ESMF.UnmappedAction.IGNORE)\n", + "regrid = esmpy.Regrid(srcfield, dstfield,\n", + " regrid_method=esmpy.RegridMethod.BILINEAR,\n", + " unmapped_action=esmpy.UnmappedAction.IGNORE)\n", "\n", - "dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT)" + "dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT)" ] }, { @@ -258,7 +258,7 @@ "source": [ "dstfield.data[...] = uninitval\n", "\n", - "dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT)" + "dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb b/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb index b31881f6b4..c5cf86c2a1 100644 --- a/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb +++ b/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy" ] }, @@ -60,7 +60,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll2.5deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"T42_grid.nc\"))\n", "print('Done.')" @@ -96,11 +96,11 @@ "metadata": {}, "outputs": [], "source": [ - "srcgrid = ESMF.Grid(filename=\"ESMPy-data/ll2.5deg_grid.nc\", \n", - " filetype=ESMF.FileFormat.SCRIP,\n", + "srcgrid = esmpy.Grid(filename=\"ESMPy-data/ll2.5deg_grid.nc\", \n", + " filetype=esmpy.FileFormat.SCRIP,\n", " add_corner_stagger=True)\n", - "dstgrid = ESMF.Grid(filename=\"ESMPy-data/T42_grid.nc\", \n", - " filetype=ESMF.FileFormat.SCRIP,\n", + "dstgrid = esmpy.Grid(filename=\"ESMPy-data/T42_grid.nc\", \n", + " filetype=esmpy.FileFormat.SCRIP,\n", " add_corner_stagger=True)" ] }, @@ -117,14 +117,14 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(srcgrid, name='srcfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "srcfield = esmpy.Field(srcgrid, name='srcfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])\n", - "dstfield = ESMF.Field(dstgrid, name='dstfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "dstfield = esmpy.Field(dstgrid, name='dstfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])\n", - "xctfield = ESMF.Field(dstgrid, name='xctfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "xctfield = esmpy.Field(dstgrid, name='xctfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])" ] }, @@ -142,8 +142,8 @@ "outputs": [], "source": [ "[lon,lat] = [0, 1]\n", - "gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "\n", "deg2rad = 3.14159/180\n", "\n", @@ -169,8 +169,8 @@ "metadata": {}, "outputs": [], "source": [ - "gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "\n", "for timestep in range(time):\n", " for level in range(levels):\n", @@ -196,9 +196,9 @@ "metadata": {}, "outputs": [], "source": [ - "regrid = ESMF.Regrid(srcfield, dstfield,\n", - " regrid_method=ESMF.RegridMethod.CONSERVE,\n", - " unmapped_action=ESMF.UnmappedAction.ERROR)" + "regrid = esmpy.Regrid(srcfield, dstfield,\n", + " regrid_method=esmpy.RegridMethod.CONSERVE,\n", + " unmapped_action=esmpy.UnmappedAction.ERROR)" ] }, { diff --git a/src/addon/ESMPy/examples/read_write_weight_file.py b/src/addon/ESMPy/examples/read_write_weight_file.py index 4c779e72ec..836a2267ba 100644 --- a/src/addon/ESMPy/examples/read_write_weight_file.py +++ b/src/addon/ESMPy/examples/read_write_weight_file.py @@ -6,18 +6,18 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -mg = ESMF.Manager(debug=True) +mg = esmpy.Manager(debug=True) # ESMPy uses Fortran style dimension ordering (as of November 2017) [lat,lon] = [1,0] @@ -25,17 +25,17 @@ # Create the source grid from memory with periodic dimension specified. lons = numpy.arange(5, 350.1, 10) lats = numpy.arange(-85, 85.1, 10) -srcgrid = ESMF.Grid(numpy.array([lons.size, lats.size]), - coord_sys=ESMF.CoordSys.SPH_DEG, - staggerloc=ESMF.StaggerLoc.CENTER, +srcgrid = esmpy.Grid(numpy.array([lons.size, lats.size]), + coord_sys=esmpy.CoordSys.SPH_DEG, + staggerloc=esmpy.StaggerLoc.CENTER, num_peri_dims=1, periodic_dim=0, pole_dim=1) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(lon) srcGridCoordLat = srcgrid.get_coords(lat) -slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = numpy.meshgrid(slons_par, slats_par, indexing='ij') @@ -46,17 +46,17 @@ # Create the dest grid from memory with periodic dimension specified. lons = numpy.arange(2.5, 357.6, 5) lats = numpy.arange(-87.5, 87.6, 5) -dstgrid = ESMF.Grid(numpy.array([lons.size, lats.size]), - coord_sys=ESMF.CoordSys.SPH_DEG, - staggerloc=ESMF.StaggerLoc.CENTER, +dstgrid = esmpy.Grid(numpy.array([lons.size, lats.size]), + coord_sys=esmpy.CoordSys.SPH_DEG, + staggerloc=esmpy.StaggerLoc.CENTER, num_peri_dims=1, periodic_dim=1, pole_dim=0) # Get and set the source grid coordinates. dstGridCoordLat = dstgrid.get_coords(lat) dstGridCoordLon = dstgrid.get_coords(lon) -dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = numpy.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -65,14 +65,14 @@ dstGridCoordLat[:] = latm # Create a field on the centers of the source grid with the mask applied. -srcfield = ESMF.Field(srcgrid, name="srcfield", staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name="srcfield", staggerloc=esmpy.StaggerLoc.CENTER) # Create a field on the centers of the source grid with the mask applied. -dstfield = ESMF.Field(dstgrid, name="dstfield", staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(dstgrid, name="xctfield", staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name="dstfield", staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(dstgrid, name="xctfield", staggerloc=esmpy.StaggerLoc.CENTER) -gridLon = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) # wave = lambda x,k: numpy.sin(x*k*numpy.pi/180.0) # srcfield.data[...] = numpy.outer(wave(slons_par,3), wave(slats_par,3)) + 2 @@ -90,20 +90,20 @@ # write regridding weights to file filename = "esmpy_example_weight_file.nc" -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: import os if os.path.isfile( os.path.join(os.getcwd(), filename)): os.remove(os.path.join(os.getcwd(), filename)) mg.barrier() -regrid = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # # create a regrid object from file -regrid = ESMF.RegridFromFile(srcfield, dstfield, filename) +regrid = esmpy.RegridFromFile(srcfield, dstfield, filename) # calculate the regridding from source to destination field dstfield = regrid(srcfield, dstfield) @@ -118,12 +118,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid Mesh Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) @@ -132,7 +132,7 @@ os.remove(os.path.join(os.getcwd(), filename)) # set to 1 to output results -# if ESMF.pet_count() == 0: +# if esmpy.pet_count() == 0: # import matplotlib.pyplot as plt # fig = plt.figure(1, (15, 6)) # fig.suptitle('ESMPy Periodic Grids', fontsize=14, fontweight='bold') diff --git a/src/addon/ESMPy/examples/regrid_from_file.py b/src/addon/ESMPy/examples/regrid_from_file.py index 0af92b238f..f68fb8edb2 100644 --- a/src/addon/ESMPy/examples/regrid_from_file.py +++ b/src/addon/ESMPy/examples/regrid_from_file.py @@ -7,46 +7,46 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "so_Omon_GISS-E2.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) import os -import ESMF +import esmpy # This call enables debug logging -# ESMF.Manager(debug=True) +# esmpy.Manager(debug=True) # Set up the DATADIR DATADIR = os.path.join(os.getcwd(), "examples/data") # Create a global grid from a GRIDSPEC formatted file -grid = ESMF.Grid(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), - filetype=ESMF.FileFormat.GRIDSPEC) +grid = esmpy.Grid(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), + filetype=esmpy.FileFormat.GRIDSPEC) # Create a field on the centers of the grid, with extra dimensions -srcfield = ESMF.Field(grid, staggerloc=ESMF.StaggerLoc.CENTER, ndbounds=[33, 2]) +srcfield = esmpy.Field(grid, staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) # Read the field data from file srcfield.read(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), variable="so", timeslice=2) # Create an ESMF formatted unstructured mesh with clockwise cells removed -mesh = ESMF.Mesh(filename=os.path.join(DATADIR, "mpas_uniform_10242_dual_counterclockwise.nc"), - filetype=ESMF.FileFormat.ESMFMESH) +mesh = esmpy.Mesh(filename=os.path.join(DATADIR, "mpas_uniform_10242_dual_counterclockwise.nc"), + filetype=esmpy.FileFormat.ESMFMESH) # Create a field on the nodes of the mesh -dstfield = ESMF.Field(mesh, meshloc=ESMF.MeshLoc.NODE, ndbounds=[33, 2]) +dstfield = esmpy.Field(mesh, meshloc=esmpy.MeshLoc.NODE, ndbounds=[33, 2]) dstfield.data[:] = 1e20 # compute the weight matrix for regridding -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # calculate the regridding from source to destination field dstfield = regrid(srcfield, dstfield) -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: print ("Fields created from file regridded successfully :)") diff --git a/src/addon/ESMPy/examples/test_examples.py b/src/addon/ESMPy/examples/test_examples.py new file mode 100644 index 0000000000..94bdf1a6c9 --- /dev/null +++ b/src/addon/ESMPy/examples/test_examples.py @@ -0,0 +1,77 @@ +# $Id$ + +""" +examples test file +""" + +import pytest + +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO +import esmpy.api.constants as constants +from esmpy.api.esmpymanager import Manager + +# Start up esmpy +mg = Manager(debug=True) + +if mg.pet_count == 1: + from esmpy.util.cache_data import cache_data_files + cache_data_files() + +class TestExamples(TestBase): + + def test_helloworld(self): + from . import hello_world + + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_field_read(self): + from . import field_read + + # only example, not in documentation + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_grid_create_peridim_mask(self): + from . import grid_create_peridim_mask + + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_grid_locstream_regrid(self): + from . import grid_locstream_regrid + + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_locstream_grid_regrid(self): + from . import locstream_grid_regrid + + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + def test_mesh_locstream_regrid(self): + from . import mesh_locstream_regrid + + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_read_write_weight_file(self): + from . import read_write_weight_file + + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_regrid_from_file(self): + from . import regrid_from_file + + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_ugrid_latlon_regrid(self): + from . import ugrid_latlon_regrid + + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + def test_ungridded_dimension_regrid(self): + from . import ungridded_dimension_regrid + + # this will currently never run because it isn't yet possible to run pytest with mpiexec + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=6, reason="test must be run with 6 cores") + def test_cubed_sphere_to_mesh_regrid(self): + from . import cubed_sphere_to_mesh_regrid + + # # datafile missing from repo + # def test_tripole_regrid(self): + # from . import tripole_regrid diff --git a/src/addon/ESMPy/examples/test_examples_download.py b/src/addon/ESMPy/examples/test_examples_download.py new file mode 100644 index 0000000000..ac6c18da48 --- /dev/null +++ b/src/addon/ESMPy/examples/test_examples_download.py @@ -0,0 +1,15 @@ +# $Id$ + +""" +examples data download +""" + +import sys + +from esmpy.util.cache_data import cache_data_files + +DATAURL = None +if len(sys.argv) > 1: + DATAURL = sys.argv[1] + +cache_data_files(DATAURL) diff --git a/src/addon/ESMPy/examples/tripole_regrid.py b/src/addon/ESMPy/examples/tripole_regrid.py index 9fd4371d45..5afdb72101 100644 --- a/src/addon/ESMPy/examples/tripole_regrid.py +++ b/src/addon/ESMPy/examples/tripole_regrid.py @@ -7,47 +7,47 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "GRIDSPEC_ACCESS1.nc")) # cache_data_file(os.path.join(DD, "tx0.1v2_070911.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) grid1 = "examples/data/GRIDSPEC_ACCESS1.nc" grid2 = "examples/data/tx0.1v2_070911.nc" # Create a grid from a GRIDSPEC formatted file -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.GRIDSPEC, +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname="so") # create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(grid, name='srcfield', staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(grid, name='srcfield', staggerloc=esmpy.StaggerLoc.CENTER) # create a tripole grid -tripole = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, +tripole = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True, add_mask=True, varname="grid_imask") # create fields on the center stagger locations of the tripole grid -dstfield = ESMF.Field(tripole, name='dstfield', meshloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(tripole, name='xctfield', meshloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(tripole, name='dstfield', meshloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(tripole, name='xctfield', meshloc=esmpy.StaggerLoc.CENTER) # create fields needed to analyze accuracy of conservative regridding -srcfracfield = ESMF.Field(grid, name='srcfracfield') -dstfracfield = ESMF.Field(tripole, name='dstfracfield') -srcareafield = ESMF.Field(grid, name='srcareafield') -dstareafield = ESMF.Field(tripole, name='dstareafield') +srcfracfield = esmpy.Field(grid, name='srcfracfield') +dstfracfield = esmpy.Field(tripole, name='dstfracfield') +srcareafield = esmpy.Field(grid, name='srcareafield') +dstareafield = esmpy.Field(tripole, name='dstareafield') # get the coordinate pointers and set the coordinates [lon,lat] = [0, 1] -gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) deg2rad = 3.14159/180 @@ -55,8 +55,8 @@ # get the coordinate pointers and set the coordinates [lon,lat] = [0, 1] -gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 10.0 + (gridXCoord*deg2rad)**2 + (gridYCoord*deg2rad)**2 @@ -64,9 +64,9 @@ # create an object to regrid data from the source to the destination field # NOTE: this example requires the unmapped_action flag to be set to IGNORE missing values due to masking -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.IGNORE, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.IGNORE, src_mask_values=numpy.array([0]), dst_mask_values=numpy.array([0]), src_frac_field=srcfracfield, @@ -96,14 +96,14 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) srcmass = helpers.reduce_val(srcmass, op=constants.Reduce.SUM) dstmass = helpers.reduce_val(dstmass, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes csrverr = numpy.abs(srcmass - dstmass) / dstmass diff --git a/src/addon/ESMPy/examples/ugrid_latlon_regrid.py b/src/addon/ESMPy/examples/ugrid_latlon_regrid.py index 47476e0417..89716d8906 100644 --- a/src/addon/ESMPy/examples/ugrid_latlon_regrid.py +++ b/src/addon/ESMPy/examples/ugrid_latlon_regrid.py @@ -6,12 +6,12 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) # cache_data_file(os.path.join(DD, "ne30np4-t2UGRID_nodual.nc")) # cache_data_file(os.path.join(DD, "aggregAtlanticESTOFS.nc")) -import ESMF +import esmpy import numpy def plot_error(field1, field2, uninitval): @@ -90,35 +90,35 @@ def plot_field(field2, uninitval): plt.show() # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) # these are for a new test using opendap, dataset has periodic failures.. # meshfile = "http://coastalmodeldev.data.noaa.gov/thredds/dodsC/aggregAtlanticESTOFS" meshfile = "examples/data/aggregAtlanticESTOFS.nc" -mesh = ESMF.Mesh(filename=meshfile, filetype=ESMF.FileFormat.UGRID, meshname='adcirc_mesh') +mesh = esmpy.Mesh(filename=meshfile, filetype=esmpy.FileFormat.UGRID, meshname='adcirc_mesh') # Create a global latlon grid from a SCRIP formatted file gridfile = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, +grid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True, is_sphere=True) # create a field on the element locations of the source mesh -srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE) +srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE) # create a field on the centers of the destination grid -dstfield = ESMF.Field(grid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(grid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(grid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(grid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER) # initialize the fields [lon,lat] = [0, 1] -srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=ESMF.MeshLoc.NODE) -srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=ESMF.MeshLoc.NODE) +srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=esmpy.MeshLoc.NODE) +srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=esmpy.MeshLoc.NODE) srcfield.data[...] = 2.0 + numpy.cos(numpy.radians(srcgridYCoord)[...])**2 * \ numpy.cos(2.0*numpy.radians(srcgridXCoord)[...]) -dstgridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -dstgridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +dstgridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +dstgridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 2.0 + numpy.cos(numpy.radians(dstgridYCoord)[...])**2 * \ numpy.cos(2.0*numpy.radians(dstgridXCoord)[...]) @@ -126,15 +126,15 @@ def plot_field(field2, uninitval): dstfield.data[...] = uninitval # create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: print ("ESMPy UGRID to LatLon Regridding Example") # plot_error(xctfield, dstfield, uninitval=uninitval) @@ -154,11 +154,11 @@ def plot_field(field2, uninitval): # dstfield.data[...] = uninitval # # create an object to regrid data from the source to the destination field -# regrid = ESMF.Regrid(srcfield, dstfield, -# regrid_method=ESMF.RegridMethod.BILINEAR, -# unmapped_action=ESMF.UnmappedAction.IGNORE) +# regrid = esmpy.Regrid(srcfield, dstfield, +# regrid_method=esmpy.RegridMethod.BILINEAR, +# unmapped_action=esmpy.UnmappedAction.IGNORE) # # # do the regridding from source to destination field -# dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +# dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # # plot_field(dstfield, uninitval=uninitval) \ No newline at end of file diff --git a/src/addon/ESMPy/examples/ungridded_dimension_regrid.py b/src/addon/ESMPy/examples/ungridded_dimension_regrid.py index 41f21e3d49..f4ab910df0 100644 --- a/src/addon/ESMPy/examples/ungridded_dimension_regrid.py +++ b/src/addon/ESMPy/examples/ungridded_dimension_regrid.py @@ -7,18 +7,18 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) # cache_data_file(os.path.join(DD, "T42_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) grid1 = "examples/data/ll2.5deg_grid.nc" grid2 = "examples/data/T42_grid.nc" @@ -28,39 +28,39 @@ time = 5 # Create a uniform global latlon grid from a SCRIP formatted file -srcgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, +srcgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) # Create a uniform global latlon grid from a SCRIP formatted file -dstgrid = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, +dstgrid = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) # Create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(srcgrid, name='srcfield', - staggerloc=ESMF.StaggerLoc.CENTER, +srcfield = esmpy.Field(srcgrid, name='srcfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create a field on the center stagger locations of the destination grid -dstfield = ESMF.Field(dstgrid, name='dstfield', - staggerloc=ESMF.StaggerLoc.CENTER, +dstfield = esmpy.Field(dstgrid, name='dstfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create a field on the center stagger locations of the destination grid -xctfield = ESMF.Field(dstgrid, name='xctfield', - staggerloc=ESMF.StaggerLoc.CENTER, +xctfield = esmpy.Field(dstgrid, name='xctfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create fields needed to analyze accuracy of conservative regridding -srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') -dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') -srcareafield = ESMF.Field(srcgrid, name='srcareafield') -dstareafield = ESMF.Field(dstgrid, name='dstareafield') +srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') +dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') +srcareafield = esmpy.Field(srcgrid, name='srcareafield') +dstareafield = esmpy.Field(dstgrid, name='dstareafield') # Get the coordinate pointers and initialize the source field [lon,lat] = [0, 1] -gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) deg2rad = 3.14159/180 @@ -73,8 +73,8 @@ (gridYCoord*deg2rad)**2 # Get the coordinate pointers and initialize the exact solution -gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) for level in range(levels): for timestep in range(time): @@ -87,9 +87,9 @@ dstfield.data[...] = 1e20 # Create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) @@ -126,14 +126,14 @@ csrverr = numpy.abs(srcmass - dstmass) / dstmass # Handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) srcmass = helpers.reduce_val(srcmass, op=constants.Reduce.SUM) dstmass = helpers.reduce_val(dstmass, op=constants.Reduce.SUM) # Output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes csrverr = numpy.abs(srcmass - dstmass) / dstmass diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml new file mode 100644 index 0000000000..91a8ecb838 --- /dev/null +++ b/src/addon/ESMPy/pyproject.toml @@ -0,0 +1,38 @@ +[build-system] +requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning"] +build-backend = "setuptools.build_meta" + +[project] +name = "ESMPy" +description = "ESMF Python interface" +# readme = "README.md" +maintainers = [{author = "ESMF Core Team", email = "esmf_support@ucar.edu"}] +requires-python = ">=3.7" +license = {text = "University of Illinois-NCSA"} +dependencies = [ + "numpy", + "pytest-json-report", + 'importlib-metadata; python_version<"3.8"', +] +dynamic = ["version"] + +[tool.setuptools-git-versioning] +enabled = true +template = "{tag}" +dev_template = "{tag}" +dirty_template = "{tag}" +starting_version = "8.4.0" # this is a backup for pip <= 22.0 where git-versioning doesn't work + +[tool.dynamic] +version = "placeholder" # this is a placeholder for the version pulled with git-versioning + +[tool.setuptools.packages.find] +where = ["src"] +exclude = ["doc*"] + +[tool.pytest.ini_options] +testpaths = [ + "src/esmpy/test/test_api", + "examples/test_examples.py", + "src/esmpy/test/regrid_from_file/test_regrid_from_file.py", +] diff --git a/src/addon/ESMPy/setup.py b/src/addon/ESMPy/setup.py deleted file mode 100644 index d4f53c3191..0000000000 --- a/src/addon/ESMPy/setup.py +++ /dev/null @@ -1,278 +0,0 @@ -# $Id$ - -import os -import sys -from distutils.core import setup, Command -from distutils.util import get_platform -import subprocess - - -def download_test_data(func): - def wrapper(self): - update_system_path() - from ESMF.util.cache_data import cache_data_files - cache_data_files() - return func(self) - return wrapper - - -def update_system_path(): - if 'src' not in sys.path: - sys.path.insert(0, 'src') - - -class AbstractESMFCommand(Command): - user_options = [] - - def initialize_options(self): - self.cwd = None - - def finalize_options(self): - self.cwd = os.getcwd() - - def _validate_(self): - if os.getcwd() != self.cwd: - raise RuntimeError('Must be in package root: %s' % self.cwd) - - -class AbstractESMFNoseCommand(AbstractESMFCommand): - _nose_attrs = None - _nose_base_attrs = ['!slow'] - _nose_parallel = False - _nose_flags = None - _default_target = os.path.join('src', 'ESMF') - _needs_data = False - - def run(self): - self._validate_() - cmd = self.nosetests_command() - subprocess.check_call(cmd) - - @classmethod - def nosetests_command(cls): - ret = ['nosetests', '-vs', '--with-xunit'] - if not isinstance(cls._nose_attrs, type(None)): - nose_attrs = cls._nose_base_attrs + cls._nose_attrs - nose_attrs = ','.join(nose_attrs) - cmd_nose_attrs = ['-a', nose_attrs] - ret = ret + cmd_nose_attrs - - if cls._nose_parallel: - # Needed for ESMF constants import - sys.path.append('src') - - from ESMF.api import constants - - # -np is used in place of -n for esmf mpirun.srun wrapper - mpisyntax = "-n"; - if "mpirun.srun" in constants._ESMF_MPIRUN: - mpisyntax = "-np"; - mpirun_prefix = [constants._ESMF_MPIRUN, mpisyntax, str(constants._ESMF_MPIRUN_NP)] - ret = mpirun_prefix + ret - - if not isinstance(cls._nose_flags, type(None)): - ret.append(cls._nose_flags) - ret.append(cls._default_target) - return ret - - -class BuildCommand(AbstractESMFCommand): - description = "build: will build the ESMF package" - user_options = [('ESMFMKFILE=', 'e', - "Location of esmf.mk for the ESMF installation")] - - def initialize_options(self): - self.cwd = None - self.ESMFMKFILE = None - SITEDIR = os.system('%s -m site --user-site' % sys.executable) - self.build_base = 'build' - self.build_lib = None - self.plat_name = None - - def finalize_options(self): - self.cwd = os.getcwd() - if isinstance(self.ESMFMKFILE, type(None)): - self.ESMFMKFILE = os.getenv('ESMFMKFILE') - if isinstance(self.build_lib, type(None)): - self.build_lib = os.path.join(self.build_base, 'lib') - if isinstance(self.plat_name, type(None)): - self.plat_name = get_platform() - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - - # Create "esmfmkfile.py" file holding the path to the ESMF "esmf.mk" file - if not isinstance(self.ESMFMKFILE, type(None)): - f = open(os.path.join('src', 'ESMF', 'interface', 'esmfmkfile.py'), 'w') - f.write('ESMFMKFILE = "%s"' % self.ESMFMKFILE) - f.close() - - # Attempt to load ESMF. - update_system_path() - import ESMF.interface.loadESMF - - -class CleanCommand(AbstractESMFCommand): - description = "clean: will remove all libraries, log and output files" - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - os.system('find . -name "*.pyc" -exec rm -f {} \;') - os.system('find . -name "*ESMF_LogFile*" -exec rm -f {} \;') - os.system('find . -name "*.log" -exec rm -f {} \;') - os.system('find . -name "*.vtk" -exec rm -f {} \;') - os.system('rm src/ESMF/interface/esmfmkfile.py') - os.system('rm -rf build') - os.system('rm -rf dist') - os.system('rm -rf src/ESMF/test/regrid_from_file/data') - os.system('rm -rf examples/data') - - -class DustCommand(AbstractESMFCommand): - description = "dust: will remove log and output files" - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - os.system('find . -name "*ESMF_LogFile*" -exec rm -f {} \;') - os.system('find . -name "*.log" -exec rm -f {} \;') - os.system('find . -name "*.vtk" -exec rm -f {} \;') - os.system('find . -name "*.pyc" -exec rm -f {} \;') - - -class TestCommand(AbstractESMFNoseCommand): - description = "run serial tests" - _nose_attrs = ['!parallel'] - - -class TestParallelCommand(AbstractESMFNoseCommand): - description = "run parallel tests" - _nose_attrs = ['!serial'] - _nose_parallel = True - - -class TestRegridCommand(AbstractESMFNoseCommand): - description = "run test_regrid.py" - _default_target = os.path.join('src', 'ESMF', 'test', 'test_api', 'test_regrid.py') - - -class TestRegridParallelCommand(TestRegridCommand): - description = "test regrid parallel" - _nose_attrs = ['!serial'] - _nose_parallel = True - -class TestExamplesCommand(AbstractESMFNoseCommand): - description = "run examples in serial" - _nose_attrs = ['!parallel'] - _default_target = os.path.join('examples', 'exampletest.py') - - @download_test_data - def run(self): - update_system_path() - AbstractESMFNoseCommand.run(self) - -class TestExamplesParallelCommand(TestExamplesCommand): - description = "run examples in parallel" - _nose_attrs = ['!serial'] - _nose_parallel = True - -class TestExamplesDryrunCommand(TestExamplesCommand): - description = "collect example tests only and download data" - _nose_flags = '--collect-only' - - -class TestRegridFromFileCommand(AbstractESMFCommand): - description = "test regrid from file" - _filename = 'run_regrid_from_file.py' - _flags = None - - def run(self): - original_pp = os.environ.get('PYTHONPATH', '') - path = os.path.join(os.getcwd(), 'src') - os.environ['PYTHONPATH'] = '{0}:{1}'.format(path, original_pp) - self._validate_() - target = os.path.join('src', 'ESMF', 'test', 'regrid_from_file', self._filename) - cmd = [sys.executable, target] - if not isinstance(self._flags, type(None)): - cmd.append(self._flags) - subprocess.check_call(cmd) - - -class TestRegridFromFileDryrunCommand(TestRegridFromFileCommand): - description = "test regrid from file dryrun" - _filename = 'run_regrid_from_file_dryrun.py' - - -class TestRegridFromFileParallelCommand(TestRegridFromFileCommand): - description = "test regrid from file parallel" - _filename = 'run_regrid_from_file.py' - _flags = '--parallel' - - def run(self): - TestRegridFromFileCommand.run(self) - - -class TestAllCommand(AbstractESMFCommand): - description = "run serial, parallel, and example tests" - - @download_test_data - def run(self): - self._validate_() - to_run = [TestCommand, TestParallelCommand, TestExamplesCommand, TestExamplesParallelCommand] - for t in to_run: - cmd = t.nosetests_command() - subprocess.check_call(cmd) - - -# Get package structure -def _get_dot_(path, root='src'): - ret = [] - path_parse = path - while True: - path_parse, tail = os.path.split(path_parse) - if tail == root: - break - else: - ret.append(tail) - ret.reverse() - return '.'.join(ret) - - -src_path = os.path.join('src', 'ESMF') -packages = [] -for dirpath, dirnames, filenames in os.walk(src_path): - if '__init__.py' in filenames: - package = _get_dot_(dirpath) - packages.append(package) - -# TODO: build doc command -# TODO: remove duplicated metadata: here and src/ESMF/__init__.py -setup(name="ESMPy", - version="8.4.0", - description="ESMF Python interface", - author="University Corporation for Atmospheric Research, \ - Massachusetts Institute of Technology, \ - Geophysical Fluid Dynamics Laboratory, \ - University of Michigan, \ - National Centers for Environmental Prediction, \ - Los Alamos National Laboratory, \ - Argonne National Laboratory, \ - NASA Goddard Space Flight Center", - license="University of Illinois-NCSA", - author_email="esmf_support@ucar.edu", - url="http://earthsystemmodeling.org/esmpy/", - packages=packages, - package_dir={'': 'src'}, - cmdclass={'build': BuildCommand, - 'clean': CleanCommand, - 'dust': DustCommand, - 'test': TestCommand, - 'test_all': TestAllCommand, - 'test_parallel': TestParallelCommand, - 'test_examples': TestExamplesCommand, - 'test_examples_dryrun': TestExamplesDryrunCommand, - 'test_examples_parallel': TestExamplesParallelCommand, - 'test_regrid': TestRegridCommand, - 'test_regrid_from_file': TestRegridFromFileCommand, - 'test_regrid_from_file_dryrun': TestRegridFromFileDryrunCommand, - 'test_regrid_parallel': TestRegridParallelCommand, - 'test_regrid_from_file_parallel': TestRegridFromFileParallelCommand}) diff --git a/src/addon/ESMPy/src/ESMF/test/base_test.py b/src/addon/ESMPy/src/ESMF/test/base_test.py deleted file mode 100644 index 1a8fff0c7e..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/base_test.py +++ /dev/null @@ -1,28 +0,0 @@ -import unittest -from ESMF.test.base import TestBase -import numpy as np -from ESMF import Manager - - -class Test(TestBase): - - def setup(self): - mg = Manager() - # mg.barrier() - - def test_assertNumpyAll_bad_mask(self): - arr = np.ma.array([1,2,3],mask=[True,False,True]) - arr2 = np.ma.array([1,2,3],mask=[False,True,False]) - self.assertRaises(AssertionError, lambda: self.assertNumpyAll(arr,arr2)) - - def test_assertNumpyAll_type_differs(self): - arr = np.ma.array([1,2,3],mask=[True,False,True]) - arr2 = np.array([1,2,3]) - self.assertRaises(AssertionError, lambda: self.assertNumpyAll(arr,arr2)) - - def tearDown(self): - mg = Manager() - # mg.barrier() - -if __name__ == "__main__": - unittest.main() \ No newline at end of file diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py deleted file mode 100644 index c11335bf6a..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py +++ /dev/null @@ -1,93 +0,0 @@ -# $Id$ - -""" -Reads each line of a control file where each line corresponds to one test -case. Parses each line and calls a test subroutine that creates meshes from -source and destination NetCDF files, creates an analytic field across the -source mesh, regrids the source mesh to the grid of the destination mesh, -and compares the analytic field of the resulting regridded mesh to that of the -source mesh. -""" - -import sys -import os -import traceback - -try: - import ESMF -except: - raise ImportError('The ESMF library cannot be found!') -from ESMF.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR -from ESMF.test.regrid_from_file.run_regrid_from_file_dryrun import cache_data_files_for_test_cases -from ESMF.test.regrid_from_file.regrid_check import regrid_check -from ESMF.test.regrid_from_file.read_test_cases_from_control_file import read_control_file - -# Start up ESMF and run regrid test for each line of options -# read from a control file. Retrieve data files for each test from a remote -# server if they do not exist locally. -# Start up ESMF. -mg = ESMF.Manager(debug=True) - -parallel = False -if ESMF.pet_count() > 1: - parallel = True - -# Read the test case parameters from the control file. - -print('Reading control file...') -test_cases = read_control_file() -if (ESMF.local_pet() == 0): - # Retrieve the data files needed for the test cases from the remote server. - print('Retrieving regrid_from_file data...') - status_ok = cache_data_files_for_test_cases(test_cases) - -# For each test case line from the control file parse the line and call -# the test subroutine. -for ctr, test_case in enumerate(test_cases, start=1): - print('Running {0} of {1} regrid_from_file test cases...'.format(ctr, len(test_cases))) - (src_fname, dst_fname, regrid_method, options, - itrp_mean_err, itrp_max_err, csrv_err) = test_case - test_str = 'Regrid %s to %s as %s with %s itrp_mean_err=%f, itrp_max_err=%f, and csrv_err=%f' % (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) - print ('\n' + test_str + ' - START\n') - src_fname_full = os.path.join(DATA_SUBDIR, src_fname) - dst_fname_full = os.path.join(DATA_SUBDIR, dst_fname) - - if parallel: - # set a barrier to wait for files to be downloaded - mg.barrier() - - # run the data file retrieval and regridding through try/except - correct = False - try: - correct = regrid_check(src_fname_full, dst_fname_full, regrid_method, - options, itrp_mean_err, itrp_max_err, csrv_err) - except: - print ("Regridding ERROR:\n") - traceback.print_exc(file=sys.stdout) - - skip = False - for i in range(ESMF.pet_count()): - for line in open("PET"+str(i)+".ESMF_LogFile"): - if "ESMF_NETCDF not defined when lib was compiled" in line or \ - "File format is not supported" in line: - # set skip - skip = True - - # print the file - print ('\n***NOTE*** The log files must be deleted in this test case, they are printed below for future reference\n') - if skip: - for line in open("PET"+str(i)+".ESMF_LogFile"): - print (line) - - # clean the log files - for i in range(ESMF.pet_count()): - os.system("echo ' ' > PET"+str(i)+".ESMF_LogFile") - - print ("\nPET: " + str(ESMF.local_pet()) + " - " + test_str + " - FINISH\n") - - if skip: - print ('RESULT: SKIP\n\n') - elif correct: - print ('RESULT: PASS\n\n') - else: - print ('RESULT: FAIL\n\n') diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py deleted file mode 100644 index 3c4277dad2..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Constants required for the regrid from file tests. -""" -import os -try: - import ESMF -except: - raise ImportError('The ESMF library cannot be found!') -# -TEST_REGRID_DIR = 'src/ESMF/test/regrid_from_file/' -CONTROL_FNAME = 'regrid_test_data.txt' -DATA_SUBDIR = os.path.join(TEST_REGRID_DIR,'data/') -DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' -UNINITVAL = 422397696. -EPSILON = 1E-30 -# -regrid_method_map = {"bilinear" : ESMF.RegridMethod.BILINEAR, - "patch" : ESMF.RegridMethod.PATCH, - "conserve" : ESMF.RegridMethod.CONSERVE, - "neareststod" : ESMF.RegridMethod.NEAREST_STOD, - "nearestdtos" : ESMF.RegridMethod.NEAREST_DTOS} -file_type_map = {"VTK" : ESMF.FileFormat.VTK, - "SCRIP" : ESMF.FileFormat.SCRIP, - "ESMF" : ESMF.FileFormat.ESMFMESH, - "ESMFMESH" : ESMF.FileFormat.ESMFMESH, - "ESMFGRID" : ESMF.FileFormat.ESMFGRID, - "UGRID" : ESMF.FileFormat.UGRID, - "GRIDSPEC" : ESMF.FileFormat.GRIDSPEC} -pole_method_map = {"none" : ESMF.PoleMethod.NONE, - "all" : ESMF.PoleMethod.ALLAVG, - "teeth" : ESMF.PoleMethod.TEETH} diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py deleted file mode 100644 index e219c1d865..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py +++ /dev/null @@ -1,58 +0,0 @@ -# $Id$ - -import os -import sys - -import ESMF.api.constants as constants -from ESMF.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR - - -parallel = False -if len(sys.argv) > 1: - if "--parallel" in sys.argv[1]: - parallel = True - -# run utests, pipe to file -rtestfile=os.path.join(TEST_REGRID_DIR, 'regrid_check_driver.py') -rtestoutfile='run_regrid_from_file.log' -num_proc = 1 -if parallel: - # make sure we are not in uni mode - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise ValueError("Cannot run parallel tests when ESMF is built with ESMF_COMM=mpiuni") - - # setup the constants - rtestoutfile='run_regrid_from_file_parallel.log' - -constants._ESMF_MPIRUN + " -n " -os.system(constants._ESMF_MPIRUN + " -n " + str(constants._ESMF_MPIRUN_NP) + " python " + rtestfile + " > " + rtestoutfile + " 2>&1") - -# traverse output, find number of pass and fail and print report -RTEST = open(rtestoutfile) - -rtpass = 0 -rtfail = 0 -rtskip = 0 - -for line in RTEST: - if 'RESULT: PASS' in line: - rtpass=rtpass+1 - if 'RESULT: FAIL' in line: - rtfail=rtfail+1 - if 'RESULT: SKIP' in line: - rtskip=rtskip+1 - -RTEST.close() - -rtpass = rtpass/num_proc -rtfail = rtfail/num_proc -rtskip = rtskip/num_proc - -print("Regrid from file test results: "+rtestoutfile) -print("PASS = "+str(int(rtpass))) -print("FAIL = "+str(int(rtfail))) -print("SKIP = "+str(int(rtskip))) - -if rtpass == 0 and rtfail == 0 and rtskip == 0: - print(rtestoutfile+":") - os.system("tail "+rtestoutfile) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py deleted file mode 100644 index e8c7223d4d..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -vm unit test file -""" - -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr - -class TestVM(TestBase): - @attr('parallel') - def test_vm_broadcast(self): - mg = Manager() - - bcst = np.ones(4, dtype=np.float64) - if mg.local_pet != 0: - bcst[:] = 2 - - if mg.local_pet == 0: - assert(np.all(bcst == 1)) - else: - assert(np.all(bcst == 2)) - - mg.barrier() - mg._broadcast_(bcst, 4) - mg.barrier() - assert(np.all(bcst == 1)) - - mg.barrier() - - @attr('parallel') - def test_vm_reduce(self): - send = np.ones(4, dtype=np.float64) - recv = np.zeros(4, dtype=np.float64) - - mg = Manager() - - mg.barrier() - mg._reduce_(send, recv, 4, Reduce.SUM, 0) - mg.barrier() - - if mg.local_pet == 0: - assert(np.all(recv == mg.pet_count)) - else: - assert(np.all(recv == 0)) - - mg.barrier() diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/esmpy/__init__.py similarity index 68% rename from src/addon/ESMPy/src/ESMF/__init__.py rename to src/addon/ESMPy/src/esmpy/__init__.py index 9aee630788..a7f90a2a3e 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/esmpy/__init__.py @@ -15,9 +15,9 @@ can be found in the `ESMF Reference Manual `_. -ESMPy provides a :class:`~ESMF.api.grid.Grid` to represent single-tile logically -rectangular coordinate data, a :class:`~ESMF.api.mesh.Mesh` for unstructured -coordinates, and a :class:`~ESMF.api.locstream.LocStream` for collections of +ESMPy provides a :class:`~esmpy.api.grid.Grid` to represent single-tile logically +rectangular coordinate data, a :class:`~esmpy.api.mesh.Mesh` for unstructured +coordinates, and a :class:`~esmpy.api.locstream.LocStream` for collections of unconnected points like observational data streams. ESMPy supports bilinear, nearest neighbor, higher order patch recovery, first-order conservative and second-order conservative regridding. There is @@ -26,7 +26,7 @@ spherical coordinates and extrapolate data to points outside of the destination domain. Regridding on the sphere takes place in 3D Cartesian space, so the pole problem is not an issue as it commonly is with many Earth system grid remapping -softwares. :class:`~ESMF.api.grid.Grid` and :class:`~ESMF.api.mesh.Mesh` +softwares. :class:`~esmpy.api.grid.Grid` and :class:`~esmpy.api.mesh.Mesh` objects can be created in 2D or 3D space, and 3D conservative regridding is fully supported. @@ -64,35 +64,56 @@ data values. """ -#### IMPORT LIBRARIES ######################################################### +#### SET UP SOME INFO ######################################################### -from ESMF.api.esmpymanager import * -from ESMF.api.grid import * -from ESMF.api.mesh import * -from ESMF.api.locstream import * -from ESMF.api.field import * -from ESMF.api.regrid import * -from ESMF.api.constants import * -from ESMF.util.helpers import * -from ESMF.api.constants import _ESMF_VERSION +import esmpy.api.constants as constants -# for testing -from ESMF.util.decorators import expected_failure +import sys -#### SET UP SOME INFO ######################################################### +msg = "" -__name__ = "ESMF" -__description__ = "ESMF Python interface" -__author__ = "University Corporation for Atmospheric Research, " + \ - "Massachusetts Institute of Technology, " + \ - "Geophysical Fluid Dynamics Laboratory, " + \ - "University of Michigan, " + \ - "National Centers for Environmental Prediction, " + \ - "Los Alamos National Laboratory, " + \ - "Argonne National Laboratory, " + \ - "NASA Goddard Space Flight Center" -__license__ = "University of Illinois-NCSA" -__release__ = _ESMF_VERSION -__version__ = _ESMF_VERSION +if (sys.version_info >= (3,8)): + # this requires Python 3.8 or higher + import importlib.metadata as ilm + + msg = ilm.metadata("ESMPy") +else: + # pre Python 3.8, not sure how far yet + from pkg_resources import get_distribution + try: + pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') + except: + try: + pkgInfo = get_distribution('ESMPy').get_metadata('PKG-INFO') + except: + raise ImportError("Could not find METADATA or PKG-INFO for ESMPy") + + # parse it using email.Parser + from email import message_from_string + msg = message_from_string(pkgInfo) + +# set the private metadata +__name__ = msg["Name"] +__version__ = msg["Version"] +constants._ESMPY_VERSION = __version__ # required to check against ESMF_VERSION in loadESMF +__license__ = msg["License"] +__email__ = msg["Maintainer-email"] +__description__ = msg["Summary"] +__requires__ = msg["Requires-Dist"] +__requires_python__ = msg["Requires-Python"] +# these don't seem to work with setuptools pyproject.toml +__author__ = msg["Author"] +__homepage__ = msg["Home-page"] +__obsoletes__ = msg["obsoletes"] + +#### IMPORT LIBRARIES ######################################################### +from esmpy.api.esmpymanager import * +from esmpy.api.grid import * +from esmpy.api.mesh import * +from esmpy.api.locstream import * +from esmpy.api.field import * +from esmpy.api.regrid import * +from esmpy.api.constants import * +from esmpy.util.helpers import * diff --git a/src/addon/ESMPy/src/ESMF/api/__init__.py b/src/addon/ESMPy/src/esmpy/api/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/api/__init__.py rename to src/addon/ESMPy/src/esmpy/api/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/api/constants.py b/src/addon/ESMPy/src/esmpy/api/constants.py similarity index 83% rename from src/addon/ESMPy/src/ESMF/api/constants.py rename to src/addon/ESMPy/src/esmpy/api/constants.py index 98fa1c2fc8..87f6abac97 100644 --- a/src/addon/ESMPy/src/ESMF/api/constants.py +++ b/src/addon/ESMPy/src/esmpy/api/constants.py @@ -2,7 +2,10 @@ import numpy as np -from ESMF.util.enum import IntEnum +from esmpy.util.enum import IntEnum + +# Test exhaustive parameter +esmpy_test_exhaustive=False # error message _errmsg = 'Please check the log files (named "*ESMF_LogFile").' @@ -38,6 +41,9 @@ # ESMF_NETCDF _ESMF_NETCDF = False +# ESMF_NETCDF +_ESMF_PIO = False + # ESMF_COMM _ESMF_COMM = None _ESMF_COMM_MPIUNI = -1 @@ -45,6 +51,10 @@ # ESMF_VERSION _ESMF_VERSION = None +# ESMPY_VERSION, this is required to avoid a circular import in loadESMF when +# checking that the ESMF_VERSION matches esmpy.__version__ +_ESMPY_VERSION = None + # ESMF_MPIRUN _ESMF_MPIRUN = None _ESMF_MPIRUN_NP = None @@ -54,33 +64,33 @@ # CoordSys class CoordSys(IntEnum): """ - This flag indicates the coordinate system of a :class:`~ESMF.api.grid.Grid`. This value is + This flag indicates the coordinate system of a :class:`~esmpy.api.grid.Grid`. This value is useful both to indicate to other users the type of the coordinates, but also to control how the coordinates are interpreted in - regridding methods (e.g. :class:`~ESMF.api.regrid.Regrid`). + regridding methods (e.g. :class:`~esmpy.api.regrid.Regrid`). """ INVALID = -2 UNINIT = -1 CART = 0 """ Cartesian coordinate system. In this system, the Cartesian - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: x, y, z. (e.g. using coord_dim=1 in - :class:`~ESMF.api.grid.Grid.get_coords()` references the y dimension) + :class:`~esmpy.api.grid.Grid.get_coords()` references the y dimension) """ SPH_DEG = 1 """ Spherical coordinates in degrees. In this system, the spherical - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: longitude, latitude, radius. (E.g. using - coord_dim=1 in :class:`~ESMF.api.grid.:class:`~ESMF.api.grid.Grid.get_coords()`` references the latitude dimension). + coord_dim=1 in :class:`~esmpy.api.grid.:class:`~esmpy.api.grid.Grid.get_coords()`` references the latitude dimension). """ SPH_RAD = 2 """ Spherical coordinates in radians. In this system, the spherical - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: longitude, latitude, radius. (E.g. using - coord_dim=1 in :class:`~ESMF.api.grid.Grid.get_coords()` references the latitude dimension). + coord_dim=1 in :class:`~esmpy.api.grid.Grid.get_coords()` references the latitude dimension). """ # DecompFlag @@ -153,7 +163,7 @@ class ExtrapMethod(IntEnum): # FileFormat class FileFormat(IntEnum): """ - The :class:`~ESMF.api.grid.Grid` and :class:`~ESMF.api.mesh.Mesh` objects + The :class:`~esmpy.api.grid.Grid` and :class:`~esmpy.api.mesh.Mesh` objects may be created from specifications in a NetCDF data file. This flag indicates the format of the data file. """ @@ -200,9 +210,9 @@ class FileMode(IntEnum): # GridItem class GridItem(IntEnum): """ - The :class:`~ESMF.api.grid.Grid` can contain other kinds of data besides coordinates. This - data is referred to as :class:`~ESMF.api.grid.Grid` "items". Some items may be used - for calculations involving the :class:`~ESMF.api.grid.Grid`. + The :class:`~esmpy.api.grid.Grid` can contain other kinds of data besides coordinates. This + data is referred to as :class:`~esmpy.api.grid.Grid` "items". Some items may be used + for calculations involving the :class:`~esmpy.api.grid.Grid`. """ INVALID = -2 UNINIT = -1 @@ -260,11 +270,11 @@ class LogKind(IntEnum): # MeshElemType class MeshElemType(IntEnum): """ - A :class:`~ESMF.api.mesh.Mesh` can be constructed from a combination of different elements. - The type of elements that can be used in a :class:`~ESMF.api.mesh.Mesh` depends on the - parametric dimension of the :class:`~ESMF.api.mesh.Mesh`, which is set during :class:`~ESMF.api.mesh.Mesh` - creation. The following are the valid :class:`~ESMF.api.mesh.Mesh` element types for each - valid :class:`~ESMF.api.mesh.Mesh` parametric dimension (2D or 3D). + A :class:`~esmpy.api.mesh.Mesh` can be constructed from a combination of different elements. + The type of elements that can be used in a :class:`~esmpy.api.mesh.Mesh` depends on the + parametric dimension of the :class:`~esmpy.api.mesh.Mesh`, which is set during :class:`~esmpy.api.mesh.Mesh` + creation. The following are the valid :class:`~esmpy.api.mesh.Mesh` element types for each + valid :class:`~esmpy.api.mesh.Mesh` parametric dimension (2D or 3D). """ TRI = 3 """ @@ -286,15 +296,15 @@ class MeshElemType(IntEnum): # MeshLoc class MeshLoc(IntEnum): """ - The :class:`~ESMF.api.mesh.Mesh` location used to hold :class:`~ESMF.api.field.Field` data. + The :class:`~esmpy.api.mesh.Mesh` location used to hold :class:`~esmpy.api.field.Field` data. """ NODE = 0 """ - The nodes of the :class:`~ESMF.api.mesh.Mesh`. + The nodes of the :class:`~esmpy.api.mesh.Mesh`. """ ELEMENT = 1 """ - The elements of the :class:`~ESMF.api.mesh.Mesh`. + The elements of the :class:`~esmpy.api.mesh.Mesh`. """ # NormType @@ -323,7 +333,7 @@ class NormType(IntEnum): class PoleKind(IntEnum): """ This type describes the type of connection that occurs at the pole of a - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ NONE = 0 """ @@ -343,12 +353,12 @@ class PoleKind(IntEnum): class PoleMethod(IntEnum): """ Indicates which type of artificial pole to construct on the source - :class:`~ESMF.api.grid.Grid` for regridding. + :class:`~esmpy.api.grid.Grid` for regridding. """ NONE = 0 """ No pole. Destination points which lie above the top or below the bottom row - of the source :class:`~ESMF.api.grid.Grid` won't be mapped. + of the source :class:`~esmpy.api.grid.Grid` won't be mapped. """ ALLAVG = 1 """ @@ -371,11 +381,11 @@ class PoleMethod(IntEnum): TEETH = 3 """ No new pole point is constructed, instead the holes at the poles are filled - by constructing triangles across the top and bottom row of the source :class:`~ESMF.api.grid.Grid`. + by constructing triangles across the top and bottom row of the source :class:`~esmpy.api.grid.Grid`. This can be useful because no averaging occurs, however, because the top and bottom of the sphere are now flat, for a big enough mismatch between the size of the destination and source pole holes, some destination points may - still not be able to be mapped to the source :class:`~ESMF.api.grid.Grid`. + still not be able to be mapped to the source :class:`~esmpy.api.grid.Grid`. """ # Region @@ -399,7 +409,7 @@ class Reduce(IntEnum): # Region class Region(IntEnum): """ - Specify various regions in the data layout of a :class:`~ESMF.api.field.Field` object. + Specify various regions in the data layout of a :class:`~esmpy.api.field.Field` object. """ TOTAL = 0 """ @@ -408,7 +418,7 @@ class Region(IntEnum): SELECT = 1 """ An operation applies to a select portion of the domain. One use of this is - to specify that the portions of a :class:`~ESMF.api.field.Field` that are not mapped in a regridding + to specify that the portions of a :class:`~esmpy.api.field.Field` that are not mapped in a regridding operation should retain their original value (as opposed to being initialized to 0). """ @@ -448,10 +458,10 @@ class RegridMethod(IntEnum): is calculated as the weighted sum of the values of the source cells that it overlaps. The weights are determined by the amount the source cell overlaps the destination cell. This method requires corner coordinate values to be - provided in the :class:`~ESMF.api.grid.Grid`. It currently only works for - :class:`Fields `s created on the - :class:`~ESMF.api.grid.Grid` center stagger or - the :class:`~ESMF.api.mesh.Mesh` element location. + provided in the :class:`~esmpy.api.grid.Grid`. It currently only works for + :class:`Fields `s created on the + :class:`~esmpy.api.grid.Grid` center stagger or + the :class:`~esmpy.api.mesh.Mesh` element location. """ NEAREST_STOD = 3 """ @@ -482,18 +492,18 @@ class RegridMethod(IntEnum): mininum value in the source field is 0.0, then it's possible that after regridding with the second-order method, the destination field will contain values less than 0.0. This method requires corner coordinate values to be - provided in the :class:`~ESMF.api.grid.Grid`. It currently only works for - :class:`Fields `s created on the - :class:`~ESMF.api.grid.Grid` center stagger or - the :class:`~ESMF.api.mesh.Mesh` element location. + provided in the :class:`~esmpy.api.grid.Grid`. It currently only works for + :class:`Fields `s created on the + :class:`~esmpy.api.grid.Grid` center stagger or + the :class:`~esmpy.api.mesh.Mesh` element location. """ # StaggerLoc class StaggerLoc(IntEnum): """ - In the :class:`~ESMF.api.grid.Grid` class, data can be located at different positions in a - :class:`~ESMF.api.grid.Grid` cell. When setting or retrieving coordinate data the stagger - location is specified to tell the :class:`~ESMF.api.grid.Grid` method from where in the + In the :class:`~esmpy.api.grid.Grid` class, data can be located at different positions in a + :class:`~esmpy.api.grid.Grid` cell. When setting or retrieving coordinate data the stagger + location is specified to tell the :class:`~esmpy.api.grid.Grid` method from where in the cell to get the data. """ INVALID = -2 diff --git a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py similarity index 84% rename from src/addon/ESMPy/src/ESMF/api/esmpymanager.py rename to src/addon/ESMPy/src/esmpy/api/esmpymanager.py index be1e72608f..8dd02bb50c 100644 --- a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py +++ b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py @@ -6,10 +6,11 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.constants import * -from ESMF.util.exceptions import * -from ESMF.interface.cbindings import * -from ESMF.util.decorators import initialize +from esmpy.interface.cbindings import * + +from esmpy.api.constants import * +from esmpy.util.exceptions import * +from esmpy.util.decorators import initialize import re @@ -18,7 +19,7 @@ def _preprocess(v, separator, ignorecase): if ignorecase: v = v.lower() return [int(x) if x.isdigit() else [int(y) if y.isdigit() else y for y in - re.findall("\d+|[a-zA-Z]+", x)] for x in v.split(separator)] + re.findall(r"\d+|[a-zA-Z]+", x)] for x in v.split(separator)] def version_compare(a, b, separator = '.', ignorecase = True): a = _preprocess(a, separator, ignorecase) @@ -46,28 +47,28 @@ class Manager(object): ''' This singleton class is designed to ensure that ESMF is properly initialized and finalized. ESMF is initialized at - :class:`~ESMF.api.esmpymanager.Manager` creation, and the __del__ + :class:`~esmpy.api.esmpymanager.Manager` creation, and the __del__ method is registered with atexit to ensure ESMF is always finalized prior to exiting Python. If the object is copied, the copy will always be an alias - to the original :class:`~ESMF.api.esmpymanager.Manager` object. The - :class:`~ESMF.api.esmpymanager.Manager` will be created when the first + to the original :class:`~esmpy.api.esmpymanager.Manager` object. The + :class:`~esmpy.api.esmpymanager.Manager` will be created when the first ESMPy object is created if it is not created explicitly by the user. - Explicit creation of a :class:`~ESMF.api.esmpymanager.Manager` object allows + Explicit creation of a :class:`~esmpy.api.esmpymanager.Manager` object allows for setting a flag which results in the output of debug information from the ESMF logging capability during the application runtime. The output log files are named PET.ESMF_LogFile. The PET rank (local_pet) and total number of PETs (pet_count) - can also be retrieved from the :class:`~ESMF.api.esmpymanager.Manager` + can also be retrieved from the :class:`~esmpy.api.esmpymanager.Manager` using the following calls:: - ESMF.local_pet() - ESMF.pet_count() + esmpy.local_pet() + esmpy.pet_count() ``local_pet`` and ``pet_count`` are also properties of the - :class:`~ESMF.api.esmpymanager.Manager`. + :class:`~esmpy.api.esmpymanager.Manager`. Calls ESMP_Initialize and registers __del__ with atexit when called the first time. Subsequent calls only return whether or not ESMF is @@ -75,9 +76,14 @@ class Manager(object): will always be called prior to exiting Python. Calling __init__ explicitly results in a no-op. - The Manager can be used to enable the + The :class:`~esmpy.api.esmpymanager.Manager` can be used to enable the `MOAB `_ - mesh backend to the Mesh. This is done by calling ``set_moab()`` with ``moab_on=True``. + mesh backend to the :class:`~esmpy.api.esmpymanager.Mesh`. This is done by calling ``set_moab()`` with ``moab_on=True``. + + The :class:`~esmpy.api.esmpymanager.Manager` has a `test_exhaustive` member + variable that can be enabled to run + combinatorial expansions of :class:`~esmpy.api.esmpymanager.Grid` and + :class:`~esmpy.api.esmpymanager.Field` creation parameters. :param bool debug: outputs logging information to ESMF logfiles. If ``None``, defaults to False. @@ -126,6 +132,9 @@ def __init__(self, debug=False): # set up to use the ESMF native mesh backend by default self._moab = False + + # exhaustive testing set to False by default + self._test_exhaustive = False return diff --git a/src/addon/ESMPy/src/ESMF/api/field.py b/src/addon/ESMPy/src/esmpy/api/field.py similarity index 74% rename from src/addon/ESMPy/src/ESMF/api/field.py rename to src/addon/ESMPy/src/esmpy/api/field.py index 1b19d37724..978251c104 100755 --- a/src/addon/ESMPy/src/ESMF/api/field.py +++ b/src/addon/ESMPy/src/esmpy/api/field.py @@ -6,63 +6,63 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.grid import * -from ESMF.api.mesh import * -from ESMF.api.locstream import * -from ESMF.util.esmpyarray import * +from esmpy.api.grid import * +from esmpy.api.mesh import * +from esmpy.api.locstream import * +from esmpy.util.esmpyarray import * #### Field class ############################################################## [node, element] = [0, 1] class Field(object): """ - The :class:`~ESMF.api.field.Field` class is a Python wrapper object for the ESMF Field. + The :class:`~esmpy.api.field.Field` class is a Python wrapper object for the ESMF Field. The individual values of all data arrays are referenced to those of the underlying Fortran ESMF object. - A :class:`~ESMF.api.field.Field` represents a physical field, such as temperature. The :class:`~ESMF.api.field.Field` class + A :class:`~esmpy.api.field.Field` represents a physical field, such as temperature. The :class:`~esmpy.api.field.Field` class contains distributed and discretized field data, a reference to its - associated grid, and metadata. The :class:`~ESMF.api.field.Field` class stores the grid staggering + associated grid, and metadata. The :class:`~esmpy.api.field.Field` class stores the grid staggering for that physical field. This is the relationship of how the data array of a field maps onto a grid (e.g. one item per cell located at the cell center, one item per cell located at the NW corner, one item per cell vertex, etc.). - This means that different :class:`Fields ` which are on the same underlying :class:`~ESMF.api.grid.Grid` but - have different staggerings can share the same :class:`~ESMF.api.grid.Grid` object without needing to + This means that different :class:`Fields ` which are on the same underlying :class:`~esmpy.api.grid.Grid` but + have different staggerings can share the same :class:`~esmpy.api.grid.Grid` object without needing to replicate it multiple times. Refer to the Field Class of the `ESMF Reference Manual `_ for more information. - The following parameters are used to create a :class:`~ESMF.api.field.Field` - from a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or - :class:`~ESMF.api.locstream.LocStream`. + The following parameters are used to create a :class:`~esmpy.api.field.Field` + from a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or + :class:`~esmpy.api.locstream.LocStream`. *REQUIRED:* - :param :class:`~ESMF.api.grid.Grid`/Mesh/:class:`~ESMF.api.locstream.LocStream` grid: A :class:`~ESMF.api.grid.Grid`, - :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` + :param :class:`~esmpy.api.grid.Grid`/Mesh/:class:`~esmpy.api.locstream.LocStream` grid: A :class:`~esmpy.api.grid.Grid`, + :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` with coordinates allocated on at least one stagger location. *OPTIONAL:* :param str name: An optional user friendly name for the - :class:`~ESMF.api.field.Field`. - :param TypeKind typekind: Type of the :class:`~ESMF.api.field.Field` - data. If ``None``, defaults to :attr:`~ESMF.api.constants.TypeKind.R8`. + :class:`~esmpy.api.field.Field`. + :param TypeKind typekind: Type of the :class:`~esmpy.api.field.Field` + data. If ``None``, defaults to :attr:`~esmpy.api.constants.TypeKind.R8`. :param StaggerLoc staggerloc: The stagger location of the - :class:`~ESMF.api.field.Field` data, only specify this argument when - using a :class:`~ESMF.api.grid.Grid`. - If ``None``, defaults to :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :class:`~esmpy.api.field.Field` data, only specify this argument when + using a :class:`~esmpy.api.grid.Grid`. + If ``None``, defaults to :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param MeshLoc meshloc: The mesh location of the - :class:`~ESMF.api.field.Field` data, only specify this argument when - using a :class:`~ESMF.api.mesh.Mesh` - if ``None``, defaults to :attr:`~ESMF.api.constants.MeshLoc.NODE`. + :class:`~esmpy.api.field.Field` data, only specify this argument when + using a :class:`~esmpy.api.mesh.Mesh` + if ``None``, defaults to :attr:`~esmpy.api.constants.MeshLoc.NODE`. :param tuple ndbounds: The number of entries in an extra - :class:`~ESMF.api.field.Field` dimension. This is represented as a + :class:`~esmpy.api.field.Field` dimension. This is represented as a single value, a list or a tuple containing the number of entries for - each desired extra dimension of the :class:`~ESMF.api.field.Field`. The + each desired extra dimension of the :class:`~esmpy.api.field.Field`. The time dimension must be last, following Fortran indexing conventions. """ @@ -222,8 +222,8 @@ def __repr__(self): @property def data(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The data of the :class:`~ESMF.api.field.Field` + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The data of the :class:`~esmpy.api.field.Field` """ return self._data @@ -240,10 +240,10 @@ def finalized(self): @property def grid(self): """ - :rtype: :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or - :class:`~ESMF.api.locstream.LocStream` + :rtype: :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or + :class:`~esmpy.api.locstream.LocStream` :return: The discretization object upon which the - :class:`~ESMF.api.field.Field` is built. + :class:`~esmpy.api.field.Field` is built. """ return self._grid @@ -251,7 +251,7 @@ def grid(self): def lower_bounds(self): """ :rtype: ndarray - :return: The lower bounds of the :class:`~ESMF.api.field.Field`. + :return: The lower bounds of the :class:`~esmpy.api.field.Field`. """ return self._lower_bounds @@ -267,7 +267,7 @@ def meta(self): def name(self): """ :rtype: str - :return: the name of the :class:`~ESMF.api.field.Field`. + :return: the name of the :class:`~esmpy.api.field.Field`. """ return self._name @@ -276,7 +276,7 @@ def ndbounds(self): """ :rtype: list :return: The bounds of the extra dimensions in the - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._ndbounds @@ -284,16 +284,16 @@ def ndbounds(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.field.Field`. + :return: The rank of the :class:`~esmpy.api.field.Field`. """ return self._rank @property def staggerloc(self): """ - :rtype: :attr:`~ESMF.api.constants.StaggerLoc` or - :attr:`~ESMF.api.constants.MeshLoc` - :return: The location upon which the :class:`~ESMF.api.field.Field` + :rtype: :attr:`~esmpy.api.constants.StaggerLoc` or + :attr:`~esmpy.api.constants.MeshLoc` + :return: The location upon which the :class:`~esmpy.api.field.Field` is built. """ return self._staggerloc @@ -303,15 +303,15 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._struct @property def type(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The type of the data in the :class:`~ESMF.api.field.Field`. + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The type of the data in the :class:`~esmpy.api.field.Field`. """ return self._type @@ -319,7 +319,7 @@ def type(self): def upper_bounds(self): """ :rtype: ndarray - :return: The upper bounds of the :class:`~ESMF.api.field.Field`. + :return: The upper bounds of the :class:`~esmpy.api.field.Field`. """ return self._upper_bounds @@ -328,15 +328,15 @@ def xd(self): """ :rtype: int :return: The number of extra (ungridded) dimensions of the - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._xd def copy(self): """ - Copy a :class:`~ESMF.api.field.Field` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.field.Field` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.field.Field` shallow copy. + :return: A :class:`~esmpy.api.field.Field` shallow copy. """ # shallow copy ret = copy(self) @@ -347,7 +347,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.field.Field`. + Release the memory associated with a :class:`~esmpy.api.field.Field`. """ if hasattr(self, '_finalized'): if self._finalized == False: @@ -356,9 +356,9 @@ def destroy(self): def get_area(self): """ - Initialize an existing :class:`~ESMF.api.field.Field` with the areas of - the cells of the underlying :class:`~ESMF.api.grid.Grid` or - :class:`~ESMF.api.mesh.Mesh`. + Initialize an existing :class:`~esmpy.api.field.Field` with the areas of + the cells of the underlying :class:`~esmpy.api.grid.Grid` or + :class:`~esmpy.api.mesh.Mesh`. """ # call into the ctypes layer @@ -366,7 +366,7 @@ def get_area(self): def read(self, filename, variable, timeslice=None): """ - Read data into an existing :class:`~ESMF.api.field.Field` from a + Read data into an existing :class:`~esmpy.api.field.Field` from a CF-compliant NetCDF file. :note: This interface is not supported when ESMF is built with @@ -385,10 +385,6 @@ def read(self, filename, variable, timeslice=None): :param int timeslice: The number of timeslices to read. """ - import ESMF.api.constants as constants - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise ImportError("Field.Read() requires PIO and does not work if ESMF has not been built with MPI support") - assert (type(filename) is str) assert (type(variable) is str) diff --git a/src/addon/ESMPy/src/ESMF/api/grid.py b/src/addon/ESMPy/src/esmpy/api/grid.py similarity index 89% rename from src/addon/ESMPy/src/ESMF/api/grid.py rename to src/addon/ESMPy/src/esmpy/api/grid.py index 299900f4d1..dda0bb53fe 100755 --- a/src/addon/ESMPy/src/ESMF/api/grid.py +++ b/src/addon/ESMPy/src/esmpy/api/grid.py @@ -9,25 +9,25 @@ import warnings from copy import copy -from ESMF.api.esmpymanager import * -from ESMF.util.esmpyarray import ndarray_from_esmf -import ESMF.api.constants as constants -from ESMF.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound, get_none_or_ssslice +from esmpy.api.esmpymanager import * +from esmpy.util.esmpyarray import ndarray_from_esmf +import esmpy.api.constants as constants +from esmpy.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound, get_none_or_ssslice #### Grid class ######################################################### class Grid(object): """ - The :class:`~ESMF.api.grid.Grid` class is a Python wrapper object for the ESMF Grid. The individual + The :class:`~esmpy.api.grid.Grid` class is a Python wrapper object for the ESMF Grid. The individual values of all coordinate and mask arrays are referenced to those of the underlying Fortran ESMF object. - The :class:`~ESMF.api.grid.Grid` class is used to describe the geometry and + The :class:`~esmpy.api.grid.Grid` class is used to describe the geometry and discretization of logically rectangular physical grids. It also contains the description of the underlying topology and decomposition of the physical grid across the available computational resources. The most frequent use of - the :class:`~ESMF.api.grid.Grid` class is to describe physical grids in user + the :class:`~esmpy.api.grid.Grid` class is to describe physical grids in user code so that sufficient information is available to perform regridding operations. @@ -35,9 +35,9 @@ class Grid(object): `ESMF Reference Manual `_ for more information. - A :class:`~ESMF.api.grid.Grid` can be created in two different ways, as a - :class:`~ESMF.api.grid.Grid` in memory, or from SCRIP formatted or CF compliant GRIDSPEC file. The - arguments for each type of :class:`~ESMF.api.grid.Grid` creation are + A :class:`~esmpy.api.grid.Grid` can be created in two different ways, as a + :class:`~esmpy.api.grid.Grid` in memory, or from SCRIP formatted or CF compliant GRIDSPEC file. The + arguments for each type of :class:`~esmpy.api.grid.Grid` creation are outlined below. **Created in-memory:** @@ -56,30 +56,30 @@ class Grid(object): :param int pole_dim: The pole dimension ``0`` or ``1``. If ``None``, defaults to ``1``. :param CoordSys coord_sys: Coordinate system for the - :class:`~ESMF.api.grid.Grid`. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. - :param TypeKind coord_typekind: Type of the :class:`~ESMF.api.grid.Grid` + :class:`~esmpy.api.grid.Grid`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. + :param TypeKind coord_typekind: Type of the :class:`~esmpy.api.grid.Grid` coordinates. - If ``None``, defaults to :attr:`~ESMF.api.constants.TypeKind.R8`. + If ``None``, defaults to :attr:`~esmpy.api.constants.TypeKind.R8`. **Created either from file or in-memory:** :param StaggerLoc staggerloc: The stagger location of the coordinate values. - If ``None``, defaults to :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + If ``None``, defaults to :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param PoleKind pole_kind: Two item list which specifies the type of connection which occurs at the pole. The first value specifies the connection that occurs at the minimum end of the pole dimension. The second value specifies the connection that occurs at the maximum end of the pole dimension. - If ``None``, defaults to :attr:`~ESMF.api.constants.PoleKind.MONOPOLE`. + If ``None``, defaults to :attr:`~esmpy.api.constants.PoleKind.MONOPOLE`. **Created from file:** *REQUIRED:* :param str filename: The name of the NetCDF grid file. - :param FileFormat filetype: The grid :attr:`~ESMF.api.constants.FileFormat`. + :param FileFormat filetype: The grid :attr:`~esmpy.api.constants.FileFormat`. *OPTIONAL:* @@ -94,7 +94,7 @@ class Grid(object): :param bool add_mask: Set to ``True`` to generate the mask using the ``missing_value`` attribute defined in ``varname``. This argument is only supported with filetype - :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``False``. :param str varname: If add_mask is ``True``, provide a variable name stored in the grid file and the mask will be generated using the missing value @@ -102,12 +102,12 @@ class Grid(object): variable has to be the longitude and the latitude dimension and the mask is derived from the first 2D values of this variable even if this data is a 3D, or 4D array. This argument is only supported with - filetype :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + filetype :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``None``. :param list coord_names: A two-element array containing the longitude and latitude variable names in a GRIDSPEC file if there are multiple coordinates defined in the file. This argument is only supported with - filetype :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + filetype :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``None``. **Cubed sphere:** @@ -130,7 +130,7 @@ class Grid(object): PET count. For instance, if the total PET count is 16, the total DE count will be 12 with each tile decomposed into 1x2 blocks. The 12 DEs are mapped to the first 12 PETs and the remaining 4 PETs have no DEs locally. - :param str name: The name of the :class:`~ESMF.api.grid.Grid`. + :param str name: The name of the :class:`~esmpy.api.grid.Grid`. """ # :param list decompFlagPTile: # :param list deLabelList: @@ -561,8 +561,8 @@ def __repr__(self): def area(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The :class:`~ESMF.api.grid.Grid` cell areas represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The :class:`~esmpy.api.grid.Grid` cell areas represented as numpy arrays of floats of size given by ``upper_bounds - lower_bounds``. """ @@ -572,8 +572,8 @@ def area(self): @property def areatype(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The ESMF typekind of the :class:`~ESMF.api.grid.Grid` cell + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The ESMF typekind of the :class:`~esmpy.api.grid.Grid` cell areas. """ @@ -584,10 +584,10 @@ def coords(self): """ :rtype: 2D list of numpy arrays of size given by ``upper_bounds - lower_bounds``, where the first index represents - the stagger locations of the :class:`~ESMF.api.grid.Grid` and the + the stagger locations of the :class:`~esmpy.api.grid.Grid` and the second index represent the coordinate dimensions of the - :class:`~ESMF.api.grid.Grid`. - :return: The coordinates of the :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. + :return: The coordinates of the :class:`~esmpy.api.grid.Grid`. """ return self._coords @@ -595,8 +595,8 @@ def coords(self): @property def coord_sys(self): """ - :rtype: :attr:`~ESMF.api.constants.CoordSys` - :return: The coordinate system of the :class:`~ESMF.api.grid.Grid`. + :rtype: :attr:`~esmpy.api.constants.CoordSys` + :return: The coordinate system of the :class:`~esmpy.api.grid.Grid`. """ return self._coord_sys @@ -615,7 +615,7 @@ def finalized(self): def has_corners(self): """ :rtype: bool - :return: A boolean value to tell if the :class:`~ESMF.api.grid.Grid` + :return: A boolean value to tell if the :class:`~esmpy.api.grid.Grid` has corners allocated. """ @@ -625,8 +625,8 @@ def has_corners(self): def lower_bounds(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The lower bounds of the :class:`~ESMF.api.grid.Grid` + of the :class:`~esmpy.api.grid.Grid`. + :return: The lower bounds of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -637,8 +637,8 @@ def lower_bounds(self): def mask(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The mask of the :class:`~ESMF.api.grid.Grid` represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The mask of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ` `upper_bounds - lower_bounds``. """ @@ -649,8 +649,8 @@ def mask(self): def max_index(self): """ :rtype: A numpy array with as many values as the - :class:`~ESMF.api.grid.Grid` rank. - :return: The number of :class:`~ESMF.api.grid.Grid` cells in each + :class:`~esmpy.api.grid.Grid` rank. + :return: The number of :class:`~esmpy.api.grid.Grid` cells in each dimension of the grid. """ @@ -669,7 +669,7 @@ def meta(self): def name(self): """ :rtype: str - :return: The name of the :class:`~ESMF.api.grid.Grid`. + :return: The name of the :class:`~esmpy.api.grid.Grid`. """ return self._name @@ -679,7 +679,7 @@ def ndims(self): """ :rtype: int :return: The rank of the coordinate arrays of the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._ndims @@ -689,7 +689,7 @@ def num_peri_dims(self): """ :rtype: int :return: The total number of periodic dimensions in the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._num_peri_dims @@ -699,7 +699,7 @@ def decount(self): """ :rtype: int :return: The total number of tiles in the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._decount @@ -708,7 +708,7 @@ def decount(self): def periodic_dim(self): """ :rtype: int - :return: The periodic dimension of the :class:`~ESMF.api.grid.Grid` + :return: The periodic dimension of the :class:`~esmpy.api.grid.Grid` (e.g. ``0`` for ``x`` or ``longitude``, ``1`` for ``y`` or ``latitude``, etc.). """ @@ -719,7 +719,7 @@ def periodic_dim(self): def pole_dim(self): """ :rtype: int - :return: The pole dimension of the :class:`~ESMF.api.grid.Grid` + :return: The pole dimension of the :class:`~esmpy.api.grid.Grid` (e.g. ``0`` for ``x`` or ``longitude``, ``1`` for ``y`` or ``latitude``, etc.). """ @@ -730,8 +730,8 @@ def pole_dim(self): def pole_kind(self): """ :rtype: A numpy array with as many values as the - :class:`~ESMF.api.grid.Grid` has poles. - :return: The number of connections at each pole of the :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid` has poles. + :return: The number of connections at each pole of the :class:`~esmpy.api.grid.Grid`. """ return self._pole_kind @@ -740,7 +740,7 @@ def pole_kind(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.grid.Grid`. + :return: The rank of the :class:`~esmpy.api.grid.Grid`. """ return self._rank @@ -749,8 +749,8 @@ def rank(self): def size(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The size of the :class:`~ESMF.api.grid.Grid` represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The size of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -762,7 +762,7 @@ def staggerloc(self): """ :rtype: list of bools :return: The stagger locations that have been allocated for the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._staggerloc @@ -772,7 +772,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._struct @@ -780,8 +780,8 @@ def struct(self): @property def type(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The ESMF typekind of the :class:`~ESMF.api.grid.Grid` + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The ESMF typekind of the :class:`~esmpy.api.grid.Grid` coordinates. """ return self._type @@ -790,8 +790,8 @@ def type(self): def upper_bounds(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The upper bounds of the :class:`~ESMF.api.grid.Grid` + of the :class:`~esmpy.api.grid.Grid`. + :return: The upper bounds of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -799,20 +799,20 @@ def upper_bounds(self): def add_coords(self, staggerloc=None, coord_dim=None, from_file=False): """ - Add coordinates to the :class:`~ESMF.api.grid.Grid` at the specified + Add coordinates to the :class:`~esmpy.api.grid.Grid` at the specified stagger location. :param StaggerLoc staggerloc: The stagger location of the coordinate values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param int coord_dim: The dimension number of the coordinates to return e.g. ``[x, y, z] = (0, 1, 2)``, or ``[lon, lat] = (0, 1)`` (coordinates will not be returned if coord_dim is not specified and staggerlocs is a list with more than one element). :param bool from_file: Boolean for internal use to determine whether the - :class:`~ESMF.api.grid.Grid` has already been created from file. + :class:`~esmpy.api.grid.Grid` has already been created from file. :return: A numpy array of coordinate values if staggerloc and coord_dim are specified, otherwise return None. @@ -844,23 +844,23 @@ def add_coords(self, staggerloc=None, coord_dim=None, from_file=False): def add_item(self, item, staggerloc=None, from_file=False): """ - Allocate space for a :class:`~ESMF.api.grid.Grid` item (mask or areas) + Allocate space for a :class:`~esmpy.api.grid.Grid` item (mask or areas) at a specified stagger location. *REQUIRED:* - :param GridItem item: The :attr:`~ESMF.api.constants.GridItem` to + :param GridItem item: The :attr:`~esmpy.api.constants.GridItem` to allocate. *OPTIONAL:* :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param bool from_file: Boolean for internal use to determine whether the - :class:`~ESMF.api.grid.Grid` has already been created from file. + :class:`~esmpy.api.grid.Grid` has already been created from file. :return: A numpy array of the mask or area values if a single staggerloc is given, otherwise return None. @@ -905,9 +905,9 @@ def add_item(self, item, staggerloc=None, from_file=False): def copy(self): """ - Copy a :class:`~ESMF.api.grid.Grid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.grid.Grid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.grid.Grid` shallow copy. + :return: A :class:`~esmpy.api.grid.Grid` shallow copy. """ # shallow copy ret = copy(self) @@ -918,7 +918,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.grid.Grid`. + Release the memory associated with a :class:`~esmpy.api.grid.Grid`. """ if hasattr(self, '_finalized'): if not self._finalized: @@ -929,7 +929,7 @@ def get_coords(self, coord_dim, staggerloc=None): """ Return a numpy array of coordinates at a specified stagger location. The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* @@ -942,8 +942,8 @@ def get_coords(self, coord_dim, staggerloc=None): :param StaggerLoc staggerloc: The stagger location of the coordinate values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :return: A numpy array of coordinate values at the specified staggerloc. @@ -967,19 +967,19 @@ def get_item(self, item, staggerloc=None): """ Return a numpy array of item values at a specified stagger location. The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* - :param GridItem item: The :attr:`~ESMF.api.constants.GridItem` to + :param GridItem item: The :attr:`~esmpy.api.constants.GridItem` to return. *OPTIONAL:* :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` in 2D and - :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` in 2D and + :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :return: A numpy array of mask or area values at the specified staggerloc. """ @@ -1177,8 +1177,8 @@ def _write_(self, filename, staggerloc=None): :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` in 2D and - :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` in 2D and + :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. """ # handle the default case diff --git a/src/addon/ESMPy/src/ESMF/api/locstream.py b/src/addon/ESMPy/src/esmpy/api/locstream.py similarity index 79% rename from src/addon/ESMPy/src/ESMF/api/locstream.py rename to src/addon/ESMPy/src/esmpy/api/locstream.py index 07a10a472d..e5d5982140 100644 --- a/src/addon/ESMPy/src/ESMF/api/locstream.py +++ b/src/addon/ESMPy/src/esmpy/api/locstream.py @@ -6,25 +6,25 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.esmpymanager import * -from ESMF.util.esmpyarray import ndarray_from_esmf -import ESMF.api.constants as constants -from ESMF.util.slicing import get_formatted_slice +from esmpy.api.esmpymanager import * +from esmpy.util.esmpyarray import ndarray_from_esmf +import esmpy.api.constants as constants +from esmpy.util.slicing import get_formatted_slice #### LocStream class ######################################################### class LocStream(dict): """ - The :class:`~ESMF.api.locstream.LocStream` class is a Python wrapper object for the ESMF LocStream. - :class:`~ESMF.api.locstream.LocStream` is a derived type of a Python dictionary. + The :class:`~esmpy.api.locstream.LocStream` class is a Python wrapper object for the ESMF LocStream. + :class:`~esmpy.api.locstream.LocStream` is a derived type of a Python dictionary. The individual values of all key arrays are referenced to those of the underlying Fortran ESMF object. - A :class:`~ESMF.api.locstream.LocStream` is used to represent the locations of a + A :class:`~esmpy.api.locstream.LocStream` is used to represent the locations of a set of data points. The values of the data points are stored within a - :class:`~ESMF.api.field.Field` created using the :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.field.Field` created using the :class:`~esmpy.api.locstream.LocStream`. In the data assimilation world, location streams can be thought of as a set of observations. Their locations are generally described using Cartesian @@ -38,7 +38,7 @@ class LocStream(dict): `ESMF Reference Manual `_ for more information. - :class:`~ESMF.api.locstream.LocStream` follows standard dictionary syntax. For example: + :class:`~esmpy.api.locstream.LocStream` follows standard dictionary syntax. For example: >>> locstream["ESMF:X"] = [1, 2, 3] >>> x = locstream["ESMF:X"] @@ -54,29 +54,29 @@ class LocStream(dict): .. note:: - Mask must be of type :attr:`~ESMF.api.constants.TypeKind.I4`, - and coordinates must by of type :attr:`~ESMF.api.constants.TypeKind.R8`. + Mask must be of type :attr:`~esmpy.api.constants.TypeKind.I4`, + and coordinates must by of type :attr:`~esmpy.api.constants.TypeKind.R8`. - For ESMF to be able to recognize coordinates specified in a :class:`~ESMF.api.locstream.LocStream` key + For ESMF to be able to recognize coordinates specified in a :class:`~esmpy.api.locstream.LocStream` key they need to be named with the appropriate identifiers. The particular identifiers depend on the coordinate system (i.e. ``coord_sys`` argument) - used to create the :class:`~ESMF.api.locstream.LocStream`. + used to create the :class:`~esmpy.api.locstream.LocStream`. The valid values are: ============================================ =========== =========== =========== Coordinate System dimension 1 dimension 2 dimension 3 ============================================ =========== =========== =========== - :attr:`~ESMF.api.constants.CoordSys.SPH_DEG` ESMF:Lon ESMF:Lat ESMF:Radius - :attr:`~ESMF.api.constants.CoordSys.SPH_RAD` ESMF:Lon ESMF:Lat ESMF:Radius - :attr:`~ESMF.api.constants.CoordSys.CART` ESMF:X ESMF:Y ESMF:Z + :attr:`~esmpy.api.constants.CoordSys.SPH_DEG` ESMF:Lon ESMF:Lat ESMF:Radius + :attr:`~esmpy.api.constants.CoordSys.SPH_RAD` ESMF:Lon ESMF:Lat ESMF:Radius + :attr:`~esmpy.api.constants.CoordSys.CART` ESMF:X ESMF:Y ESMF:Z ============================================ =========== =========== =========== :param int location_count: The number of points in this stream. :param CoordSys coord_sys: Coordinate system for the location stream. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. :param str name: Optional name for the location stream. - :param bool esmf: Internal parameter controlling shallow copying by ESMF. + :param bool esmf: Internal parameter controlling shallow copying by esmpy. """ @initialize @@ -189,7 +189,7 @@ def finalized(self): def lower_bounds(self): """ :rtype: int - :return: The lower bounds of the :class:`~ESMF.api.locstream.LocStream`. + :return: The lower bounds of the :class:`~esmpy.api.locstream.LocStream`. """ return self._lower_bounds @@ -198,7 +198,7 @@ def lower_bounds(self): def mask(self): """ :rtype: list - :return: The mask of the :class:`~ESMF.api.locstream.LocStream`. + :return: The mask of the :class:`~esmpy.api.locstream.LocStream`. """ return self.get("ESMF:Mask") @@ -216,7 +216,7 @@ def meta(self): def name(self): """ :rtype: str - :return: The name of the :class:`~ESMF.api.locstream.LocStream`. + :return: The name of the :class:`~esmpy.api.locstream.LocStream`. """ return self._name @@ -225,7 +225,7 @@ def name(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.locstream.LocStream`. + :return: The rank of the :class:`~esmpy.api.locstream.LocStream`. """ return self._rank @@ -235,7 +235,7 @@ def singlestagger(self): """ :rtype: bool :return: A boolean value to tell if this - :class:`~ESMF.api.locstream.LocStream` has been sliced. + :class:`~esmpy.api.locstream.LocStream` has been sliced. """ return self._singlestagger @@ -244,7 +244,7 @@ def singlestagger(self): def size(self): """ :rtype: int - :return: The size of the :class:`~ESMF.api.locstream.LocStream`. + :return: The size of the :class:`~esmpy.api.locstream.LocStream`. """ return self._size @@ -254,7 +254,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.locstream.LocStream`. """ return self._struct @@ -263,16 +263,16 @@ def struct(self): def upper_bounds(self): """ :rtype: int - :return: The upper bounds of the :class:`~ESMF.api.locstream.LocStream`. + :return: The upper bounds of the :class:`~esmpy.api.locstream.LocStream`. """ return self._upper_bounds def copy(self): """ - Copy a :class:`~ESMF.api.locstream.LocStream` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.locstream.LocStream` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.locstream.LocStream` shallow copy. + :return: A :class:`~esmpy.api.locstream.LocStream` shallow copy. """ # shallow copy ret = LocStream(self._size, name=self._name, esmf=False) @@ -292,7 +292,7 @@ def copy(self): def destroy(self): """ Release the memory associated with a - :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.locstream.LocStream`. """ if hasattr(self, '_finalized'): @@ -310,4 +310,4 @@ def _add_(self, key_name, typekind=None): # create a numpy array out of the pointer keyvals = ndarray_from_esmf(key_ptr, typekind, (self.size,)) - return keyvals \ No newline at end of file + return keyvals diff --git a/src/addon/ESMPy/src/ESMF/api/mesh.py b/src/addon/ESMPy/src/esmpy/api/mesh.py similarity index 81% rename from src/addon/ESMPy/src/ESMF/api/mesh.py rename to src/addon/ESMPy/src/esmpy/api/mesh.py index a2ff3e9e12..7bfc1cdbff 100755 --- a/src/addon/ESMPy/src/ESMF/api/mesh.py +++ b/src/addon/ESMPy/src/esmpy/api/mesh.py @@ -8,12 +8,12 @@ from copy import copy -from ESMF.api.constants import * -from ESMF.interface.cbindings import * -from ESMF.util.decorators import initialize +from esmpy.api.constants import * +from esmpy.interface.cbindings import * +from esmpy.util.decorators import initialize -from ESMF.api.esmpymanager import * -from ESMF.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound_list +from esmpy.api.esmpymanager import * +from esmpy.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound_list import warnings @@ -22,91 +22,91 @@ class Mesh(object): """ - The :class:`~ESMF.api.mesh.Mesh` class is a Python wrapper object for the ESMF Mesh. + The :class:`~esmpy.api.mesh.Mesh` class is a Python wrapper object for the ESMF Mesh. The individual values of all coordinate and mask arrays are referenced to those of the underlying Fortran ESMF object. The ESMF library provides a class for representing unstructured grids called - the :class:`~ESMF.api.mesh.Mesh`. :class:`Fields ` can be created on a :class:`~ESMF.api.mesh.Mesh` to hold data. :class:`Fields ` created on a - :class:`~ESMF.api.mesh.Mesh` can also be used as either the source or destination or both of a + the :class:`~esmpy.api.mesh.Mesh`. :class:`Fields ` can be created on a :class:`~esmpy.api.mesh.Mesh` to hold data. :class:`Fields ` created on a + :class:`~esmpy.api.mesh.Mesh` can also be used as either the source or destination or both of a regrididng operation which allows data to be moved between unstructured - grids. A :class:`~ESMF.api.mesh.Mesh` is constructed of nodes and elements. A node, also known as - a vertex or corner, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a single point. + grids. A :class:`~esmpy.api.mesh.Mesh` is constructed of nodes and elements. A node, also known as + a vertex or corner, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a single point. Coordinate information is set in a node. An element, also known as a cell, is a part of a mesh which represents a small region of space. Elements are described in terms of a connected set of nodes which represent locations - along their boundaries. :class:`~ESMF.api.field.Field` data may be located on either the nodes or - elements of a :class:`~ESMF.api.mesh.Mesh`. + along their boundaries. :class:`~esmpy.api.field.Field` data may be located on either the nodes or + elements of a :class:`~esmpy.api.mesh.Mesh`. Refer to the Mesh Class of the `ESMF Reference Manual `_ for more information. - An unstructured :class:`~ESMF.api.mesh.Mesh` can be created in two different ways, as a :class:`~ESMF.api.mesh.Mesh` in + An unstructured :class:`~esmpy.api.mesh.Mesh` can be created in two different ways, as a :class:`~esmpy.api.mesh.Mesh` in memory, or from a SCRIP formatted or CF compliant UGRID file. The arguments - for each type of :class:`~ESMF.api.mesh.Mesh` creation are outlined below. + for each type of :class:`~esmpy.api.mesh.Mesh` creation are outlined below. **Created in-memory:** - The in-memory :class:`~ESMF.api.mesh.Mesh` can be created manually in 3 steps: - 1. create the :class:`~ESMF.api.mesh.Mesh` (specifying ``parametric_dim`` and ``spatial_dim``), + The in-memory :class:`~esmpy.api.mesh.Mesh` can be created manually in 3 steps: + 1. create the :class:`~esmpy.api.mesh.Mesh` (specifying ``parametric_dim`` and ``spatial_dim``), 2. add nodes, 3. add elements. *REQUIRED:* :param int parametric_dim: the dimension of the topology of the - :class:`~ESMF.api.mesh.Mesh` (e.g. a :class:`~ESMF.api.mesh.Mesh` composed of squares would have a - parametric dimension of 2 and a :class:`~ESMF.api.mesh.Mesh` composed of cubes + :class:`~esmpy.api.mesh.Mesh` (e.g. a :class:`~esmpy.api.mesh.Mesh` composed of squares would have a + parametric dimension of 2 and a :class:`~esmpy.api.mesh.Mesh` composed of cubes would have a parametric dimension of 3). :param int spatial_dim: the number of coordinate dimensions needed to describe the locations of the nodes making up the - :class:`~ESMF.api.mesh.Mesh`. For a manifold the spatial dimension can be larger + :class:`~esmpy.api.mesh.Mesh`. For a manifold the spatial dimension can be larger than the parametric dimension (e.g. the 2D surface of a sphere in 3D space), but it cannot be smaller. *OPTIONAL:* :param CoordSys coord_sys: Coordinate system for the - :class:`~ESMF.api.mesh.Mesh`. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. + :class:`~esmpy.api.mesh.Mesh`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. **Created from file:** - Note that :class:`Meshes ` created from file do not use the ``parametric_dim`` and + Note that :class:`Meshes ` created from file do not use the ``parametric_dim`` and ``spatial_dim`` parameters. *REQUIRED:* - :param str filename: the name of NetCDF file containing the :class:`~ESMF.api.mesh.Mesh`. + :param str filename: the name of NetCDF file containing the :class:`~esmpy.api.mesh.Mesh`. :param FileFormat filetype: the input - :attr:`~ESMF.api.constants.FileFormat` of the :class:`~ESMF.api.mesh.Mesh`. + :attr:`~esmpy.api.constants.FileFormat` of the :class:`~esmpy.api.mesh.Mesh`. *OPTIONAL:* :param bool convert_to_dual: a boolean value to specify if the - dual :class:`~ESMF.api.mesh.Mesh` should be calculated. Defaults to False. This + dual :class:`~esmpy.api.mesh.Mesh` should be calculated. Defaults to False. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.SCRIP`. + :attr:`~esmpy.api.constants.FileFormat.SCRIP`. :param bool add_user_area: a boolean value to specify if an area property should be added to the mesh. This argument is only - supported for :attr:`~ESMF.api.constants.FileFormat.SCRIP` - or :attr:`~ESMF.api.constants.FileFormat.ESMFMESH`. + supported for :attr:`~esmpy.api.constants.FileFormat.SCRIP` + or :attr:`~esmpy.api.constants.FileFormat.ESMFMESH`. If ``None``, defaults to False. - :param str meshname: the name of the :class:`~ESMF.api.mesh.Mesh` metadata variable in + :param str meshname: the name of the :class:`~esmpy.api.mesh.Mesh` metadata variable in a UGRID file. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.UGRID`. + :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to the empty string. :param MeshLoc mask_flag: an enumerated integer that, if specified, tells whether a mask in a UGRID file should be - defined on the :attr:`~ESMF.api.constants.MeshLoc.NODE`s, or - :attr:`~ESMF.api.constants.MeshLoc.ELEMENT`s of the :class:`~ESMF.api.mesh.Mesh`. + defined on the :attr:`~esmpy.api.constants.MeshLoc.NODE`s, or + :attr:`~esmpy.api.constants.MeshLoc.ELEMENT`s of the :class:`~esmpy.api.mesh.Mesh`. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.UGRID`. + :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to no masking. :param str varname: a variable name for the mask in a UGRID file if mask_flag is specified. This argument is only supported - for :attr:`~ESMF.api.constants.FileFormat.UGRID`. + for :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to the empty string. """ @@ -255,9 +255,9 @@ def __repr__(self): def area(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. - :return: The :class:`~ESMF.api.mesh.Mesh` area represented as a numpy - array of floats of the same number of entries as :class:`~ESMF.api.mesh.Mesh` elements. + and elements of the :class:`~esmpy.api.mesh.Mesh`. + :return: The :class:`~esmpy.api.mesh.Mesh` area represented as a numpy + array of floats of the same number of entries as :class:`~esmpy.api.mesh.Mesh` elements. """ return self._area @@ -265,18 +265,18 @@ def area(self): def coords(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. + and elements of the :class:`~esmpy.api.mesh.Mesh`. :return: The coordinates represented as a numpy array of floats - with a value for each node and/or element of the :class:`~ESMF.api.mesh.Mesh` - :class:`~ESMF.api.mesh.Mesh`. + with a value for each node and/or element of the :class:`~esmpy.api.mesh.Mesh` + :class:`~esmpy.api.mesh.Mesh`. """ return self._coords @property def coord_sys(self): """ - :rtype: :attr:`~ESMF.api.constants.CoordSys` - :return: The coordinate system of the :class:`~ESMF.api.mesh.Mesh`. + :rtype: :attr:`~esmpy.api.constants.CoordSys` + :return: The coordinate system of the :class:`~esmpy.api.mesh.Mesh`. """ return self._coord_sys @@ -321,9 +321,9 @@ def finalized(self): def mask(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. + and elements of the :class:`~esmpy.api.mesh.Mesh`. :return: The masked values on the nodes and elements of the - :class:`~ESMF.api.mesh.Mesh`. + :class:`~esmpy.api.mesh.Mesh`. """ return self._mask @@ -367,7 +367,7 @@ def rank(self): def size(self): """ :rtype: A two element list of integers. - :return: The number of nodes and elements in the :class:`~ESMF.api.mesh.Mesh` on the current + :return: The number of nodes and elements in the :class:`~esmpy.api.mesh.Mesh` on the current processor. """ return self._size @@ -376,7 +376,7 @@ def size(self): def size_owned(self): """ :rtype: A two element list of integers. - :return: The number of owned nodes and elements in the :class:`~ESMF.api.mesh.Mesh` on the + :return: The number of owned nodes and elements in the :class:`~esmpy.api.mesh.Mesh` on the current processor. """ return self._size_owned @@ -390,7 +390,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.mesh.Mesh`. + :class:`~esmpy.api.mesh.Mesh`. """ return self._struct @@ -402,19 +402,19 @@ def add_elements(self, element_count, element_area=None, element_coords=None): """ - Add elements to a :class:`~ESMF.api.mesh.Mesh`, this must be done after adding nodes. + Add elements to a :class:`~esmpy.api.mesh.Mesh`, this must be done after adding nodes. *REQUIRED:* - :param int element_count: the number of elements to add to the :class:`~ESMF.api.mesh.Mesh`. + :param int element_count: the number of elements to add to the :class:`~esmpy.api.mesh.Mesh`. :param ndarray element_ids: a numpy array of of shape ``(element_count, 1)`` to specify the element ids. :param ndarray element_types: a numpy array of - :attr:`~ESMF.api.constants.MeshElemType`s of shape + :attr:`~esmpy.api.constants.MeshElemType`s of shape ``(element_count, 1)`` to specify the element types. :param ndarray element_conn: a numpy array of shape ``sum(element_types[:], 1)`` to specify the connectivity of the - :class:`~ESMF.api.mesh.Mesh`. The connectivity array is constructed by concatenating the + :class:`~esmpy.api.mesh.Mesh`. The connectivity array is constructed by concatenating the tuples that correspond to the element_ids. The connectivity tuples are constructed by listing the node_ids of each element in **COUNTERCLOCKWISE** order. @@ -424,7 +424,7 @@ def add_elements(self, element_count, :param ndarray element_mask: a numpy array of shape ``(element_count, 1)`` containing integer values to specify masked elements. The specific values that are masked are specified in the - :class:`~ESMF.api.regrid.Regrid` constructor. + :class:`~esmpy.api.regrid.Regrid` constructor. :param ndarray element_area: a numpy array of shape ``(element_count, 1)`` to specify the areas of the elements. :param ndarray element_coords: a numpy array of shape @@ -483,13 +483,13 @@ def add_nodes(self, node_count, node_coords, node_owners): """ - Add nodes to a :class:`~ESMF.api.mesh.Mesh`, this must be done before adding elements. + Add nodes to a :class:`~esmpy.api.mesh.Mesh`, this must be done before adding elements. - :param int node_count: the number of nodes to add to the :class:`~ESMF.api.mesh.Mesh`. + :param int node_count: the number of nodes to add to the :class:`~esmpy.api.mesh.Mesh`. :param ndarray node_ids: a numpy array of shape (node_count, 1) to specify the node_ids. :param ndarray node_coords: a numpy array of shape - (spatial_dim*node_count, 1) to specify the coordinates of the :class:`~ESMF.api.mesh.Mesh`. + (spatial_dim*node_count, 1) to specify the coordinates of the :class:`~esmpy.api.mesh.Mesh`. The array should be constructed by concatenating the coordinate tuples into a numpy array that correspond to node_ids. :param ndarray node_owners: a numpy array of shape (node_count, 1) to @@ -517,9 +517,9 @@ def add_nodes(self, node_count, def copy(self): """ - Copy a :class:`~ESMF.api.mesh.Mesh` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.mesh.Mesh` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.mesh.Mesh` shallow copy. + :return: A :class:`~esmpy.api.mesh.Mesh` shallow copy. """ # shallow copy ret = copy(self) @@ -531,7 +531,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.mesh.Mesh`. + Release the memory associated with a :class:`~esmpy.api.mesh.Mesh`. """ if hasattr(self, '_finalized'): if not self._finalized: @@ -541,7 +541,7 @@ def destroy(self): def free_memory(self): """ Free memory associated with the creation of a - :class:`~ESMF.api.mesh.Mesh` which is no longer needed for ongoing + :class:`~esmpy.api.mesh.Mesh` which is no longer needed for ongoing operations. """ # call into ctypes layer @@ -549,11 +549,11 @@ def free_memory(self): def get_coords(self, coord_dim, meshloc=MeshLoc.NODE): """ - Return a numpy array of coordinates at a specified :class:`~ESMF.api.mesh.Mesh` - location (coordinates can only be returned for the :class:`~ESMF.api.mesh.Mesh` - :attr:`~ESMF.api.constants.MeshLoc.NODE`\s + Return a numpy array of coordinates at a specified :class:`~esmpy.api.mesh.Mesh` + location (coordinates can only be returned for the :class:`~esmpy.api.mesh.Mesh` + :attr:`~esmpy.api.constants.MeshLoc.NODE` at this time). The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* @@ -562,12 +562,12 @@ def get_coords(self, coord_dim, meshloc=MeshLoc.NODE): *OPTIONAL:* - :param MeshLoc meshloc: the :attr:`~ESMF.api.constants.MeshLoc` of the + :param MeshLoc meshloc: the :attr:`~esmpy.api.constants.MeshLoc` of the coordinates. If ``None``, defaults to - :attr:`~ESMF.api.constants.MeshLoc.NODE`. + :attr:`~esmpy.api.constants.MeshLoc.NODE`. :return: A numpy array of coordinate values at the specified - :attr:`~ESMF.api.constants.MeshLoc`. + :attr:`~esmpy.api.constants.MeshLoc`. """ ret = None @@ -619,7 +619,7 @@ def _link_coords_(self): def _write_(self, filename): """ - Write the :class:`~ESMF.api.mesh.Mesh` to a vtk formatted file. + Write the :class:`~esmpy.api.mesh.Mesh` to a vtk formatted file. :param str filename: the name of the output file, .vtk will be appended. """ diff --git a/src/addon/ESMPy/src/ESMF/api/regrid.py b/src/addon/ESMPy/src/esmpy/api/regrid.py similarity index 80% rename from src/addon/ESMPy/src/ESMF/api/regrid.py rename to src/addon/ESMPy/src/esmpy/api/regrid.py index 7552960306..d5d608425a 100644 --- a/src/addon/ESMPy/src/ESMF/api/regrid.py +++ b/src/addon/ESMPy/src/esmpy/api/regrid.py @@ -3,32 +3,32 @@ """ The Regrid API """ -from ESMF.api import constants -from ESMF.api.field import * +from esmpy.api import constants +from esmpy.api.field import * class Regrid(object): """ - The :class:`~ESMF.api.regrid.Regrid` object represents a regridding operator between two :class:`Fields `. The + The :class:`~esmpy.api.regrid.Regrid` object represents a regridding operator between two :class:`Fields `. The creation of this object is analogous to ESMF_FieldRegridStore(), and calling this object corresponds to ESMF_FieldRegrid(). - ESMF_FieldRegridRelease() is called when the :class:`~ESMF.api.regrid.Regrid` object goes out of - scope (this only happens when the :class:`~ESMF.api.esmpymanager.Manager` goes out of scope, there is a - destroy() call for explicit deallocation of the :class:`~ESMF.api.regrid.Regrid`). + ESMF_FieldRegridRelease() is called when the :class:`~esmpy.api.regrid.Regrid` object goes out of + scope (this only happens when the :class:`~esmpy.api.esmpymanager.Manager` goes out of scope, there is a + destroy() call for explicit deallocation of the :class:`~esmpy.api.regrid.Regrid`). Refer to the ESMF_FieldRegrid methods in the `ESMF Reference Manual `_ for more information. The following arguments are used to create a handle to a Regridding - operation between two :class:`Fields `. + operation between two :class:`Fields `. *REQUIRED:* - :param Field srcfield: source :class:`~ESMF.api.field.Field` associated with an underlying :class:`~ESMF.api.grid.Grid`, - :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream`. - :param Field dstfield: destination :class:`~ESMF.api.field.Field` associated with an underlying - :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream`. The data in this :class:`~ESMF.api.field.Field` may be overwritten + :param Field srcfield: source :class:`~esmpy.api.field.Field` associated with an underlying :class:`~esmpy.api.grid.Grid`, + :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream`. + :param Field dstfield: destination :class:`~esmpy.api.field.Field` associated with an underlying + :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream`. The data in this :class:`~esmpy.api.field.Field` may be overwritten by this call. *OPTIONAL:* @@ -36,65 +36,65 @@ class Regrid(object): :param string filename: path to the output netCDF weight file. :param string rh_filename: path to the output RouteHandle file. :param ndarray src_mask_values: a numpy array of values that should be - considered masked value on the source :class:`~ESMF.api.field.Field`. + considered masked value on the source :class:`~esmpy.api.field.Field`. :param ndarray dst_mask_values: a numpy array of values that should be - considered masked value on the destination :class:`~ESMF.api.field.Field`. + considered masked value on the destination :class:`~esmpy.api.field.Field`. :param RegridMethod regrid_method: specifies which - :attr:`~ESMF.api.constants.RegridMethod` to use. If ``None``, defaults - to :attr:`~ESMF.api.constants.RegridMethod.BILINEAR`. + :attr:`~esmpy.api.constants.RegridMethod` to use. If ``None``, defaults + to :attr:`~esmpy.api.constants.RegridMethod.BILINEAR`. :param PoleMethod pole_method: specifies which type of artificial pole - to construct on the source :class:`~ESMF.api.grid.Grid` for regridding. If - ``None``, defaults to: :attr:`~ESMF.api.constants.PoleMethod.NONE` for - regridmethod == :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, or - :attr:`~ESMF.api.constants.PoleMethod.ALLAVG` for - regridmethod != :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`. + to construct on the source :class:`~esmpy.api.grid.Grid` for regridding. If + ``None``, defaults to: :attr:`~esmpy.api.constants.PoleMethod.NONE` for + regridmethod == :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, or + :attr:`~esmpy.api.constants.PoleMethod.ALLAVG` for + regridmethod != :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`. :param int regrid_pole_npoints: specifies how many points to average over - if polemethod == :attr:`~ESMF.api.constants.PoleMethod.ALLAVG`. + if polemethod == :attr:`~esmpy.api.constants.PoleMethod.ALLAVG`. :param LineType line_type: select the path of the line that connects two points on the surface of a sphere. This in turn controls the path along which distances are calculated and the shape of the edges that make up a cell. If ``None``, defaults to: - :attr:`~ESMF.api.constants.LineType.GREAT_CIRCLE` for - regridmethod == :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, or - :attr:`~ESMF.api.constants.LineType.CART` for - regridmethod != :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`. + :attr:`~esmpy.api.constants.LineType.GREAT_CIRCLE` for + regridmethod == :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, or + :attr:`~esmpy.api.constants.LineType.CART` for + regridmethod != :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`. :param NormType norm_type: control which type of normalization to do when generating conservative regridding weights. If ``None``, defaults to - :attr:`~ESMF.api.constants.NormType.DSTAREA`. + :attr:`~esmpy.api.constants.NormType.DSTAREA`. :param ExtrapMethod extrap_method: Specify which extrapolation method to use on unmapped destination points after regridding. :param int extrap_num_src_pnts: The number of source points to use for the extrapolation methods that use more than one source point - (e.g. :attr:`~ESMF.api.constants.ExtrapMethod.NEAREST_IDAVG`). If not + (e.g. :attr:`~esmpy.api.constants.ExtrapMethod.NEAREST_IDAVG`). If not specified, defaults to 8. :param float extrap_dist_exponent: The exponent to raise the distance to when - calculating weights for the :attr:`~ESMF.api.constants.ExtrapMethod.NEAREST_IDAVG` + calculating weights for the :attr:`~esmpy.api.constants.ExtrapMethod.NEAREST_IDAVG` extrapolation method. A higher value reduces the influence of more distant points. If not specified, defaults to ``2.0``. :param int extrap_num_levels: The number of levels to output for the extrapolation - methods that fill levels (e.g. :attr:`~ESMF.api.constants.ExtrapMethod.CREEP`). + methods that fill levels (e.g. :attr:`~esmpy.api.constants.ExtrapMethod.CREEP`). When a method is used that requires this, then an error will be returned if it is not specified. :param UnmappedAction unmapped_action: specifies which action to take if a destination point is found which does not map to any source point. If - ``None``, defaults to :attr:`~ESMF.api.constants.UnmappedAction.ERROR`. + ``None``, defaults to :attr:`~esmpy.api.constants.UnmappedAction.ERROR`. :param bool ignore_degenerate: Ignore degenerate cells when checking the - input :class:`Grids ` or :class:`Meshes ` + input :class:`Grids ` or :class:`Meshes ` for errors. If this is set to True, then the regridding proceeds, but degenerate cells will be skipped. If set to False, a degenerate cell produces - an error. This currently only applies to :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, + an error. This currently only applies to :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, other regrid methods currently always skip degenerate cells. If ``None``, defaults to ``False``. :param ndarray src_frac_field: return a numpy array of values containing - weights corresponding to the amount of each :class:`~ESMF.api.field.Field` - value which contributes to the total mass of the :class:`~ESMF.api.field.Field`. + weights corresponding to the amount of each :class:`~esmpy.api.field.Field` + value which contributes to the total mass of the :class:`~esmpy.api.field.Field`. :param ndarray dst_frac_field: return a numpy array of values containing - weights corresponding to the amount of each :class:`~ESMF.api.field.Field` - value which contributes to the total mass of the :class:`~ESMF.api.field.Field`. + weights corresponding to the amount of each :class:`~esmpy.api.field.Field` + value which contributes to the total mass of the :class:`~esmpy.api.field.Field`. :param bool factors: If ``True``, return the factor and factor index list when calling into ``ESMF``'s regrid store method. These lists are converted to NumPy arrays and attached to the regrid object. The factor arrays - are retrievable via :meth:`~ESMF.api.regrid.get_factors` or :meth:`~ESMF.api.regrid.get_weights_dict`. + are retrievable via :meth:`~esmpy.api.regrid.get_factors` or :meth:`~esmpy.api.regrid.get_weights_dict`. See the respective documentation on those methods for additional information. For more information on how ``ESMF`` treats factor retrieval see the ESMF_FieldRegridStore interface in the @@ -143,11 +143,6 @@ def __init__(self, srcfield=None, dstfield=None, filename=None, rh_filename=None # Write weights to file if requested. if not isinstance(filename, type(None)): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - msg = "Regrid(filename) requires PIO and does not work if ESMF has " \ - "not been built with MPI support" - raise ImportError(msg) - self._routehandle = ESMP_FieldRegridStoreFile( srcfield, dstfield, @@ -247,15 +242,15 @@ def __call__(self, srcfield, dstfield, zero_region=None): *REQUIRED:* - :param Field srcfield: the :class:`~ESMF.api.field.Field` of source data to regrid. - :param Field dstfield: the :class:`~ESMF.api.field.Field` to hold the regridded data. + :param Field srcfield: the :class:`~esmpy.api.field.Field` of source data to regrid. + :param Field dstfield: the :class:`~esmpy.api.field.Field` to hold the regridded data. *OPTIONAL:* :param Region zero_region: specify which region of the field indices will be zeroed out before adding the values resulting from the interpolation. If ``None``, defaults to - :attr:`~ESMF.api.constants.Region.TOTAL`. + :attr:`~esmpy.api.constants.Region.TOTAL`. :return: dstfield """ @@ -390,7 +385,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.regrid.Regrid`. + :class:`~esmpy.api.regrid.Regrid`. """ return self.struct @@ -401,9 +396,9 @@ def unmapped_action(self): def copy(self): """ - Copy a :class:`~ESMF.api.regrid.Regrid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.regrid.Regrid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.regrid.Regrid` shallow copy. + :return: A :class:`~esmpy.api.regrid.Regrid` shallow copy. """ # shallow copy @@ -415,7 +410,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.regrid.Regrid`. + Release the memory associated with a :class:`~esmpy.api.regrid.Regrid`. """ # This detects if the object has made it through initialization @@ -459,7 +454,7 @@ def get_factors(self, deep_copy=False): .. note:: If ``deep_copy=True``, array memory is C contiguous according to NumPy array flags (``.flags``). - .. warning:: Remember to call :meth:`~ESMF.api.regrid.destroy` to deallocate + .. warning:: Remember to call :meth:`~esmpy.api.regrid.destroy` to deallocate memory associated with a regrid operation. This will be called by the Python garbage collector. However, if numerous regridding operations are called in a tight loop, a memory leak will occur without a call @@ -481,7 +476,7 @@ def get_factors(self, deep_copy=False): def get_weights_dict(self, deep_copy=False): """ Return a dictionary mapping that is more user-friendly for weight/factor - retrieval. Please read the documentation for :meth:`~ESMF.api.regrid.get_factors` + retrieval. Please read the documentation for :meth:`~esmpy.api.regrid.get_factors` before using this function. =========== ======================= @@ -549,30 +544,30 @@ def _handle_factors_(self, fil, fl, num_factors): class RegridFromFile(object): """ - The :class:`~ESMF.api.regrid.RegridFromFile` object represents a regridding - operator between two :class:`Fields ` that is read + The :class:`~esmpy.api.regrid.RegridFromFile` object represents a regridding + operator between two :class:`Fields ` that is read from a file. The creation of this object is analogous to= ESMF_FieldSMMStore(), and calling this object corresponds to ESMF_FieldRegrid(). ESMF_FieldRegridRelease() - is called when the :class:`~ESMF.api.regrid.RegridFromFile` object goes - out of scope (this only happens when the :class:`~ESMF.api.esmpymanager.Manager` + is called when the :class:`~esmpy.api.regrid.RegridFromFile` object goes + out of scope (this only happens when the :class:`~esmpy.api.esmpymanager.Manager` goes out of scope, there is a destroy() call for explicit deallocation of - the :class:`~ESMF.api.regrid.RegridFromFile`). + the :class:`~esmpy.api.regrid.RegridFromFile`). For more information about the ESMF Regridding functionality, please see the ESMF_FieldRegrid methods in the `ESMF Reference Manual `_. The following arguments are used to create a handle to a regridding - operation between two :class:`Fields `. + operation between two :class:`Fields `. *REQUIRED:* - :param Field srcfield: source :class:`~ESMF.api.field.Field` associated - with an underlying :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` - or :class:`~ESMF.api.locstream.LocStream`. - :param Field dstfield: destination :class:`~ESMF.api.field.Field` associated - with an underlying :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` - or :class:`~ESMF.api.locstream.LocStream`. The data in this :class:`~ESMF.api.field.Field` + :param Field srcfield: source :class:`~esmpy.api.field.Field` associated + with an underlying :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` + or :class:`~esmpy.api.locstream.LocStream`. + :param Field dstfield: destination :class:`~esmpy.api.field.Field` associated + with an underlying :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` + or :class:`~esmpy.api.locstream.LocStream`. The data in this :class:`~esmpy.api.field.Field` may be overwritten by this call. :param string filename: the name of the file from which to retrieve the weights. @@ -607,15 +602,15 @@ def __call__(self, srcfield, dstfield, zero_region=None): *REQUIRED:* - :param Field srcfield: the :class:`~ESMF.api.field.Field` of source data to regrid. - :param Field dstfield: the :class:`~ESMF.api.field.Field` to hold the regridded data. + :param Field srcfield: the :class:`~esmpy.api.field.Field` of source data to regrid. + :param Field dstfield: the :class:`~esmpy.api.field.Field` to hold the regridded data. *OPTIONAL:* :param Region zero_region: specify which region of the field indices will be zeroed out before adding the values resulting from the interpolation. If ``None``, defaults to - :attr:`~ESMF.api.constants.Region.TOTAL`. + :attr:`~esmpy.api.constants.Region.TOTAL`. :return: dstfield """ @@ -664,16 +659,16 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.regrid.Regrid`. + :class:`~esmpy.api.regrid.Regrid`. """ return self.struct def copy(self): """ - Copy a :class:`~ESMF.api.regrid.Regrid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.regrid.Regrid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.regrid.Regrid` shallow copy. + :return: A :class:`~esmpy.api.regrid.Regrid` shallow copy. """ # shallow copy @@ -685,7 +680,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with the :class:`~ESMF.api.regrid.RegridFromFile` + Release the memory associated with the :class:`~esmpy.api.regrid.RegridFromFile` object. """ diff --git a/src/addon/ESMPy/src/ESMF/fragments/dump_esmf_internal_info.py b/src/addon/ESMPy/src/esmpy/fragments/dump_esmf_internal_info.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/dump_esmf_internal_info.py rename to src/addon/ESMPy/src/esmpy/fragments/dump_esmf_internal_info.py diff --git a/src/addon/ESMPy/src/ESMF/fragments/extras.py b/src/addon/ESMPy/src/esmpy/fragments/extras.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/extras.py rename to src/addon/ESMPy/src/esmpy/fragments/extras.py diff --git a/src/addon/ESMPy/src/ESMF/fragments/remap.py b/src/addon/ESMPy/src/esmpy/fragments/remap.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/remap.py rename to src/addon/ESMPy/src/esmpy/fragments/remap.py diff --git a/src/addon/ESMPy/src/ESMF/interface/__init__.py b/src/addon/ESMPy/src/esmpy/interface/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/interface/__init__.py rename to src/addon/ESMPy/src/esmpy/interface/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/interface/cbindings.py b/src/addon/ESMPy/src/esmpy/interface/cbindings.py similarity index 99% rename from src/addon/ESMPy/src/ESMF/interface/cbindings.py rename to src/addon/ESMPy/src/esmpy/interface/cbindings.py index a7a7e3acf4..126ff6372f 100644 --- a/src/addon/ESMPy/src/ESMF/interface/cbindings.py +++ b/src/addon/ESMPy/src/esmpy/interface/cbindings.py @@ -8,9 +8,9 @@ import numpy as np import sys -import ESMF.api.constants as constants -from ESMF.util.decorators import deprecated, netcdf, beta -from ESMF.interface.loadESMF import _ESMF +import esmpy.api.constants as constants +from esmpy.util.decorators import * +from esmpy.interface.loadESMF import _ESMF def copy_struct(src): @@ -20,7 +20,7 @@ def copy_struct(src): def handle_esmf_error(rc, esmf_name): - from ESMF.api import constants + from esmpy.api import constants if rc != constants._ESMP_SUCCESS: msg = esmf_name + ' failed with rc = ' + str(rc) + '. ' + constants._errmsg raise ValueError(msg) @@ -613,7 +613,6 @@ def ESMP_GridCreateNoPeriDim(maxIndex, coordSys=None, coordTypeKind=None): ct.POINTER(ESMP_InterfaceInt), ct.c_void_p, ct.POINTER(ct.c_int)] -@beta def ESMP_GridCreateCubedSphere(tilesize, regDecompPTile=None, #decompFlagPTile=None, deLabelList=None, staggerLocList=None, name=None): @@ -1210,6 +1209,7 @@ def ESMP_MeshCreate(parametricDim, spatialDim, coordSys=None): OptionalNamedConstant, Py3Char] +@pio @netcdf def ESMP_MeshCreateFromFile(filename, fileTypeFlag, convertToDual=None, addUserArea=None, @@ -1943,6 +1943,8 @@ def ESMP_FieldPrint(field): Py3Char, ct.c_uint, ct.c_uint] +@pio +@netcdf def ESMP_FieldRead(field, filename, variablename, timeslice, iofmt=1): #TODO: C doc says it defaults to NETCDF(1), but actually defaults to BIN(0) """ @@ -2160,7 +2162,8 @@ def ESMP_FieldRegridStore(srcField, OptionalBool, OptionalField, OptionalField] -@deprecated +@pio +@netcdf def ESMP_FieldRegridStoreFile(srcField, dstField, filename, srcMaskValues=None, dstMaskValues=None, regridmethod=None, @@ -2326,7 +2329,6 @@ def ESMP_FieldRegrid(srcField, dstField, routehandle, zeroregion=None): _ESMF.ESMC_FieldSMMStore.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.POINTER(ESMP_RouteHandle), ct.c_bool, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int)] -@deprecated def ESMP_FieldSMMStore(srcField, dstField, filename, ignoreUnmatchedIndices=None): """ diff --git a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py similarity index 75% rename from src/addon/ESMPy/src/ESMF/interface/loadESMF.py rename to src/addon/ESMPy/src/esmpy/interface/loadESMF.py index c10bd60fbc..0b57d47775 100644 --- a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py +++ b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py @@ -5,29 +5,33 @@ import os import sys import traceback +import re -import ESMF.api.constants as constants - -try: - from ESMF.interface.esmfmkfile import ESMFMKFILE as esmfmk -except: - raise ImportError('The ESMFMKFILE cannot be found!') +import esmpy.api.constants as constants +from esmpy.util.exceptions import VersionWarning, VersionMismatch try: import numpy as np except: - raise ImportError('The Numpy library cannot be found!') + raise ImportError('The Numpy library cannot be found.') # this library is loaded here so that it can be pulled back up without sys try: import ctypes as ct except: - raise ImportError('The CTypes library cannot be found!') + raise ImportError('The CTypes library cannot be found.') + +esmfmk = None +try: + esmfmk = os.environ["ESMFMKFILE"] +except: + raise ImportError('The ESMFMKFILE environment variable is not available.') #### INVESTIGATE esmf.mk ###################################################### # TODO: look for various dependecies in the ESMF build log # - NetCDF +# - PIO # - LAPACK # - mpirun # use this information to set variables that can be checked at beginning @@ -41,7 +45,8 @@ esmfabi = None esmfcomm = None esmfversion = None - netcdf = [False, False] + netcdf = False + pio = False use_inmem_factors = False for line in MKFILE: @@ -52,9 +57,7 @@ elif 'ESMF_ABI:' in line: esmfabi = line.split(":")[1] elif 'ESMF_NETCDF:' in line: - netcdf[0] = True - elif 'ESMF_PIO:' in line: - netcdf[1] = True + netcdf = True elif 'ESMF_COMM:' in line: esmfcomm = line.split(":")[1] elif 'ESMF_VERSION_STRING=' in line: @@ -64,6 +67,24 @@ if "gfortran" in line: use_inmem_factors = True +# check and set _ESMF_VERSION_STRING +esmfvs = re.split(r'\D+',esmfversion) +esmpyvs = re.split(r'\D+',constants._ESMPY_VERSION) + +if esmfversion != constants._ESMPY_VERSION: + # check if major, minor and patch version numbers are equivalent + if esmfvs[0:2] != esmpyvs[0:2]: + raise VersionMismatch("ESMF installation version {}, ESMPy version {}".format( + esmfversion, constants._ESMPY_VERSION)) + # otherwise warn that beta versions may be in use + else: + import warnings + warnings.warn("ESMF installation version {}, ESMPy version {}".format( + esmfversion, constants._ESMPY_VERSION), VersionWarning) + +constants._ESMF_VERSION = esmfversion + + if not libsdir: raise ValueError("ESMF_LIBSDIR not found!") if not esmfos: @@ -92,16 +113,17 @@ raise ValueError("Unrecognized ESMF_ABI setting!") # set _ESMF_NETCDF -if np.any(netcdf): +if netcdf: constants._ESMF_NETCDF = True +# set _ESMF_PIO +if "mpiuni" not in esmfcomm: + constants._ESMF_PIO = True + # set _ESMF_COMM if "mpiuni" in esmfcomm: constants._ESMF_COMM = constants._ESMF_COMM_MPIUNI -# set _ESMF_VERSION_STRING -constants._ESMF_VERSION = esmfversion - # look for ESMPY_MPIRUN, set accordingly try: constants._ESMF_MPIRUN = os.environ['ESMPY_MPIRUN'] @@ -134,4 +156,4 @@ mode=ct.RTLD_GLOBAL) except: traceback.print_exc(file=sys.stdout) - raise ImportError('The ESMF shared library did not load properly.') \ No newline at end of file + raise ImportError('The ESMF shared library did not load properly.') diff --git a/src/addon/ESMPy/src/ESMF/test/__init__.py b/src/addon/ESMPy/src/esmpy/test/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/__init__.py rename to src/addon/ESMPy/src/esmpy/test/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/base.py b/src/addon/ESMPy/src/esmpy/test/base.py similarity index 88% rename from src/addon/ESMPy/src/ESMF/test/base.py rename to src/addon/ESMPy/src/esmpy/test/base.py index 54344429dc..28bd37ff37 100644 --- a/src/addon/ESMPy/src/ESMF/test/base.py +++ b/src/addon/ESMPy/src/esmpy/test/base.py @@ -1,13 +1,22 @@ import unittest import numpy as np -import ESMF -from ESMF.util.itester import iter_product_keywords - +from esmpy.util.itester import iter_product_keywords +from esmpy.api.esmpymanager import Manager class TestBase(unittest.TestCase): + @property + def mg(self): + """ + :rtype: :class:`~esmpy.api.esmpymanager.Manager` + :return: :class:`~esmpy.api.esmpymanager.Manager` + """ + return self._mg + def __init__(self, *args, **kwds): super(TestBase, self).__init__(*args, **kwds) + self._mg = Manager(debug = True) + self._mg.test_exhaustive = False def assertNumpyAll(self, arr1, arr2, check_fill_value_dtype=True, check_arr_dtype=True): """ @@ -96,21 +105,3 @@ def assertWeightFileIsRational(self, filename, src_size, dst_size): @staticmethod def iter_product_keywords(keywords, as_namedtuple=True): return iter_product_keywords(keywords, as_namedtuple=as_namedtuple) - - -def attr(*args, **kwargs): - """ - Decorator that adds attributes to classes or functions for use with the Attribute (-a) plugin. - - http://nose.readthedocs.org/en/latest/plugins/attrib.html - """ - - def wrap_ob(ob): - for name in args: - setattr(ob, name, True) - for name, value in kwargs.items(): - setattr(ob, name, value) - return ob - - return wrap_ob - diff --git a/src/addon/ESMPy/src/ESMF/test/data/T42_grid.nc b/src/addon/ESMPy/src/esmpy/test/data/T42_grid.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/T42_grid.nc rename to src/addon/ESMPy/src/esmpy/test/data/T42_grid.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/gridspec1Dcoords.nc b/src/addon/ESMPy/src/esmpy/test/data/gridspec1Dcoords.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/gridspec1Dcoords.nc rename to src/addon/ESMPy/src/esmpy/test/data/gridspec1Dcoords.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/ne4np4-esmf.nc b/src/addon/ESMPy/src/esmpy/test/data/ne4np4-esmf.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/ne4np4-esmf.nc rename to src/addon/ESMPy/src/esmpy/test/data/ne4np4-esmf.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/ne4np4-pentagons.nc b/src/addon/ESMPy/src/esmpy/test/data/ne4np4-pentagons.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/ne4np4-pentagons.nc rename to src/addon/ESMPy/src/esmpy/test/data/ne4np4-pentagons.nc diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/__init__.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/__init__.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py similarity index 79% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py index 6dca02d866..a07eec5913 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py @@ -10,7 +10,7 @@ import os import re -from ESMF.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR, CONTROL_FNAME +from esmpy.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR, CONTROL_FNAME def read_control_file(): @@ -18,9 +18,9 @@ def read_control_file(): # Parse each test case line from the control file. test_cases = [] for line in open(os.path.join(TEST_REGRID_DIR, CONTROL_FNAME), 'r'): - if line[0] != '#' and re.match('(\s*.+\s*:){3}', line): + if line[0] != '#' and re.match(r'(\s*.+\s*:){3}', line): (src_fname, dst_fname, regrid_method, options, mean_err_str, - max_err_str, max_area_err_str) = re.split('\s*:\s*', line) + max_err_str, max_area_err_str) = re.split(r'\s*:\s*', line) test_cases.append([src_fname, dst_fname, regrid_method, options, float(mean_err_str), float(max_err_str), float(max_area_err_str)]) diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py similarity index 83% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py index 4a7582b869..f0748021d8 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py @@ -16,21 +16,21 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') -from ESMF.test.regrid_from_file.regrid_from_file_consts import regrid_method_map, file_type_map, pole_method_map, UNINITVAL -from ESMF.util.grid_utilities import compute_mass_grid -from ESMF.util.mesh_utilities import compute_mass_mesh -from ESMF.util.field_utilities import compare_fields +from esmpy.test.regrid_from_file.regrid_from_file_consts import regrid_method_map, file_type_map, pole_method_map, UNINITVAL +from esmpy.util.grid_utilities import compute_mass_grid +from esmpy.util.mesh_utilities import compute_mass_mesh +from esmpy.util.field_utilities import compare_fields def nc_is_mesh(filename, filetype): is_mesh = False - if (filetype == ESMF.FileFormat.UGRID) or (filetype == ESMF.FileFormat.ESMFMESH): + if (filetype == esmpy.FileFormat.UGRID) or (filetype == esmpy.FileFormat.ESMFMESH): is_mesh = True - elif filetype == ESMF.FileFormat.SCRIP: - grid_rank, dims = ESMF.ESMP_ScripInq(filename) + elif filetype == esmpy.FileFormat.SCRIP: + grid_rank, dims = esmpy.ESMP_ScripInq(filename) if grid_rank == 1: is_mesh = True return is_mesh @@ -42,7 +42,7 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, missingvalue=None): is_mesh = False if nc_is_mesh(filename, filetype): - grid_or_mesh = ESMF.Mesh(filename=filename, + grid_or_mesh = esmpy.Mesh(filename=filename, filetype=filetype, meshname=meshname, convert_to_dual=convert_to_dual) @@ -50,7 +50,7 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, add_mask = False else: add_mask = (missingvalue is not None) and (len(missingvalue) > 0) - grid_or_mesh = ESMF.Grid(filename=filename, filetype=filetype, + grid_or_mesh = esmpy.Grid(filename=filename, filetype=filetype, add_corner_stagger=add_corner_stagger, is_sphere=isSphere, add_mask=add_mask, varname=missingvalue) @@ -59,16 +59,16 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, def get_coords_from_grid_or_mesh(grid_or_mesh, is_mesh, regrid_method): if is_mesh: # Mesh - if regrid_method == ESMF.RegridMethod.CONSERVE: - lons = grid_or_mesh.get_coords(0, meshloc=ESMF.element) - lats = grid_or_mesh.get_coords(1, meshloc=ESMF.element) + if regrid_method == esmpy.RegridMethod.CONSERVE: + lons = grid_or_mesh.get_coords(0, meshloc=esmpy.element) + lats = grid_or_mesh.get_coords(1, meshloc=esmpy.element) else: - lons = grid_or_mesh.get_coords(0, meshloc=ESMF.node) - lats = grid_or_mesh.get_coords(1, meshloc=ESMF.node) + lons = grid_or_mesh.get_coords(0, meshloc=esmpy.node) + lats = grid_or_mesh.get_coords(1, meshloc=esmpy.node) else: # Grid - lons = grid_or_mesh.get_coords(0, staggerloc=ESMF.StaggerLoc.CENTER) - lats = grid_or_mesh.get_coords(1, staggerloc=ESMF.StaggerLoc.CENTER) + lons = grid_or_mesh.get_coords(0, staggerloc=esmpy.StaggerLoc.CENTER) + lats = grid_or_mesh.get_coords(1, staggerloc=esmpy.StaggerLoc.CENTER) # Convert to radians lons = np.radians(lons) lats = np.radians(lats) @@ -80,13 +80,13 @@ def create_field(grid, name, regrid_method=None): will be used to initialize the name of a new Field. POSTCONDITIONS: A Field has been created. ''' - if isinstance(grid,ESMF.Mesh): - if regrid_method == ESMF.RegridMethod.CONSERVE: - field = ESMF.Field(grid, name=name, meshloc=ESMF.MeshLoc.ELEMENT) + if isinstance(grid,esmpy.Mesh): + if regrid_method == esmpy.RegridMethod.CONSERVE: + field = esmpy.Field(grid, name=name, meshloc=esmpy.MeshLoc.ELEMENT) else: - field = ESMF.Field(grid, name=name, meshloc=ESMF.MeshLoc.NODE) + field = esmpy.Field(grid, name=name, meshloc=esmpy.MeshLoc.NODE) else: - field = ESMF.Field(grid, name=name) + field = esmpy.Field(grid, name=name) return field @@ -117,11 +117,11 @@ def run_regridding(srcfield, dstfield, src_mask, dst_mask, src_mask_vals = None dst_mask_vals = None if src_mask: - src_mask_vals = np.array([0]) + src_mask_vals = np.atleast_1d(np.array([0])) if dst_mask: - dst_mask_vals = np.array([0]) + dst_mask_vals = np.atleast_1d(np.array([0])) - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=src_mask_vals, dst_mask_values=dst_mask_vals, regrid_method=regrid_method, @@ -130,7 +130,7 @@ def run_regridding(srcfield, dstfield, src_mask, dst_mask, dst_frac_field=dstfracfield, pole_method=pole_method, regrid_pole_npoints=regrid_pole_npoints) - dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=ESMF.Region.SELECT) + dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=esmpy.Region.SELECT) regridSrc2Dst.destroy() return dstfield @@ -148,7 +148,7 @@ def parse_options(options): src_meshname = "Undefined" dst_meshname = "Undefined" pole_method_str = None - unmapped_action = ESMF.UnmappedAction.ERROR + unmapped_action = esmpy.UnmappedAction.ERROR src_regional = False dst_regional = False src_missingvalue = "" @@ -163,7 +163,7 @@ def parse_options(options): elif opt == '--dst_meshname': dst_meshname = arg elif opt == '-i' or opt == '--ignore_unmapped': - unmapped_action = ESMF.UnmappedAction.IGNORE + unmapped_action = esmpy.UnmappedAction.IGNORE elif opt == '-t': src_type_str = arg dst_type_str = arg @@ -190,7 +190,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, # print ("\nregrid_weight_gen_check.py: mesh_check()") parallel = False - if ESMF.pet_count() > 1: + if esmpy.pet_count() > 1: parallel = True # Settings for regrid @@ -200,8 +200,8 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, src_type = file_type_map[src_type_str] dst_type = file_type_map[dst_type_str] regrid_method = regrid_method_map[regrid_method] - convert_to_dual = (regrid_method != ESMF.RegridMethod.CONSERVE) - add_corner_stagger = (regrid_method == ESMF.RegridMethod.CONSERVE) + convert_to_dual = (regrid_method != esmpy.RegridMethod.CONSERVE) + add_corner_stagger = (regrid_method == esmpy.RegridMethod.CONSERVE) src_is_sphere = not src_regional dst_is_sphere = not dst_regional pole_method = None @@ -210,7 +210,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, if pole_method_str in pole_method_map: pole_method = pole_method_map[pole_method_str] else: - pole_method = ESMF.PoleMethod.NPNTAVG + pole_method = esmpy.PoleMethod.NPNTAVG pole_method_npntavg = int(pole_method_str) src_mask = False @@ -259,7 +259,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, srcmass = None dstmass = None - if regrid_method == ESMF.RegridMethod.CONSERVE: + if regrid_method == esmpy.RegridMethod.CONSERVE: if src_is_mesh: srcmass = compute_mass_mesh(srcfield, dofrac=True, fracfield=srcfracfield) @@ -290,7 +290,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, srcfield.destroy() dstfield.destroy() dstfield2.destroy() - if regrid_method == ESMF.RegridMethod.CONSERVE: + if regrid_method == esmpy.RegridMethod.CONSERVE: srcfracfield.destroy() dstfracfield.destroy() srcgrid.destroy() diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py new file mode 100644 index 0000000000..8e0b7fcc6f --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py @@ -0,0 +1,31 @@ +""" +Constants required for the regrid from file tests. +""" +import os +try: + import esmpy +except: + raise ImportError('The ESMF library cannot be found!') +# +TEST_REGRID_DIR = 'src/esmpy/test/regrid_from_file/' +CONTROL_FNAME = 'regrid_test_data.txt' +DATA_SUBDIR = os.path.join(TEST_REGRID_DIR,'data/') +DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' +UNINITVAL = 422397696. +EPSILON = 1E-30 +# +regrid_method_map = {"bilinear" : esmpy.RegridMethod.BILINEAR, + "patch" : esmpy.RegridMethod.PATCH, + "conserve" : esmpy.RegridMethod.CONSERVE, + "neareststod" : esmpy.RegridMethod.NEAREST_STOD, + "nearestdtos" : esmpy.RegridMethod.NEAREST_DTOS} +file_type_map = {"VTK" : esmpy.FileFormat.VTK, + "SCRIP" : esmpy.FileFormat.SCRIP, + "ESMF" : esmpy.FileFormat.ESMFMESH, + "ESMFMESH" : esmpy.FileFormat.ESMFMESH, + "ESMFGRID" : esmpy.FileFormat.ESMFGRID, + "UGRID" : esmpy.FileFormat.UGRID, + "GRIDSPEC" : esmpy.FileFormat.GRIDSPEC} +pole_method_map = {"none" : esmpy.PoleMethod.NONE, + "all" : esmpy.PoleMethod.ALLAVG, + "teeth" : esmpy.PoleMethod.TEETH} diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_test_data.txt b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_test_data.txt similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_test_data.txt rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_test_data.txt diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py new file mode 100644 index 0000000000..7c5a648fb4 --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py @@ -0,0 +1,52 @@ +# $Id$ + +""" +Reads each line of a control file where each line corresponds to one test +case. Parses each line and calls a test subroutine that creates meshes from +source and destination NetCDF files, creates an analytic field across the +source mesh, regrids the source mesh to the grid of the destination mesh, +and compares the analytic field of the resulting regridded mesh to that of the +source mesh. +""" + +import pytest + +import sys +import os +import traceback + +from esmpy import * +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR +from esmpy.test.regrid_from_file.regrid_check import regrid_check +from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file + + +# Start up esmpy +mg = Manager(debug=True) + +if mg.pet_count == 1: + import esmpy.test.regrid_from_file.test_regrid_from_file_download + +# Read the test case parameters from the control file. +print('Reading control file...') +test_cases = read_control_file() + +# For each test case line from the control file parse the line and call +# the test subroutine. + +@pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") +@pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") +@pytest.mark.parametrize('test_case', test_cases) +def test_run_regrid_from_file(test_case): + (src_fname, dst_fname, regrid_method, options, + itrp_mean_err, itrp_max_err, csrv_err) = test_case + test_str = 'Regrid %s to %s as %s with %s itrp_mean_err=%f, itrp_max_err=%f, and csrv_err=%f' % (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) + if local_pet() == 0: + print ('\n' + test_str) + src_fname_full = os.path.join(DATA_SUBDIR, src_fname) + dst_fname_full = os.path.join(DATA_SUBDIR, dst_fname) + + # run the data file retrieval and regridding through try/except + regrid_check(src_fname_full, dst_fname_full, regrid_method, + options, itrp_mean_err, itrp_max_err, csrv_err) diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py similarity index 56% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py index fdc512551f..94c4d5c384 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py @@ -4,22 +4,25 @@ coordinate grid. Parses each line and retrieves the source and destination files from a remote server if they do not already exist locally. On parallel computers where the compute nodes do not have internet access, this script must -be run on the front-end machine before running run_regrid_from_file.py to do +be run on the front-end machine before running test_regrid_from_file.py to do the regridding. """ import sys import os -from ESMF.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR, DATA_URL_ROOT -from ESMF.util.cache_data import cache_data_file -from ESMF.test.regrid_from_file.read_test_cases_from_control_file import read_control_file +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR +from esmpy.util.cache_data import cache_data_file +from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file -def cache_data_files_for_test_cases(test_cases): +def cache_data_files_for_test_cases(test_cases, DATA_URL_ROOT=None): # Create data subdirectory if it doesn't exist. if not os.path.exists(DATA_SUBDIR): os.mkdir(DATA_SUBDIR) + if DATA_URL_ROOT == None: + DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' + # For each test case line from the control file parse the line and call # the test subroutine. status_ok = True @@ -36,18 +39,12 @@ def cache_data_files_for_test_cases(test_cases): break return status_ok -# Main program: Retrieve data files from a remote server if they do not exist -# locally for each test read from a control file. -def main(): - # Read the test case parameters from the control file. - test_cases = read_control_file() - - # Retrieve the data files needed for the test cases from the remote server. - status_ok = cache_data_files_for_test_cases(test_cases) - if status_ok: - print ('RESULT: PASS - regrid_from_file_dryrun ok\n\n') - else: - print ('RESULT: FAIL - regrid_from_file_dryrun error\n\n') - -if __name__ == '__main__': - sys.exit(main()) +DATAURL = None +if len(sys.argv) > 1: + DATAURL = sys.argv[1] + +# Read the test case parameters from the control file. +test_cases = read_control_file() + +# Retrieve the data files needed for the test cases from the remote server. +cache_data_files_for_test_cases(test_cases, DATAURL) diff --git a/src/addon/ESMPy/src/esmpy/test/test_all.bash b/src/addon/ESMPy/src/esmpy/test/test_all.bash new file mode 100644 index 0000000000..a847a0d0e1 --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/test_all.bash @@ -0,0 +1,17 @@ +#!/bin/bash + +VERSION=$(python3 -c "import esmpy; print (esmpy.__version__)") + +echo "Testing ESMPy ${VERSION}" + +for NP in 1 4 6 +do + REPORT="esmpy${VERSION}-petx${NP}.test" + COMMAND="mpiexec -n ${NP} python3 -m pytest -vs --json-report --json-report-summary > $REPORT 2>&1" + echo ${COMMAND} + eval "${COMMAND}" + find . -name "*.ESMF_LogFile" -exec cat {} >> ${REPORT} \; + cat .report.json >> ${REPORT} +done + +echo "Report is in ${REPORT}" diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/__init__.py b/src/addon/ESMPy/src/esmpy/test/test_api/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/test_api/__init__.py rename to src/addon/ESMPy/src/esmpy/test/test_api/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_array.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py similarity index 98% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_array.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_array.py index 7787555af3..69cf12f670 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_array.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py @@ -3,12 +3,13 @@ unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase - +import pytest import numpy as np +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase + # TODO: test view casting # TODO: demonstrate Fortran reordering in reshape call @@ -59,7 +60,7 @@ def make_maskedarray(self, array, type=TypeKind.R8): :param array: maxindices of a 2- or 3d array :type array: np.array of dtype=np.int32 :param type: the type of the esmf buffer - :type type: ESMF.TypeKind + :type type: esmpy.TypeKind ''' # create manager because we are doing some lower level stuff here without automatic initialization Manager() diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py similarity index 89% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_field.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_field.py index e69d2baa5f..1a443e0d05 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py @@ -2,18 +2,19 @@ field unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest +import pytest -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr -from ESMF.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel +from esmpy import * +from esmpy.test.base import TestBase +from esmpy.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel class TestField(TestBase): + + # prefer TestBase.mg, but in this case required for test_exhaustive in pytest markers + mg = Manager(debug=True) + mg.test_exhaustive = False + # this is for the documentation, do not modify def create_field(grid_or_mesh, name): ''' @@ -71,7 +72,7 @@ def test_meta_del(self): del (self.field) assert (not hasattr(self, 'field')) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_numpy_funcs(self): field = self.make_field(np.array([10, 10], dtype=np.int32)) @@ -97,10 +98,9 @@ def test_numpy_funcs(self): - @attr('serial') - @attr('slow') - #nosetests src/ESMF/test/test_api/test_field.py:TestField.test_field_create_2d_grid - def test_field_create_2d_grid(self): + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], @@ -148,9 +148,9 @@ def test_field_create_2d_grid(self): raise ValueError( "The following combinations of parameters failed to create a proper Field: " + str(fail)) - @attr('serial') - @attr('slow') - def test_field_create_3d_grid(self): + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], [None, None, 2], @@ -200,16 +200,9 @@ def test_field_create_3d_grid(self): raise ValueError( "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) - @attr('slow') - def test_field_create_2d_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + def _field_create_2d_mesh(self): keywords = dict( meshloc=[MeshLoc.NODE, MeshLoc.ELEMENT], typekind_field=[None, TypeKind.I4, TypeKind.I8, TypeKind.R4, TypeKind.R8], @@ -223,7 +216,7 @@ def test_field_create_2d_mesh(self): try: # create mesh mesh = None - if parallel: + if (pet_count == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = \ mesh_create_50_parallel() else: @@ -284,17 +277,10 @@ def create_field(gml, name): return field + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_uniqueness(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if (pet_count() == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -315,7 +301,7 @@ def test_field_uniqueness(self): assert (field.struct.ptr != field2.struct.ptr) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_area(self): grid = Grid(np.array([3, 4]), staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER], coord_sys=CoordSys.SPH_DEG, num_peri_dims=1, @@ -351,7 +337,7 @@ def test_field_area(self): assert(np.all(field.data == field2.data)) - + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_locstream_mask(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -404,18 +390,10 @@ def test_field_extradims_grid(self): field2.data[...] = 10 self.examine_field_attributes(field2) - + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_extradims_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if (pet_count() == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -431,7 +409,7 @@ def test_field_extradims_mesh(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid(self): typekind = TypeKind.R8 grid = Grid(np.array([100, 100]), coord_sys=CoordSys.CART, @@ -471,18 +449,10 @@ def test_field_slice_grid(self): assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) # slicing is disabled in parallel - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() > 1: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -510,7 +480,7 @@ def test_field_slice_mesh(self): assert (field2.grid.size[0] == 5) assert (field3.grid.size[0] == 2) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid_extraindices(self): n = 10 grid = Grid(np.array([n,n]), coord_sys=CoordSys.CART, staggerloc=StaggerLoc.CENTER) @@ -548,23 +518,9 @@ def test_field_slice_grid_extraindices(self): assert (field2.grid.upper_bounds[0].tolist() == [5, 5]) assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def disable_est_field_slice_mesh_extraindices(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - mesh = None - if parallel: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_50_parallel() - else: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_50() + mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = mesh_create_50() field = Field(mesh, typekind=TypeKind.R8, meshloc=MeshLoc.NODE, ndbounds=[5, 2]) @@ -572,9 +528,9 @@ def disable_est_field_slice_mesh_extraindices(self): for i in range(5): for j in range(2): - field[:, :, i, j] = i + j + field.data[:, i, j] = i + j - field2 = field[0:5, 0:2, 0:1] + field2 = field[0:4, 0:1, 0:1] self.examine_field_attributes(field2) field3 = field2[2:4, 1:2, 0:1] @@ -584,7 +540,7 @@ def disable_est_field_slice_mesh_extraindices(self): assert field2.data.shape == (5, 2, 1) assert field3.data.shape == (2, 1, 1) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_reshape(self): field = self.make_field(np.array([10, 10], dtype=np.int32), ndbounds=False) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py similarity index 86% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index d70e8f6a9f..300c810f9a 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -3,19 +3,23 @@ grid unit test file """ -import ESMF -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr - +import pytest import numpy as np + import os import inspect +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF + class TestGrid(TestBase): - Manager(debug=True) - + # prefer TestBase.mg, but in this case required for test_exhaustive in pytest markers + mg = Manager(debug=True) + mg.test_exhaustive = False + def examine_grid_attributes(self, grid): # ~~~~~~~~~~~~~~~~~~~~~~ STAGGER LOCATIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # grid.staggerloc returns a boolean list of the activated stagger locations @@ -138,28 +142,28 @@ def make_grid_periodic(self): assert lon.size == 100 assert lat.size == 100 - grid = ESMF.Grid(np.array([lon.size, lat.size], 'int32'), + grid = Grid(np.array([lon.size, lat.size], 'int32'), num_peri_dims=1, staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER]) - gridXCorner = grid.get_coords(0, staggerloc=ESMF.StaggerLoc.CORNER) - lon_par = lon[grid.lower_bounds[ESMF.StaggerLoc.CORNER][0]:grid.upper_bounds[ESMF.StaggerLoc.CORNER][0]] + gridXCorner = grid.get_coords(0, staggerloc=StaggerLoc.CORNER) + lon_par = lon[grid.lower_bounds[StaggerLoc.CORNER][0]:grid.upper_bounds[StaggerLoc.CORNER][0]] gridXCorner[...] = lon_par.reshape((lon_par.size, 1)) - gridYCorner = grid.get_coords(1, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(1, staggerloc=StaggerLoc.CORNER) lat_corner = np.linspace(90, -90, lat.size + 1) - lat_par = lat_corner[grid.lower_bounds[ESMF.StaggerLoc.CORNER][1]:grid.upper_bounds[ESMF.StaggerLoc.CORNER][1]] + lat_par = lat_corner[grid.lower_bounds[StaggerLoc.CORNER][1]:grid.upper_bounds[StaggerLoc.CORNER][1]] gridYCorner[...] = lat_par.reshape((1, lat_par.size)) offset_lon = 360. / lon.size / 2. lon -= offset_lon gridXCenter = grid.get_coords(0) - lon_par = lon[grid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] + lon_par = lon[grid.lower_bounds[StaggerLoc.CENTER][0]:grid.upper_bounds[StaggerLoc.CENTER][0]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1)) offset_lat = 180. / (lat.size) / 2. lat = np.linspace(90 - offset_lat, -90 + offset_lat, lat.size) gridYCenter = grid.get_coords(1) - lat_par = lat[grid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + lat_par = lat[grid.lower_bounds[StaggerLoc.CENTER][1]:grid.upper_bounds[StaggerLoc.CENTER][1]] gridYCenter[...] = lat_par.reshape((1, lat_par.size)) @@ -177,8 +181,8 @@ def test_grid_periodic(self): grid,_,_ = self.make_grid_periodic() self.examine_grid_attributes(grid) - @attr('serial') - @attr('slow') + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_create_2d(self): keywords = dict( # periodic specifies all valid combos of [pole_kind, num_peri_dims, periodic_dim, pole_dim] @@ -223,8 +227,8 @@ def test_grid_create_2d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @attr('serial') - @attr('slow') + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_create_3d(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -258,7 +262,6 @@ def test_grid_create_3d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @attr('serial') def test_grid_create_cubed_sphere(self): # keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -281,8 +284,6 @@ def test_grid_create_cubed_sphere(self): # [DecompFlag.DEFAULT, 6]], dtype=np.int32) # deLabelList = np.array([11,12,13,14,15,16], dtype=np.int32) - ESMF.Manager(debug=True) - grid = Grid(tilesize = 45, regDecompPTile = regDecompPTile, #decompFlagPTile = decompFlagPTile, #deLabelList = deLabelList, @@ -296,7 +297,7 @@ def test_grid_create_cubed_sphere(self): grid.destroy() # grid2.destroy() - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_2d(self): grid = self.make_grid_2d() @@ -316,11 +317,11 @@ def test_grid_slice_2d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1] - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() - grid.add_coords(staggerloc=ESMF.StaggerLoc.CORNER) + grid.add_coords(staggerloc=StaggerLoc.CORNER) grid_row = grid.get_coords(0, staggerloc=StaggerLoc.CORNER) grid_col = grid.get_coords(1, staggerloc=StaggerLoc.CORNER) @@ -347,7 +348,7 @@ def test_grid_slice_2d_corners(self): assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_3d(self): grid = self.make_grid_3d() @@ -367,7 +368,7 @@ def test_grid_slice_3d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1, 2) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1, 2] - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_3d_corners(self): grid = self.make_grid_3d() @@ -402,7 +403,7 @@ def test_grid_slice_3d_corners(self): assert grid3.coords[cvf][0].shape == (3, 2, 3) assert grid3.upper_bounds[cvf].tolist() == [3, 2, 3] - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_periodic(self): grid, x, y = self.make_grid_periodic() @@ -428,12 +429,13 @@ def test_grid_slice_periodic(self): assert grid3.coords[StaggerLoc.CORNER][0].shape == (3, 2) assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @attr('data') - @attr('serial') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_grid_created_from_file_scrip(self): + import esmpy reg_decomp = [pet_count(), 1] try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, pole_kind=[PoleKind.MONOPOLE, PoleKind.BIPOLE], @@ -628,238 +630,255 @@ def test_grid_area_3D(self): area[:] = areavals assert(np.all(area[...] == 12*np.ones([10, 20, 30]))) - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_gridspec1D(self): - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + import esmpy + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/gridspec1Dcoords.nc"), filetype=FileFormat.GRIDSPEC, add_corner_stagger=True, coord_names=["longitude", "latitude"]) self.examine_grid_attributes(grid) - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip(self): + import esmpy reg_decomp = [pet_count(), 1] try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp) except: raise NameError('grid_create_from_file_scrip failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_balanced_balanced failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_balanced_restfirst failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_balanced_restlast failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_balanced_cyclic failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restfirst_balanced failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restfirst_restfirst failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restfirst_restlast failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restfirst_cyclic failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restlast_balanced failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restlast_restfirst failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restlast_restlast failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_restlast_cyclic failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_cyclic_balanced failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_cyclic_restfirst failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_cyclic_restlast failed!') - @attr('data') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_cyclic_cyclic failed!') - diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py index 2df9f027a9..ea9b71bbaa 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py @@ -3,9 +3,10 @@ locstream unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +import pytest + +from esmpy import * +from esmpy.test.base import TestBase class TestLocStream(TestBase): @@ -50,7 +51,7 @@ def test_copy(self): assert np.all(l2["ESMF:X"] == [0, 1, 2, 3, 4]) - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice(self): locstream = LocStream(5, name="Test LocStream") @@ -67,7 +68,7 @@ def test_slice(self): assert(np.all(locstream["ESMF:X"] == np.array([0, 1, 2, 3, 4]))) - @expected_failure + @pytest.mark.xfail def test_pickle(self): locstream = LocStream(10, name="Test LocStream") @@ -75,7 +76,7 @@ def test_pickle(self): pickle.dumps(locstream) - @expected_failure + @pytest.mark.xfail def test_properties(self): locstream = LocStream(10, name="Test LocStream") locstream["ESMF:X"] = (1, 2, 3, 4, 5) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py similarity index 63% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py index 590ea363ab..88a537e642 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py @@ -3,21 +3,17 @@ mesh unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest +import pytest import os import inspect -import ESMF -from ESMF import * -from ESMF.test.base import TestBase, attr -from ESMF.util.mesh_utilities import * +from esmpy import * +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO +from esmpy.util.mesh_utilities import * class TestMesh(TestBase): - mg = Manager(debug=True) def check_mesh(self, mesh, nodeCoord, nodeOwner, elemCoord=None): @@ -50,17 +46,11 @@ def check_mesh(self, mesh, nodeCoord, nodeOwner, elemCoord=None): # this call fails if nodes and elements have not been added first # mesh.free_memory() + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_5(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_5_parallel() else: @@ -69,17 +59,11 @@ def test_mesh_5(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_10(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_10_parallel() else: @@ -88,17 +72,11 @@ def test_mesh_10(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -107,22 +85,16 @@ def test_mesh_50(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_moab(self): - # set this mesh to be created with the MOAB backend mg = Manager() mg.set_moab() elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -138,16 +110,10 @@ def test_mesh_50_moab(self): assert (mg.moab == False) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_ngons(self): parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -156,17 +122,11 @@ def test_mesh_50_ngons(self): self.check_mesh(mesh, nodeCoord, nodeOwner) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_mask_area(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn, elemMask, elemArea = \ mesh_create_50_parallel(domask=True, doarea=True) else: @@ -179,34 +139,23 @@ def test_mesh_50_mask_area(self): self.assertNumpyAll(mesh.area, elemArea) - @attr('data') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_mesh_create_from_file_scrip(self): - try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) - mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), filetype=FileFormat.SCRIP) - except: - raise NameError('mesh_create_from_file_scrip failed!') - @attr('data') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_mesh_create_from_file_esmfmesh(self): - try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) - mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), filetype=FileFormat.ESMFMESH) - except: - raise NameError('mesh_create_from_file_scrip failed!') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_copy(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -219,21 +168,9 @@ def test_mesh_copy(self): self.check_mesh(mesh2, nodeCoord, nodeOwner) # slicing is disabled in parallel - @attr('serial') + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_mesh_slicing(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_5_pentahexa_parallel() - else: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ + mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_5_pentahexa() mesh2 = mesh[0:5] @@ -255,16 +192,14 @@ def test_mesh_slicing(self): assert mesh3.size == [2, None] assert mesh3.size_owned == [2, None] - @attr('data') - @attr('serial') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_scrip(self): - try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), - filetype=FileFormat.SCRIP, - convert_to_dual=True) - except: - raise NameError('mesh_create_from_file_scrip failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), + filetype=FileFormat.SCRIP, + convert_to_dual=True) mesh2 = mesh[0:5] @@ -279,15 +214,13 @@ def test_slice_mesh_created_from_file_scrip(self): assert mesh2.size == [5, None] assert mesh2.size_owned == [5, None] - @attr('data') - @attr('serial') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_esmfmesh(self): - try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), - filetype=FileFormat.ESMFMESH) - except: - raise NameError('mesh_create_from_file_esmfmesh failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), + filetype=FileFormat.ESMFMESH) mesh2 = mesh[0:5] @@ -302,18 +235,16 @@ def test_slice_mesh_created_from_file_esmfmesh(self): assert mesh2.size_owned == [5, None] - @attr('data') - @attr('serial') - @expected_failure + @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") #TODO: remove expected failure once we have a smaller data file with mesh element coordinates to use # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): - try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne30np4-t2.nc"), - filetype=FileFormat.SCRIP) - except: - raise NameError('mesh_create_from_file_elem_coords failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne30np4-t2.nc"), + filetype=FileFormat.SCRIP) mesh2 = mesh[0:5] diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py new file mode 100644 index 0000000000..a8184efd60 --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py @@ -0,0 +1,29 @@ +""" +pytest tests +""" + +import pytest + +from esmpy.test.base import TestBase +from esmpy.api.esmpymanager import pet_count + +class TestPyTest(TestBase): + + @pytest.mark.xfail + @pytest.mark.skipif(pet_count()<3, reason="test must be run with more than 3 cores") + def test_pytest_singlecorefailure(self): + + print ("Test2: I AM PET {}".format(self.mg.local_pet)) + + if self.mg.local_pet == 2: + raise ValueError("Test failure on a single PET") + + # # this requires pytest-mpi package + # @pytest.mark.mpi(min_size=2) + # def test_pytest_mpi4py(self): + # from mpi4py import MPI + # + # comm = MPI.COMM_WORLD + # rank = comm.Get_rank() + # + # print ("Test1: I AM PET {} and rank {}".format(local_pet(), rank)) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py similarity index 70% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index 2e82f7b650..88a43f0c69 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -2,18 +2,16 @@ regrid unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest +import pytest import os -from ESMF import * -from ESMF.test.base import TestBase, attr -from ESMF.util.field_utilities import compare_fields -from ESMF.util.grid_utilities import * -from ESMF.util.mesh_utilities import * +from esmpy import * +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO +from esmpy.util.field_utilities import compare_fields +from esmpy.util.grid_utilities import * +from esmpy.util.mesh_utilities import * class TestRegrid(TestBase): @@ -34,9 +32,9 @@ def run_regridding(srcfield, dstfield, srcfracfield, dstfracfield): Field :: dstfracfield \n ''' # call the regridding functions - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -84,7 +82,8 @@ def test_field_regrid(self): line_type=LineType.CART, factors=False) _ = rh(srcfield, dstfield) - @attr('serial') + @pytest.mark.skipif(not constants._ESMF_USE_INMEM_FACTORS, reason="compiler does not support in-memory weights") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_regrid_factor_retrieval(self): # Test retrieving factors from a route handle. @@ -135,17 +134,11 @@ def test_field_regrid_factor_retrieval(self): keywords = dict(deep_copy=[False, True], as_dict=[False, True]) for k in self.iter_product_keywords(keywords): - try: - rh = Regrid(srcfield, dstfield, - regrid_method=RegridMethod.BILINEAR, - line_type=LineType.CART, factors=True, - create_rh=False, - unmapped_action=UnmappedAction.IGNORE) - except RuntimeError: - if constants._ESMF_USE_INMEM_FACTORS: - raise - else: - raise SkipTest("compiler does not support in-memory weights") + rh = Regrid(srcfield, dstfield, + regrid_method=RegridMethod.BILINEAR, + line_type=LineType.CART, factors=True, + create_rh=False, + unmapped_action=UnmappedAction.IGNORE) _ = rh(srcfield, dstfield) fl, fil, fdict = [None] * 3 # Reset at each loop @@ -187,7 +180,8 @@ def test_field_regrid_factor_retrieval(self): rh.destroy() - @attr('parallel') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file1(self): mgr = Manager() @@ -241,7 +235,8 @@ def test_field_regrid_file1(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file2(self): mgr = Manager() filename = 'esmpy_test_field_regrid_file2.nc' @@ -251,9 +246,9 @@ def test_field_regrid_file2(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -263,8 +258,8 @@ def test_field_regrid_file2(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -272,9 +267,9 @@ def test_field_regrid_file2(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -284,8 +279,8 @@ def test_field_regrid_file2(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -293,12 +288,12 @@ def test_field_regrid_file2(self): dstGridCoordLon[:] = lonm dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) - _ = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + _ = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) mgr.barrier() self.assertTrue(os.path.exists(filename)) @@ -312,14 +307,15 @@ def test_field_regrid_file2(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") # remove this test for 8.2.0 due to unexplained segv - def tet_field_regrid_file_withaux(self): + def _field_regrid_file_withaux(self): import os DD = os.path.join(os.getcwd(), "test/data") if not os.path.isdir(DD): os.makedirs(DD) - from ESMF.util.cache_data import cache_data_file + from esmpy.util.cache_data import cache_data_file cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) cache_data_file(os.path.join(DD, "T42_grid.nc")) @@ -332,21 +328,21 @@ def tet_field_regrid_file_withaux(self): mgr.barrier() grid1 = "test/data/ll2.5deg_grid.nc" - srcgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True) + srcgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) grid2 = "test/data/T42_grid.nc" - dstgrid = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True) + dstgrid = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) - _ = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE, - filemode=ESMF.FileMode.WITHAUX, + _ = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE, + filemode=esmpy.FileMode.WITHAUX, src_file=grid1, dst_file=grid2, - src_file_type=ESMF.FileFormat.SCRIP, - dst_file_type=ESMF.FileFormat.SCRIP) + src_file_type=esmpy.FileFormat.SCRIP, + dst_file_type=esmpy.FileFormat.SCRIP) mgr.barrier() self.assertTrue(os.path.exists(filename)) @@ -377,7 +373,8 @@ def tet_field_regrid_file_withaux(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file3(self): mgr = Manager() filename = 'esmpy_test_field_from_file.nc' @@ -388,9 +385,9 @@ def test_field_regrid_file3(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -400,8 +397,8 @@ def test_field_regrid_file3(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -409,9 +406,9 @@ def test_field_regrid_file3(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -421,8 +418,8 @@ def test_field_regrid_file3(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -431,9 +428,9 @@ def test_field_regrid_file3(self): dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) - xctfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) + xctfield = esmpy.Field(dstgrid) srcfield.data[:,:] = 24 xctfield.data[:,:] = 24 @@ -442,9 +439,9 @@ def test_field_regrid_file3(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertTrue(np.all(dstfield.data[:,:] == 0)) - regridS2D = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridS2D = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, create_rh=True, ignore_degenerate=False) mgr.barrier() @@ -454,7 +451,7 @@ def test_field_regrid_file3(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertNumpyAllClose(xctfield.data, dstfield.data) - regridS2D = ESMF.RegridFromFile(srcfield, dstfield, filename) + regridS2D = esmpy.RegridFromFile(srcfield, dstfield, filename) mgr.barrier() self.assertTrue(np.all(srcfield.data[:,:] == 24)) @@ -471,8 +468,6 @@ def test_field_regrid_file3(self): if os.path.isfile(path): os.remove(path) - - @attr('parallel') def test_field_regrid_file4(self): mgr = Manager() filename = 'routehandlefile.nc' @@ -483,9 +478,9 @@ def test_field_regrid_file4(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -495,8 +490,8 @@ def test_field_regrid_file4(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -504,9 +499,9 @@ def test_field_regrid_file4(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -516,8 +511,8 @@ def test_field_regrid_file4(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -526,9 +521,9 @@ def test_field_regrid_file4(self): dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) - xctfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) + xctfield = esmpy.Field(dstgrid) srcfield.data[:,:] = 24 xctfield.data[:,:] = 24 @@ -537,10 +532,10 @@ def test_field_regrid_file4(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertTrue(np.all(dstfield.data[:,:] == 0)) - regridS2D = ESMF.Regrid(srcfield, dstfield, + regridS2D = esmpy.Regrid(srcfield, dstfield, rh_filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, create_rh=True, ignore_degenerate=False) mgr.barrier() @@ -550,7 +545,7 @@ def test_field_regrid_file4(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertNumpyAllClose(xctfield.data, dstfield.data) - regridS2D = ESMF.RegridFromFile(srcfield, dstfield, rh_filename=filename) + regridS2D = esmpy.RegridFromFile(srcfield, dstfield, rh_filename=filename) mgr.barrier() self.assertTrue(np.all(srcfield.data[:,:] == 24)) @@ -567,17 +562,10 @@ def test_field_regrid_file4(self): if os.path.isfile(path): os.remove(path) + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_gridmesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -611,18 +599,10 @@ def test_field_regrid_gridmesh(self): rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE) dstfield = rh(srcfield, dstfield) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_zeroregion(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -649,7 +629,7 @@ def test_field_regrid_zeroregion(self): # regridding rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE, - dst_mask_values=np.array([0])) + dst_mask_values=np.atleast_1d(np.array([0]))) dstfield = rh(srcfield, dstfield, zero_region=Region.SELECT) # validate that the masked values were not zeroed out @@ -658,7 +638,8 @@ def test_field_regrid_zeroregion(self): if dstfield.grid.mask[StaggerLoc.CENTER][i, j] == 0: assert(dstfield[i, j] == 0) - @attr('parallel') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_zeroregion_select_ndbounds(self): # Test zero region select during a sparse matrix multiplication # having undistributed dimensions. @@ -679,8 +660,8 @@ def test_field_regrid_zeroregion_select_ndbounds(self): # Regrid in-memory rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.BILINEAR, - src_mask_values=np.array([0]), - dst_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), + dst_mask_values=np.atleast_1d(np.array([0])), unmapped_action=UnmappedAction.IGNORE) _ = rh(srcfield, dstfield, zero_region=Region.SELECT) @@ -692,7 +673,7 @@ def test_field_regrid_zeroregion_select_ndbounds(self): dstfield.data[:] = -999 filename = '_esmf_test_weights_.nc' _ = Regrid(srcfield, dstfield, regrid_method=RegridMethod.BILINEAR, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), unmapped_action=UnmappedAction.IGNORE, filename=filename) self.assertTrue(np.all(dstfield.data == -999)) @@ -700,28 +681,20 @@ def test_field_regrid_zeroregion_select_ndbounds(self): # Compute the regrid from file route handle rh2 = RegridFromFile(srcfield, dstfield, filename=filename) self.assertTrue(np.all(dstfield.data == -999)) - dstfield = rh2(srcfield, dstfield, zero_region=ESMF.Region.SELECT) + dstfield = rh2(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # Assert fill values are retained self.assertGreater(np.sum(dstfield.data == 33.33), 10) self.assertGreater(np.sum(dstfield.data == -999), 10) - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): if os.path.exists(filename): os.remove(filename) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_area(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -752,38 +725,29 @@ def test_field_regrid_area(self): if (dstarea.data[i] != 0.25): assert (dstarea.data[i] == 0.125) - @attr('parallel') def test_field_regrid_periodic(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid srcgrid = grid_create_from_bounds_periodic(60, 30, corners=True, domask=True) dstgrid = grid_create_from_bounds_periodic(55, 28, corners=True) # create the Fields - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # create the fraction fields - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_periodic(srcfield) exact_field = initialize_field_grid_periodic(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + src_mask_values=np.atleast_1d(np.array([0])), + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -802,7 +766,6 @@ def test_field_regrid_periodic(self): self.assertAlmostEqual(meanrel, 0.0016447124122954575) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_3d_bilinear_cartesian(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -811,18 +774,18 @@ def test_grid_grid_3d_bilinear_cartesian(self): dstgrid = grid_create_from_bounds_3d([0.5, 19.5], [0.5, 19.5], [0.5, 19.5], 19, 19, 19, corners=False) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_3d(srcfield) exactfield = initialize_field_grid_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL @@ -832,7 +795,6 @@ def test_grid_grid_3d_bilinear_cartesian(self): self.assertAlmostEqual(meanrel, 0.00215601743167) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_3d_bilinear_spherical(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -841,18 +803,18 @@ def test_grid_grid_3d_bilinear_spherical(self): dstgrid = grid_create_from_bounds_periodic_3d(50, 50, 11, corners=False) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_periodic_3d(srcfield) exactfield = initialize_field_grid_periodic_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL @@ -862,7 +824,6 @@ def test_grid_grid_3d_bilinear_spherical(self): self.assertAlmostEqual(meanrel, 0.00061587737764545617) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_regrid_csrv_mask_3D(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -871,20 +832,20 @@ def test_grid_grid_regrid_csrv_mask_3D(self): dstgrid = grid_create_from_bounds_3d([0.5, 19.5], [0.5, 19.5], [0.5, 19.5], 19, 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_3d(srcfield) exactfield = initialize_field_grid_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -903,7 +864,6 @@ def test_grid_grid_regrid_csrv_mask_3D(self): self.assertAlmostEqual(meanrel, 0.0021560174316746865) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_regrid_csrv_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -912,21 +872,21 @@ def test_grid_grid_regrid_csrv_mask(self): dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + src_mask_values=np.atleast_1d(np.array([0])), + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -945,7 +905,6 @@ def test_grid_grid_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_regrid_csrv_2nd_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -954,21 +913,21 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE_2ND, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + src_mask_values=np.atleast_1d(np.array([0])), + regrid_method=esmpy.RegridMethod.CONSERVE_2ND, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -987,7 +946,6 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): self.assertAlmostEqual(meanrel, 0.0020296891000258252) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') def test_grid_grid_regrid_srcmask_types(self): # NOTE: this tests an old issue where the items of a grid were not properly set when # the grid coord_typekind differed from the field typekind. @@ -996,25 +954,25 @@ def test_grid_grid_regrid_srcmask_types(self): # create two unique Grid objects srcgrid = grid_create_from_bounds([0, 21], [0, 21], 21, 21, corners=True, domask=True, - ctk=ESMF.TypeKind.R4) + ctk=esmpy.TypeKind.R4) dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=[0], - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1033,18 +991,10 @@ def test_grid_grid_regrid_srcmask_types(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv_mask(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn, elemMask, elemArea = \ mesh_create_50_parallel(domask=True, doarea=True) else: @@ -1055,13 +1005,13 @@ def test_grid_mesh_regrid_csrv_mask(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn, @@ -1069,10 +1019,10 @@ def test_grid_mesh_regrid_csrv_mask(self): exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + src_mask_values=np.atleast_1d(np.array([0])), + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1091,18 +1041,10 @@ def test_grid_mesh_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.038806630051265847) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1113,21 +1055,21 @@ def test_grid_mesh_regrid_csrv(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) # create Fields - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - norm_type=ESMF.NormType.FRACAREA, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + norm_type=esmpy.NormType.FRACAREA, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1147,21 +1089,13 @@ def test_grid_mesh_regrid_csrv(self): self.assertAlmostEqual(meanrel, 0.037733241800767432) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_mask(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a grid + # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, domask=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1169,44 +1103,36 @@ def test_grid_mesh_regrid_mask(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='srcfield') - dstfield = ESMF.Field(grid, name='dstfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield') + dstfield = esmpy.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield, domask=True) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - dst_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + dst_mask_values=np.atleast_1d(np.array([0])), + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 20E-1, 20E-1, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a grid + # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1214,43 +1140,35 @@ def test_grid_mesh_regrid(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='srcfield') - dstfield = ESMF.Field(grid, name='dstfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield') + dstfield = esmpy.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1258,46 +1176,38 @@ def test_field_regrid_extrapolation(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(grid, name='srcfield') - dstfield = ESMF.Field(mesh, name='dstfield') - exactfield = ESMF.Field(mesh, name='exactfield') + srcfield = esmpy.Field(grid, name='srcfield') + dstfield = esmpy.Field(mesh, name='dstfield') + exactfield = esmpy.Field(mesh, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) exactfield = initialize_field_mesh(exactfield, nodeCoord, nodeOwner, elemType, elemConn) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - extrap_method=ESMF.ExtrapMethod.NEAREST_IDAVG, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + extrap_method=esmpy.ExtrapMethod.NEAREST_IDAVG, extrap_num_src_pnts=10, extrap_dist_exponent=1.2, - unmapped_action=ESMF.UnmappedAction.ERROR) + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation_creepfill(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1305,41 +1215,34 @@ def test_field_regrid_extrapolation_creepfill(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='dstfield') - dstfield = ESMF.Field(grid, name='srcfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='dstfield') + dstfield = esmpy.Field(grid, name='srcfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - extrap_method=ESMF.ExtrapMethod.CREEP_FILL, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + extrap_method=esmpy.ExtrapMethod.CREEP_FILL, extrap_num_levels=100) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_mesh_regrid(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create two unique Mesh objects - if parallel: + srcmesh = None + dstmesh = None + if pet_count() == 4: srcmesh, nodeCoordSrc, nodeOwnerSrc, elemTypeSrc, elemConnSrc = \ mesh_create_50_parallel() dstmesh, nodeCoordDst, nodeOwnerDst, elemTypeDst, elemConnDst = \ @@ -1351,11 +1254,11 @@ def test_mesh_mesh_regrid(self): mesh_create_10() # create ESMP_Field objects on the Meshes - srcfield = ESMF.Field(srcmesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(srcmesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfield = ESMF.Field(dstmesh, name='dstfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfracfield = ESMF.Field(dstmesh, name='dstfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - exactfield = ESMF.Field(dstmesh, name='exactfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(srcmesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(srcmesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfield = esmpy.Field(dstmesh, name='dstfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfracfield = esmpy.Field(dstmesh, name='dstfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + exactfield = esmpy.Field(dstmesh, name='exactfield', meshloc=esmpy.MeshLoc.ELEMENT) # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoordSrc, nodeOwnerSrc, @@ -1364,10 +1267,10 @@ def test_mesh_mesh_regrid(self): elemTypeDst, elemConnDst) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - norm_type=ESMF.NormType.FRACAREA, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + norm_type=esmpy.NormType.FRACAREA, + unmapped_action=esmpy.UnmappedAction.ERROR, ignore_degenerate=True, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) @@ -1388,18 +1291,10 @@ def test_mesh_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.037109375) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def est_grid_mesh_pentatri_regrid_csrv(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -1410,13 +1305,13 @@ def est_grid_mesh_pentatri_regrid_csrv(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1426,9 +1321,9 @@ def est_grid_mesh_pentatri_regrid_csrv(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1447,11 +1342,8 @@ def est_grid_mesh_pentatri_regrid_csrv(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - # TODO: this test is disable, I don't remember why + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def est_grid_mesh_pentatri_regrid_csrv_simple(self): - if ESMF.pet_count() > 1: - raise NameError('This test can only be run in serial!') - # create a Mesh mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_4_ngons() @@ -1460,13 +1352,13 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1476,9 +1368,9 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1497,18 +1389,10 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - @attr('parallel') + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_pentatri_regrid_bilinear(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -1519,11 +1403,11 @@ def test_grid_mesh_pentatri_regrid_bilinear(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1533,9 +1417,9 @@ def test_grid_mesh_pentatri_regrid_bilinear(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py new file mode 100644 index 0000000000..c06cbe1121 --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py @@ -0,0 +1,44 @@ +""" +vm unit test file +""" + +import pytest + +from esmpy import * +from esmpy.test.base import TestBase + +class TestVM(TestBase): + def test_vm_broadcast(self): + + bcst = np.ones(4, dtype=np.float64) + if self.mg.local_pet != 0: + bcst[:] = 2 + + if self.mg.local_pet == 0: + assert(np.all(bcst == 1)) + else: + assert(np.all(bcst == 2)) + + self.mg.barrier() + self.mg._broadcast_(bcst, 4) + self.mg.barrier() + assert(np.all(bcst == 1)) + + self.mg.barrier() + + def test_vm_reduce(self): + send = np.ones(4, dtype=np.float64) + recv = np.zeros(4, dtype=np.float64) + + mg = Manager() + + self.mg.barrier() + self.mg._reduce_(send, recv, 4, Reduce.SUM, 0) + self.mg.barrier() + + if self.mg.local_pet == 0: + assert(np.all(recv == self.mg.pet_count)) + else: + assert(np.all(recv == 0)) + + self.mg.barrier() diff --git a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py similarity index 93% rename from src/addon/ESMPy/src/ESMF/test/test_cbindings.py rename to src/addon/ESMPy/src/esmpy/test/test_cbindings.py index f6dcca5022..deb06fce9a 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py +++ b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py @@ -4,12 +4,13 @@ unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +import pytest -import numpy as np +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase +import numpy as np class TestCbindings(TestBase): @@ -33,7 +34,7 @@ def test_interfaceint(self): interfaceint = ESMP_InterfaceInt(Narray) - @expected_failure + @pytest.mark.xfail def test_interfaceint2(self): # This test should fail try: @@ -43,7 +44,7 @@ def test_interfaceint2(self): except: raise TypeError('FAIL: tuples cannot be used in place of numpy.array') - @expected_failure + @pytest.mark.xfail def test_interfaceint3(self): # This test should fail try: diff --git a/src/addon/ESMPy/src/ESMF/util/__init__.py b/src/addon/ESMPy/src/esmpy/util/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/__init__.py rename to src/addon/ESMPy/src/esmpy/util/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/util/cache_data.py b/src/addon/ESMPy/src/esmpy/util/cache_data.py similarity index 88% rename from src/addon/ESMPy/src/ESMF/util/cache_data.py rename to src/addon/ESMPy/src/esmpy/util/cache_data.py index 4b414209f3..ab3171bfb6 100644 --- a/src/addon/ESMPy/src/ESMF/util/cache_data.py +++ b/src/addon/ESMPy/src/esmpy/util/cache_data.py @@ -1,9 +1,7 @@ import os -DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' - # If fname doesn't exist, retrieve it from the remote server via http. -def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): +def cache_data_file(fname, DATA_URL_ROOT=None): import sys if sys.version_info[0] >= 3: from urllib.request import urlopen, URLError @@ -12,6 +10,9 @@ def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): from shutil import copyfileobj + if DATA_URL_ROOT == None: + DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' + status_ok = True if not os.path.exists(fname): url = os.path.join(DATA_URL_ROOT, os.path.basename(fname)) @@ -30,7 +31,7 @@ def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): return status_ok -def cache_data_files(): +def cache_data_files(dataurl=None): # Filenames to download. datafilelist = ["aggregAtlanticESTOFS.nc", "GRIDSPEC_ACCESS1.nc", @@ -49,6 +50,6 @@ def cache_data_files(): # Download each test file. for fname in datafilelist: # Retrieve the data files needed for the test cases from the remote server. - status_ok = cache_data_file(os.path.join(datadir, fname)) + status_ok = cache_data_file(os.path.join(datadir, fname), dataurl) if not status_ok: raise IOError("Error downloading '{}'".format(fname)) diff --git a/src/addon/ESMPy/src/ESMF/util/decorators.py b/src/addon/ESMPy/src/esmpy/util/decorators.py similarity index 66% rename from src/addon/ESMPy/src/ESMF/util/decorators.py rename to src/addon/ESMPy/src/esmpy/util/decorators.py index 8d1b351e4e..38eb52631d 100644 --- a/src/addon/ESMPy/src/ESMF/util/decorators.py +++ b/src/addon/ESMPy/src/esmpy/util/decorators.py @@ -9,30 +9,8 @@ import warnings import functools -from ESMF.api.constants import LogKind, _ESMF_NETCDF -from ESMF.util.exceptions import NetCDFMissing - -try: - import nose - - def expected_failure(test): - @functools.wraps(test) - def inner(*args, **kwargs): - try: - test(*args, **kwargs) - except Exception: - raise nose.SkipTest - return inner -except: - def expected_failure(test): - @functools.wraps(test) - def inner(*args, **kwargs): - try: - test(*args, **kwargs) - except: - raise AssertionError('SkipTest: Failure expected') - return inner - +from esmpy.api.constants import LogKind, _ESMF_NETCDF, _ESMF_PIO +from esmpy.util.exceptions import NetCDFMissing, PIOMissing def beta(func): '''This is a decorator that can be used to mark functions @@ -75,7 +53,7 @@ def initialize(func): @functools.wraps(func) def new_func(*args, **kwargs): - from ESMF.api import esmpymanager + from esmpy.api import esmpymanager esmp = esmpymanager.Manager(debug = False) return func(*args, **kwargs) @@ -87,7 +65,7 @@ def netcdf(func): @functools.wraps(func) def new_func(*args, **kwargs): - from ESMF.api.constants import _ESMF_NETCDF + from esmpy.api.constants import _ESMF_NETCDF if _ESMF_NETCDF: return func(*args, **kwargs) @@ -96,3 +74,30 @@ def new_func(*args, **kwargs): return new_func +def pio(func): + '''This is a decorator that can be used to error out of functions + if PIO is not available. (e.g. if ESMF was built using ESMF_COMM=mpiuni).''' + + @functools.wraps(func) + def new_func(*args, **kwargs): + from esmpy.api.constants import _ESMF_PIO + + if _ESMF_PIO: + return func(*args, **kwargs) + else: + raise PIOMissing("This function requires ESMF to have been built with PIO.") + + return new_func + +def PETx4(func): + '''This is a decorator that can be used to error out of functions + if execution does not have 4 cores available.''' + + @functools.wraps(func) + def new_func(*args, **kwargs): + if esmpy.pet_count() == 4: + return func(*args, **kwargs) + else: + raise PETx4NotSatisfied("This function requires 4 core execution.") + + return new_func diff --git a/src/addon/ESMPy/src/ESMF/util/enum/LICENSE b/src/addon/ESMPy/src/esmpy/util/enum/LICENSE similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/LICENSE rename to src/addon/ESMPy/src/esmpy/util/enum/LICENSE diff --git a/src/addon/ESMPy/src/ESMF/util/enum/README b/src/addon/ESMPy/src/esmpy/util/enum/README similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/README rename to src/addon/ESMPy/src/esmpy/util/enum/README diff --git a/src/addon/ESMPy/src/ESMF/util/enum/__init__.py b/src/addon/ESMPy/src/esmpy/util/enum/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/__init__.py rename to src/addon/ESMPy/src/esmpy/util/enum/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/util/enum/doc/enum.pdf b/src/addon/ESMPy/src/esmpy/util/enum/doc/enum.pdf similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/doc/enum.pdf rename to src/addon/ESMPy/src/esmpy/util/enum/doc/enum.pdf diff --git a/src/addon/ESMPy/src/ESMF/util/enum/doc/enum.rst b/src/addon/ESMPy/src/esmpy/util/enum/doc/enum.rst similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/doc/enum.rst rename to src/addon/ESMPy/src/esmpy/util/enum/doc/enum.rst diff --git a/src/addon/ESMPy/src/ESMF/util/esmpyarray.py b/src/addon/ESMPy/src/esmpy/util/esmpyarray.py similarity index 97% rename from src/addon/ESMPy/src/ESMF/util/esmpyarray.py rename to src/addon/ESMPy/src/esmpy/util/esmpyarray.py index 0683eae8fc..9bb7605c17 100755 --- a/src/addon/ESMPy/src/ESMF/util/esmpyarray.py +++ b/src/addon/ESMPy/src/esmpy/util/esmpyarray.py @@ -5,7 +5,7 @@ """ #### IMPORT LIBRARIES ######################################################### -import ESMF.api.constants as constants +import esmpy.api.constants as constants import numpy as np import numpy.ma as ma import ctypes as ct @@ -16,7 +16,7 @@ def ndarray_from_esmf(data, dtype, shape): :param data: buffer of fortran allocated ESMF array :type data: ctypes void_p :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: numpy array representing the data with dtype and shape @@ -50,7 +50,7 @@ def __new__(cls, data, mask, dtype, shape): :param mask: mask corresponding to the fortran allocated ESMF array :type mask: list :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: MaskedArray object @@ -93,7 +93,7 @@ def __new__(cls, data, dtype, shape): :param data: buffer of fortran allocated ESMF array :type data: ctypes void_p :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: Array object diff --git a/src/addon/ESMPy/src/ESMF/util/exceptions.py b/src/addon/ESMPy/src/esmpy/util/exceptions.py similarity index 83% rename from src/addon/ESMPy/src/ESMF/util/exceptions.py rename to src/addon/ESMPy/src/esmpy/util/exceptions.py index 4075087fc8..746692b6a5 100644 --- a/src/addon/ESMPy/src/ESMF/util/exceptions.py +++ b/src/addon/ESMPy/src/esmpy/util/exceptions.py @@ -10,14 +10,27 @@ class ESMPyException(Exception): """Base class for errors in the ESMPy package.""" pass -class RequiredArgs(ESMPyException): - """Required arguments were not specified.""" +class ESMPyWarning(Warning): + """Base class for warnings in the ESMPy package.""" + pass + +class VersionMismatch(ESMPyException): + """The ESMF installation is not compatible with this version of ESMPy.""" + pass + +class VersionWarning(ESMPyWarning): + """The ESMF and/or ESMPy installations are beta version which may not be fully compatible.""" pass class NetCDFMissing(ESMPyException): """ESMF was not built with the NetCDF package.""" pass +class PIOMissing(ESMPyException): + """ESMF was not built with PIO support.""" + pass + + class MethodNotImplemented(ESMPyException): """Raised when an unimplemented method is called.""" pass @@ -26,6 +39,9 @@ class SerialMethod(ESMPyException): """This method is not safe to run in parallel!""" pass +class RequiredArgs(ESMPyException): + """Required arguments were not specified.""" + pass class GridException(ESMPyException): @@ -79,12 +95,3 @@ class FieldDOError(FieldException): """Raised when an attempt is made to build a Field on an undefined discretization object (e.g. not a Grid or a Mesh)""" pass - -class TestException(ESMPyException): - """Base class for errors in the ESMPy testing.""" - pass - -class TestGridWriteBeforeCoords(TestException): - """Raised when an attempt is made to write a Grid before c - coordinates have been specified""" - pass diff --git a/src/addon/ESMPy/src/ESMF/util/field_utilities.py b/src/addon/ESMPy/src/esmpy/util/field_utilities.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/util/field_utilities.py rename to src/addon/ESMPy/src/esmpy/util/field_utilities.py index af85c5977f..bda753fa62 100644 --- a/src/addon/ESMPy/src/ESMF/util/field_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/field_utilities.py @@ -3,14 +3,14 @@ """ import numpy as np -import ESMF +import esmpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, dstfracfield=None, mass1=None, mass2=None, - regrid_method=ESMF.RegridMethod.CONSERVE, + regrid_method=esmpy.RegridMethod.CONSERVE, uninitval=422397696., mask_values=[0]): """ Compare the values of two fields to verify the accuracy of a Regrid. The @@ -32,7 +32,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, import numpy.ma as ma parallel = False - if ESMF.pet_count() > 1: + if esmpy.pet_count() > 1: parallel = True correct = False @@ -54,7 +54,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, field2_flat = np.ravel(field2.data) dstfracfield_flat = np.ravel(dstfracfield.data) # setup mask, no Mask on a Mesh (yet) so need to look at the type first - if (isinstance(field2.grid, ESMF.Grid)) and \ + if (isinstance(field2.grid, esmpy.Grid)) and \ (not isinstance(field2.grid.mask[field2.staggerloc], type(None))): if not isinstance(field2.grid.mask[field2.staggerloc], type(None)): field2mask_flat = [True if x in mask_values else False for x in field2.grid.mask[field2.staggerloc].flatten().tolist()] @@ -105,7 +105,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, itrp_mean = False itrp_max = False csrv = False - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: if mass1_global == 0.: csrv_error_global = abs(mass2_global - mass1_global) else: @@ -123,7 +123,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, csrv = True # print out diagnostic information - print ("\n Mean relative error = "+str(total_error_global)) + print (" Mean relative error = "+str(total_error_global)) print (" Max relative error = "+str(max_error_global)) print (" Conservation error = "+str(csrv_error_global)) #print (" Min error = "+str(min_error_global)) @@ -140,9 +140,9 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, # print pass or fail if (itrp_mean and itrp_max and csrv): - print ("PET{0} - PASS".format(ESMF.local_pet())) + print ("PET{0} - PASS".format(esmpy.local_pet())) correct = True else: - print ("PET{0} - FAIL".format(ESMF.local_pet())) + print ("PET{0} - FAIL".format(esmpy.local_pet())) - return total_error_global, csrv_error_global, correct \ No newline at end of file + return total_error_global, csrv_error_global, correct diff --git a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py b/src/addon/ESMPy/src/esmpy/util/grid_utilities.py similarity index 78% rename from src/addon/ESMPy/src/ESMF/util/grid_utilities.py rename to src/addon/ESMPy/src/esmpy/util/grid_utilities.py index cf2492a432..83597f85ca 100644 --- a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/grid_utilities.py @@ -10,11 +10,11 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') -def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doarea=False, ctk=ESMF.TypeKind.R8): +def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doarea=False, ctk=esmpy.TypeKind.R8): """ Create a 2 dimensional Grid using the bounds of the domain defined in the `xdom` and `ydom` lists. The parameters `nx` and `ny` are used to define the number coordinate points between the bounds of the domain. @@ -45,7 +45,7 @@ def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doa return grid -def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=False, corners=False, domask=False, doarea=False, ctk=ESMF.TypeKind.R8): +def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=False, corners=False, domask=False, doarea=False, ctk=esmpy.TypeKind.R8): """ Create a 2 dimensional Grid using the bounds of the x and y coordiantes. :param xcoords: The 1st dimension or 'x' coordinates at cell centers, as a Python list or numpy Array @@ -62,45 +62,45 @@ def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=Fals # create a grid given the number of grid cells in each dimension, the center stagger location is allocated, the # Cartesian coordinate system and type of the coordinates are specified max_index = np.array([len(xcoords), len(ycoords)]) - grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER], coord_sys=ESMF.CoordSys.CART, coord_typekind=ctk) + grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER], coord_sys=esmpy.CoordSys.CART, coord_typekind=ctk) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(x) - x_par = xcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER][x]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][x]] + x_par = xcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER][x]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][x]] gridXCenter[...] = x_par.reshape((x_par.size, 1)) gridYCenter = grid.get_coords(y) - y_par = ycoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER][y]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][y]] + y_par = ycoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER][y]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][y]] gridYCenter[...] = y_par.reshape((1, y_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][x] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][x] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][y] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][y] + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][x] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][x] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][y] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][y] - gridXCorner = grid.get_coords(x, staggerloc=ESMF.StaggerLoc.CORNER) + gridXCorner = grid.get_coords(x, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :] = xcorners[i0+lbx, 0] gridXCorner[i0 + 1, :] = xcorners[i0+lbx, 1] - gridYCorner = grid.get_coords(y, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(y, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1] = ycorners[i1+lby, 0] gridYCorner[:, i1 + 1] = ycorners[i1+lby, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.any() < 2.25) & (1.75 <= gridYCenter.any() < 2.25))] = 0 # add arbitrary areas values if doarea: - area = grid.add_item(ESMF.GridItem.AREA) + area = grid.add_item(esmpy.GridItem.AREA) area[:] = 5.0 return grid @@ -147,38 +147,38 @@ def grid_create_from_coordinates_periodic(longitudes, latitudes, lon_corners=Fal # create a grid given the number of grid cells in each dimension the center stagger location is allocated max_index = np.array([len(longitudes), len(latitudes)]) - grid = ESMF.Grid(max_index, num_peri_dims=1, staggerloc=[ESMF.StaggerLoc.CENTER]) + grid = esmpy.Grid(max_index, num_peri_dims=1, staggerloc=[esmpy.StaggerLoc.CENTER]) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(lon) - lon_par = longitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lon]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lon]] + lon_par = longitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lon]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lon]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1)) gridYCenter = grid.get_coords(lat) - lat_par = latitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lat]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lat]] + lat_par = latitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lat]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lat]] gridYCenter[...] = lat_par.reshape((1, lat_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lon] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lon] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lat] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lat] + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lon] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lon] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lat] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lat] - gridXCorner = grid.get_coords(lon, staggerloc=ESMF.StaggerLoc.CORNER) + gridXCorner = grid.get_coords(lon, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :] = lon_corners[i0+lbx, 0] gridXCorner[i0 + 1, :] = lon_corners[i0+lbx, 1] - gridYCorner = grid.get_coords(lat, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(lat, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1] = lat_corners[i1+lby, 0] gridYCorner[:, i1 + 1] = lat_corners[i1+lby, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.any() < 2.25) & (1.75 <= gridYCenter.any() < 2.25))] = 0 @@ -242,49 +242,49 @@ def grid_create_from_coordinates_3d(xcoords, ycoords, zcoords, xcorners=False, y # create a grid given the number of grid cells in each dimension, the center stagger location is allocated and the # Cartesian coordinate system is specified max_index = np.array([len(xcoords), len(ycoords), len(zcoords)]) - grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER_VCENTER], coord_sys=ESMF.CoordSys.CART) + grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER_VCENTER], coord_sys=esmpy.CoordSys.CART) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(x) - x_par = xcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][x]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][x]] + x_par = xcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][x]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][x]] gridXCenter[...] = x_par.reshape(x_par.size, 1, 1) gridYCenter = grid.get_coords(y) - y_par = ycoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][y]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][y]] + y_par = ycoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][y]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][y]] gridYCenter[...] = y_par.reshape(1, y_par.size, 1) gridZCenter = grid.get_coords(z) - z_par = zcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][z]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][z]] + z_par = zcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][z]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][z]] gridZCenter[...] = z_par.reshape(1, 1, z_par.size) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER_VFACE]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][x] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][x] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][y] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][y] - lbz = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][z] - ubz = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][z] - - gridXCorner = grid.get_coords(x, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + grid.add_coords([esmpy.StaggerLoc.CORNER_VFACE]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][x] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][x] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][y] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][y] + lbz = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][z] + ubz = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][z] + + gridXCorner = grid.get_coords(x, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :, :] = xcorners[i0+lbx, 0] gridXCorner[i0 + 1, :, :] = xcorners[i0+lbx, 1] - gridYCorner = grid.get_coords(y, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + gridYCorner = grid.get_coords(y, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i1 in range(uby - lby - 1): gridYCorner[:, i1, :] = ycorners[i1+lby, 0] gridYCorner[:, i1 + 1, :] = ycorners[i1+lby, 1] - gridZCorner = grid.get_coords(z, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + gridZCorner = grid.get_coords(z, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i2 in range(ubz - lbz - 1): gridZCorner[:, :, i2] = zcorners[i2+lbz, 0] gridZCorner[:, :, i2 + 1] = zcorners[i2+lbz, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 < gridXCenter.data < 2.25) & (1.75 < gridYCenter.data < 2.25) & @@ -292,7 +292,7 @@ def grid_create_from_coordinates_3d(xcoords, ycoords, zcoords, xcorners=False, y # add arbitrary areas values if doarea: - area = grid.add_item(ESMF.GridItem.AREA) + area = grid.add_item(esmpy.GridItem.AREA) area[:] = 5.0 return grid @@ -350,49 +350,49 @@ def grid_create_from_coordinates_periodic_3d(longitudes, latitudes, heights, # create a grid given the number of grid cells in each dimension the center stagger location is allocated max_index = np.array([len(longitudes), len(latitudes), len(heights)]) - grid = ESMF.Grid(max_index, num_peri_dims=1, staggerloc=[ESMF.StaggerLoc.CENTER]) + grid = esmpy.Grid(max_index, num_peri_dims=1, staggerloc=[esmpy.StaggerLoc.CENTER]) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(lon) - lon_par = longitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lon]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lon]] + lon_par = longitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lon]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lon]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1, 1)) gridYCenter = grid.get_coords(lat) - lat_par = latitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lat]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lat]] + lat_par = latitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lat]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lat]] gridYCenter[...] = lat_par.reshape((1, lat_par.size, 1)) gridZCenter = grid.get_coords(z) - z_par = heights[grid.lower_bounds[ESMF.StaggerLoc.CENTER][z]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][z]] + z_par = heights[grid.lower_bounds[esmpy.StaggerLoc.CENTER][z]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][z]] gridZCenter[...] = z_par.reshape((1, 1, z_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lon] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lon] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lat] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lat] - lbz = grid.lower_bounds[ESMF.StaggerLoc.CORNER][z] - ubz = grid.upper_bounds[ESMF.StaggerLoc.CORNER][z] - - gridXCorner = grid.get_coords(lon, staggerloc=ESMF.StaggerLoc.CORNER) + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lon] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lon] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lat] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lat] + lbz = grid.lower_bounds[esmpy.StaggerLoc.CORNER][z] + ubz = grid.upper_bounds[esmpy.StaggerLoc.CORNER][z] + + gridXCorner = grid.get_coords(lon, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :, :] = lon_corners[i0+lbx, 0] gridXCorner[i0 + 1, :, :] = lon_corners[i0+lbx, 1] - gridYCorner = grid.get_coords(lat, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(lat, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1, :] = lat_corners[i1+lby, 0] gridYCorner[:, i1 + 1, :] = lat_corners[i1+lby, 1] - gridZCorner = grid.get_coords(z, staggerloc=ESMF.StaggerLoc.CORNER) + gridZCorner = grid.get_coords(z, staggerloc=esmpy.StaggerLoc.CORNER) for i2 in range(ubz - lbz - 1): gridZCorner[:, :, i2] = z_corners[i2+lbz, 0] gridZCorner[:, :, i2 + 1] = z_corners[i2+lbz, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.data < 2.25) & (1.75 <= gridYCenter.data < 2.25) & @@ -401,19 +401,19 @@ def grid_create_from_coordinates_periodic_3d(longitudes, latitudes, heights, return grid def initialize_field_grid(field, domask=False, doarea=False): - ''' + """ PRECONDITIONS: A Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ if domask: - mask = field.grid.get_item(ESMF.GridItem.MASK) + mask = field.grid.get_item(esmpy.GridItem.MASK) # get the coordinate pointers and set the coordinates [x,y] = [0, 1] - gridXCoord = field.grid.get_coords(0, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(1, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(0, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(1, esmpy.StaggerLoc.CENTER) field.data[:] = 20.0 + gridXCoord**2 + gridXCoord*gridYCoord + gridYCoord**2 @@ -423,20 +423,20 @@ def initialize_field_grid(field, domask=False, doarea=False): return field def initialize_field_grid_periodic(field): - ''' + """ PRECONDITIONS: A Field has been created as 'field' with a 'grid' where coordinates have been set on both the center and corner stagger locations. \n POSTCONDITIONS: The 'field' has been initialized to an analytic field.\n RETURN VALUES: \n Field :: field \n - ''' + """ DEG2RAD = 3.141592653589793/180.0 # get the coordinate pointers and set the coordinates [x,y] = [0, 1] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER) field.data[:] = 2.0 + np.cos(DEG2RAD*gridXCoord)**2 * \ np.cos(2.0*DEG2RAD*(90.0 - gridYCoord)) @@ -444,21 +444,21 @@ def initialize_field_grid_periodic(field): return field def initialize_field_grid_periodic_3d(field): - ''' + """ PRECONDITIONS: A Field has been created as 'field' with a 'grid' where coordinates have been set on both the center and corner stagger locations. \n POSTCONDITIONS: The 'field' has been initialized to an analytic field.\n RETURN VALUES: \n Field :: field \n - ''' + """ DEG2RAD = 3.141592653589793/180.0 # get the coordinate pointers and set the coordinates [x,y,z] = [0, 1, 2] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER) - gridZCoord = field.grid.get_coords(z, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER) + gridZCoord = field.grid.get_coords(z, esmpy.StaggerLoc.CENTER) field.data[:] = 2.0 + np.cos(DEG2RAD*gridXCoord)**2 * \ np.cos(2.0*DEG2RAD*(90.0 - gridYCoord)) + \ @@ -467,20 +467,20 @@ def initialize_field_grid_periodic_3d(field): return field def initialize_field_grid_3d(field, domask=False): - ''' + """ PRECONDITIONS: A Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ if domask: - mask = field.grid.get_item(ESMF.GridItem.MASK) + mask = field.grid.get_item(esmpy.GridItem.MASK) # get the coordinate pointers and set the coordinates [x,y,z] = [0,1,2] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER_VCENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER_VCENTER) - gridZCoord = field.grid.get_coords(z, ESMF.StaggerLoc.CENTER_VCENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER_VCENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER_VCENTER) + gridZCoord = field.grid.get_coords(z, esmpy.StaggerLoc.CENTER_VCENTER) field.data[:]=20.0 + gridXCoord**2 + gridXCoord*gridYCoord + gridZCoord**2 @@ -491,16 +491,16 @@ def initialize_field_grid_3d(field, domask=False): def compute_mass_grid(valuefield, dofrac=False, fracfield=None, uninitval=422397696.): - ''' + """ PRECONDITIONS: 'fracfield' contains the fractions of each cell which contributed to a regridding operation involving 'valuefield. 'dofrac' is a boolean value that gives the option to not use the 'fracfield'.\n POSTCONDITIONS: The mass of the data field is computed.\n RETURN VALUES: float :: mass \n - ''' + """ mass = 0.0 - areafield = ESMF.Field(valuefield.grid, name='areafield') + areafield = esmpy.Field(valuefield.grid, name='areafield') areafield.get_area() ind = np.where(valuefield.data != uninitval) diff --git a/src/addon/ESMPy/src/ESMF/util/helpers.py b/src/addon/ESMPy/src/esmpy/util/helpers.py similarity index 87% rename from src/addon/ESMPy/src/ESMF/util/helpers.py rename to src/addon/ESMPy/src/esmpy/util/helpers.py index 98e4973689..a7087de0e6 100644 --- a/src/addon/ESMPy/src/ESMF/util/helpers.py +++ b/src/addon/ESMPy/src/esmpy/util/helpers.py @@ -1,5 +1,5 @@ -from ESMF import Manager -from ESMF.api.constants import Reduce +from esmpy import Manager +from esmpy.api.constants import Reduce import numpy as np diff --git a/src/addon/ESMPy/src/ESMF/util/itester.py b/src/addon/ESMPy/src/esmpy/util/itester.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/itester.py rename to src/addon/ESMPy/src/esmpy/util/itester.py diff --git a/src/addon/ESMPy/src/ESMF/util/locstream_utilities.py b/src/addon/ESMPy/src/esmpy/util/locstream_utilities.py similarity index 77% rename from src/addon/ESMPy/src/ESMF/util/locstream_utilities.py rename to src/addon/ESMPy/src/esmpy/util/locstream_utilities.py index dac2b07bb1..9dda92df3c 100644 --- a/src/addon/ESMPy/src/ESMF/util/locstream_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/locstream_utilities.py @@ -10,7 +10,7 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') @@ -22,10 +22,10 @@ def create_locstream_16(domask=False): :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 1: + if esmpy.pet_count() != 1: raise ValueError("processor count must be 1 to use this function") - locstream = ESMF.LocStream(16) + locstream = esmpy.LocStream(16) locstream["ESMF:X"] = [0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0] locstream["ESMF:Y"] = [0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 4.0, 4.0, 4.0, 4.0] @@ -39,30 +39,30 @@ def create_locstream_16_parallel(domask=False): :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 4: + if esmpy.pet_count() != 4: raise ValueError("processor count must be 4 to use this function") locstream = None - if ESMF.local_pet() == 0: - locstream = ESMF.LocStream(4) + if esmpy.local_pet() == 0: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [0.0, 1.5, 0.0, 1.5] locstream["ESMF:Y"] = [0.0, 0.0, 1.5, 1.5] if domask: locstream["ESMF:Mask"] = [1, 0, 0, 1] - elif ESMF.local_pet() == 1: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 1: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [2.5, 4.0, 2.5, 4.0] locstream["ESMF:Y"] = [0.0, 0.0, 1.5, 1.5] if domask: locstream["ESMF:Mask"] = [1, 1, 1, 1] - elif ESMF.local_pet() == 2: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 2: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [0.0, 1.5, 0.0, 1.5] locstream["ESMF:Y"] = [2.5, 2.5, 4.0, 4.0] if domask: locstream["ESMF:Mask"] = [1, 1, 1, 1] - elif ESMF.local_pet() == 3: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 3: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [2.5, 4.0, 2.5, 4.0] locstream["ESMF:Y"] = [2.5, 2.5, 4.0, 4.0] if domask: @@ -70,19 +70,19 @@ def create_locstream_16_parallel(domask=False): return locstream -def create_locstream_spherical_16(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False): +def create_locstream_spherical_16(coord_sys=esmpy.CoordSys.SPH_DEG, domask=False): """ :param coord_sys: the coordinate system of the LocStream :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 1: + if esmpy.pet_count() != 1: raise ValueError("processor count must be 1 to use this function") - locstream = ESMF.LocStream(16, coord_sys=coord_sys) + locstream = esmpy.LocStream(16, coord_sys=coord_sys) deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180 locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad] @@ -92,40 +92,40 @@ def create_locstream_spherical_16(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False) return locstream -def create_locstream_spherical_16_parallel(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False): +def create_locstream_spherical_16_parallel(coord_sys=esmpy.CoordSys.SPH_DEG, domask=False): """ :param coord_sys: the coordinate system of the LocStream :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 4: + if esmpy.pet_count() != 4: raise ValueError("processor count must be 4 to use this function") deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180.0 locstream = None - if ESMF.local_pet() == 0: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + if esmpy.local_pet() == 0: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 0.0, 0.5*deg_rad] locstream["ESMF:Lat"] = [deg_rad/-2.0, deg_rad/-2.0, -0.25*deg_rad, -0.25*deg_rad] if domask: locstream["ESMF:Mask"] = np.array([1, 0, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 1: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 1: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [1.5*deg_rad, 2*deg_rad, 1.5*deg_rad, 2*deg_rad] locstream["ESMF:Lat"] = [deg_rad/-2.0, deg_rad/-2.0, -0.25*deg_rad, -0.25*deg_rad] if domask: locstream["ESMF:Mask"] = np.array([0, 1, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 2: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 2: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 0.0, 0.5*deg_rad] locstream["ESMF:Lat"] = [0.25*deg_rad, 0.25*deg_rad, deg_rad/2.0, deg_rad/2.0] if domask: locstream["ESMF:Mask"] = np.array([1, 1, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 3: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 3: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [1.5*deg_rad, 2*deg_rad, 1.5*deg_rad, 2*deg_rad] locstream["ESMF:Lat"] = [0.25*deg_rad, 0.25*deg_rad, deg_rad/2.0, deg_rad/2.0] if domask: diff --git a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py b/src/addon/ESMPy/src/esmpy/util/mesh_utilities.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/util/mesh_utilities.py rename to src/addon/ESMPy/src/esmpy/util/mesh_utilities.py index 40b2cc030d..76ab3e664d 100644 --- a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/mesh_utilities.py @@ -10,7 +10,7 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') @@ -19,7 +19,7 @@ def mesh_create_5_pentahexa(coord_sys=None): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -43,9 +43,9 @@ def mesh_create_5_pentahexa(coord_sys=None): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) num_node = 12 num_elem = 5 @@ -67,9 +67,9 @@ def mesh_create_5_pentahexa(coord_sys=None): nodeOwner = np.zeros(num_node) elemId = np.array([1,2,3,4,5]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI, 5, 6]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI, 5, 6]) # I believe python connections are 0-based @@ -91,7 +91,7 @@ def mesh_create_5_pentahexa(coord_sys=None): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_4_ngons(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 4 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -113,9 +113,9 @@ def mesh_create_4_ngons(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 4 @@ -149,7 +149,7 @@ def mesh_create_4_ngons(): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -170,9 +170,9 @@ def mesh_create_5(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 5 @@ -189,11 +189,11 @@ def mesh_create_5(): nodeOwner = np.zeros(num_node) elemId = np.array([11,12,21,22,23]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,1,4,3, # element 11 1,2,5,4, # element 12 3,4,7,6, # element 21 @@ -212,7 +212,7 @@ def mesh_create_5(): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_10(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 10 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -237,9 +237,9 @@ def mesh_create_10(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 16 num_elem = 10 @@ -250,16 +250,16 @@ def mesh_create_10(): 0.0,4.0, 1.5,4.0, 2.5,4.0, 4.0,4.0]) nodeOwner = np.zeros(num_node) elemId = np.array([11,12,13,21,22,23,31,32,33,34]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn = np.array([0,1,5,4, 1,2,6,5, 2,3,7,6, @@ -281,7 +281,7 @@ def mesh_create_10(): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_50(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -322,9 +322,9 @@ def mesh_create_50(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 64 num_elem = 50 @@ -352,8 +352,8 @@ def mesh_create_50(domask=False, doarea=False): 51,52,53,54,55,56,57, 61,62,63,64,65,66,67, 71,72,73,74,75,76,77,78]) - elemType = np.ones(num_elem-2)*ESMF.MeshElemType.QUAD - elemType = np.append(elemType, [ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType = np.ones(num_elem-2)*esmpy.MeshElemType.QUAD + elemType = np.append(elemType, [esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23,14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 21,22,32,31,22,23,33,32,23,24,34,33,24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 31,32,42,41,32,33,43,42,33,34,44,43,34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47, @@ -397,7 +397,7 @@ def mesh_create_50(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_50_ngons(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -443,10 +443,10 @@ def mesh_create_50_ngons(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 65 num_elem = 50 @@ -474,11 +474,11 @@ def mesh_create_50_ngons(domask=False, doarea=False): 51,52,53,54,55,56,57, 61,62,63,64,65,66,67,68, 71,72,73,74,75,76,77]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemType[35] = 5 - elemType[36] = ESMF.MeshElemType.TRI + elemType[36] = esmpy.MeshElemType.TRI elemType[37] = 5 - elemType[38] = ESMF.MeshElemType.TRI + elemType[38] = esmpy.MeshElemType.TRI elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23,14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 21,22,32,31,22,23,33,32,23,24,34,33,24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 31,32,42,41,32,33,43,42,33,34,44,43,34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47, @@ -524,7 +524,7 @@ def mesh_create_50_ngons(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_4_ngons(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 4 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -546,9 +546,9 @@ def mesh_create_4_ngons(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 4 @@ -560,9 +560,9 @@ def mesh_create_4_ngons(domask=False, doarea=False): elemId = np.array([61,62,63,64]) elemType = np.ones(num_elem) elemType[0] = 5 - elemType[1] = ESMF.MeshElemType.TRI + elemType[1] = esmpy.MeshElemType.TRI elemType[2] = 5 - elemType[3] = ESMF.MeshElemType.TRI + elemType[3] = esmpy.MeshElemType.TRI elemConn = np.array([61, 62, 69, 72, 71, 62, 63, 69, 63, 64, 74, 73, 69, 69, 73, 72]) elemConn = np.array([np.where(a==nodeId) for a in elemConn]).flatten() elemMask = None @@ -592,7 +592,7 @@ def mesh_create_4_ngons(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -620,15 +620,15 @@ def mesh_create_5_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=4 num_elem=1 @@ -639,10 +639,10 @@ def mesh_create_5_parallel (): 2.0,2.0 ]) nodeOwner=np.zeros(num_node) elemId=np.array([11]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=4 num_elem=1 @@ -656,10 +656,10 @@ def mesh_create_5_parallel (): 0, 1]) elemId=np.array([12]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=4 num_elem=1 @@ -673,10 +673,10 @@ def mesh_create_5_parallel (): 2, 2]) elemId=np.array([21]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=4 num_elem=2 @@ -690,8 +690,8 @@ def mesh_create_5_parallel (): 2, 3]) elemId=np.array([22,23]) - elemType=np.array([ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,3,2, 0,1,3]) @@ -702,7 +702,7 @@ def mesh_create_5_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5_pentahexa_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -733,16 +733,16 @@ def mesh_create_5_pentahexa_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' + """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=4 num_elem=1 @@ -753,10 +753,10 @@ def mesh_create_5_pentahexa_parallel (): 1.0, 1.0 ]) nodeOwner=np.zeros(num_node) elemId=np.array([1]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0, 1, 3, 2 ]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=4 num_elem=2 @@ -770,11 +770,11 @@ def mesh_create_5_pentahexa_parallel (): 0, 1]) elemId=np.array([2, 3]) - elemType=np.array([ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn=np.array([0, 1, 2, 1, 3, 2]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=5 num_elem=1 @@ -793,7 +793,7 @@ def mesh_create_5_pentahexa_parallel (): elemType=np.array([5]) elemConn=np.array([0, 1, 4, 3, 2]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=6 num_elem=1 @@ -821,7 +821,7 @@ def mesh_create_5_pentahexa_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_10_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 10 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -855,15 +855,15 @@ def mesh_create_10_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + """ + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=9 num_elem=4 @@ -879,16 +879,16 @@ def mesh_create_10_parallel (): 2.5,2.5]) nodeOwner=np.zeros(num_node) elemId=np.array([11,12,21,22]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,4,3, 1,2,5,4, 3,4,7,6, 4,5,8,7]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=6 num_elem=2 @@ -901,12 +901,12 @@ def mesh_create_10_parallel (): 4.0,2.5 ]) nodeOwner=np.array([0,1,0,1,0,1]) elemId=np.array([13,23]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2, 2,3,5,4]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=6 num_elem=2 @@ -919,12 +919,12 @@ def mesh_create_10_parallel (): 2.5,4.0 ]) nodeOwner=np.array([0,0,0,2,2,2]) elemId=np.array([31,32]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,4,3, 1,2,5,4]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=4 num_elem=2 @@ -935,8 +935,8 @@ def mesh_create_10_parallel (): 4.0,4.0 ]) nodeOwner=np.array([0,1,2,3]) elemId=np.array([33,34]) - elemType=np.array([ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,3,2, 0,1,3]) @@ -947,7 +947,7 @@ def mesh_create_10_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_50_parallel(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -993,15 +993,15 @@ def mesh_create_50_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers - ''' - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + """ + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: num_node = 16 num_elem = 9 nodeId = np.array([11,12,13,14, @@ -1016,7 +1016,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): elemId = np.array([11,12,13, 21,22,23, 31,32,33]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23, 21,22,32,31,22,23,33,32,23,24,34,33, 31,32,42,41,32,33,43,42,33,34,44,43]) @@ -1029,7 +1029,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 1: + elif esmpy.local_pet() == 1: num_node = 20 num_elem = 12 nodeId = np.array([14,15,16,17,18, @@ -1044,7 +1044,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): elemId = np.array([14,15,16,17, 24,25,26,27, 34,35,36,37]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47]) @@ -1056,7 +1056,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 2: + elif esmpy.local_pet() == 2: num_node = 20 num_elem = 12 nodeId = np.array([41,42,43,44, @@ -1074,7 +1074,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): 51,52,53, 61,62,63, 71,72,73]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([41,42,52,51,42,43,53,52,43,44,54,53, 51,52,62,61,52,53,63,62,53,54,64,63, 61,62,72,71,62,63,73,72,63,64,74,73, @@ -1087,7 +1087,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 3: + elif esmpy.local_pet() == 3: num_node = 25 num_elem = 17 nodeId = np.array([44,45,46,47,48, @@ -1105,8 +1105,8 @@ def mesh_create_50_parallel(domask=False, doarea=False): 54,55,56,57, 64,65,66,67, 74,75,76,77,78]) - elemType = np.ones(num_elem-2)*ESMF.MeshElemType.QUAD - elemType = np.append(elemType, [ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType = np.ones(num_elem-2)*esmpy.MeshElemType.QUAD + elemType = np.append(elemType, [esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn = np.array([44,45,55,54,45,46,56,55,46,47,57,56,47,48,58,57, 54,55,65,64,55,56,66,65,56,57,67,66,57,58,68,67, 64,65,75,74,65,66,76,75,66,67,77,76,67,68,78,77, @@ -1137,7 +1137,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_50_ngons_parallel(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -1188,15 +1188,15 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers - ''' - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + """ + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: num_node = 16 num_elem = 9 nodeId = np.array([11,12,13,14, @@ -1211,7 +1211,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemId = np.array([11,12,13, 21,22,23, 31,32,33]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23, 21,22,32,31,22,23,33,32,23,24,34,33, 31,32,42,41,32,33,43,42,33,34,44,43]) @@ -1224,7 +1224,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 1: + elif esmpy.local_pet() == 1: num_node = 20 num_elem = 12 nodeId = np.array([14,15,16,17,18, @@ -1239,7 +1239,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemId = np.array([14,15,16,17, 24,25,26,27, 34,35,36,37]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47]) @@ -1251,7 +1251,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 2: + elif esmpy.local_pet() == 2: num_node = 21 num_elem = 13 nodeId = np.array([41,42,43,44, @@ -1269,11 +1269,11 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): 51,52,53, 61,62,63,68, 71,72,73]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemType[6] = 5 - elemType[7] = ESMF.MeshElemType.TRI + elemType[7] = esmpy.MeshElemType.TRI elemType[8] = 5 - elemType[9] = ESMF.MeshElemType.TRI + elemType[9] = esmpy.MeshElemType.TRI elemConn = np.array([41,42,52,51,42,43,53,52,43,44,54,53, 51,52,62,61,52,53,63,62,53,54,64,63, 61,62,69,72,71,62,63,69,63,64,74,73,69,69,73,72, @@ -1290,7 +1290,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemArea[8] = 6.25 elemArea[9] = 1.25 - elif ESMF.local_pet() == 3: + elif esmpy.local_pet() == 3: num_node = 25 num_elem = 16 nodeId = np.array([44,45,46,47,48, @@ -1308,7 +1308,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): 54,55,56,57, 64,65,66,67, 74,75,76,77]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([44,45,55,54,45,46,56,55,46,47,57,56,47,48,58,57, 54,55,65,64,55,56,66,65,56,57,67,66,57,58,68,67, 64,65,75,74,65,66,76,75,66,67,77,76,67,68,78,77, @@ -1337,19 +1337,19 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, domask=False, elemMask=None): - ''' + """ PRECONDITIONS: A Field has been created on the elements of a Mesh. POSTCONDITIONS: The Field has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ [node, element] = [0,1] if field.staggerloc == element: offset = 0 for i in range(field.grid.size_owned[element]): - if (elemType[i] == ESMF.MeshElemType.TRI): + if (elemType[i] == esmpy.MeshElemType.TRI): x1 = nodeCoord[(elemConn[offset])*2] x2 = nodeCoord[(elemConn[offset+1])*2] x3 = nodeCoord[(elemConn[offset+2])*2] @@ -1359,7 +1359,7 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, x = (x1 + x2 + x3) / 3.0 y = (y1 + y2 + y3) / 3.0 offset = offset + 3 - elif (elemType[i] == ESMF.MeshElemType.QUAD): + elif (elemType[i] == esmpy.MeshElemType.QUAD): x1 = nodeCoord[(elemConn[offset])*2] x2 = nodeCoord[(elemConn[offset+1])*2] y1 = nodeCoord[(elemConn[offset+1])*2+1] @@ -1385,7 +1385,7 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, x = nodeCoord[i*2] y = nodeCoord[i*2+1] - if (nodeOwner[i] == ESMF.local_pet()): + if (nodeOwner[i] == esmpy.local_pet()): if ind > field.grid.size_owned[node]: raise ValueError("Overstepped the mesh bounds!") field.data[ind] = 20.0 + x**2 +x*y + y**2 @@ -1404,18 +1404,18 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, def compute_mass_mesh(valuefield, dofrac=False, fracfield=None, uninitval=422397696.): - ''' + """ PRECONDITIONS: 'fracfield' contains the fractions of each cell which contributed to a regridding operation involving 'valuefield. 'dofrac' is a boolean value that gives the option to not use the 'fracfield'.\n POSTCONDITIONS: The mass of the data field is computed.\n RETURN VALUES: float :: mass \n - ''' + """ mass = 0.0 # mesh area field must be built on elements - areafield = ESMF.Field(valuefield.grid, name='areafield', - meshloc=ESMF.MeshLoc.ELEMENT) + areafield = esmpy.Field(valuefield.grid, name='areafield', + meshloc=esmpy.MeshLoc.ELEMENT) areafield.get_area() ind = np.where(valuefield.data != uninitval) diff --git a/src/addon/ESMPy/src/ESMF/util/slicing.py b/src/addon/ESMPy/src/esmpy/util/slicing.py similarity index 85% rename from src/addon/ESMPy/src/ESMF/util/slicing.py rename to src/addon/ESMPy/src/esmpy/util/slicing.py index 1f53467948..0bb83864f3 100644 --- a/src/addon/ESMPy/src/ESMF/util/slicing.py +++ b/src/addon/ESMPy/src/esmpy/util/slicing.py @@ -3,7 +3,7 @@ """ import numpy as np -import ESMF +import esmpy #### HELPERS ######################################################### @@ -65,15 +65,15 @@ def get_none_or_ssslice(target, slc, stagger, rank): slc2 = None if rank == 2: assert(len(slc) == 2) - if stagger == ESMF.StaggerLoc.CENTER: + if stagger == esmpy.StaggerLoc.CENTER: slc2 = slc - elif stagger == ESMF.StaggerLoc.EDGE1: + elif stagger == esmpy.StaggerLoc.EDGE1: #slc[0] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1]) - elif stagger == ESMF.StaggerLoc.EDGE2: + elif stagger == esmpy.StaggerLoc.EDGE2: #slc[1] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step)) - elif stagger == ESMF.StaggerLoc.CORNER: + elif stagger == esmpy.StaggerLoc.CORNER: #slc[0] + 1 #slc[1] + 1 slc2 = ([slice(slc[i].start, slc[i].stop + 1, slc[i].step) for i in range(len(slc))]) @@ -82,30 +82,30 @@ def get_none_or_ssslice(target, slc, stagger, rank): elif rank == 3: assert (len(slc) == 3) - if stagger == ESMF.StaggerLoc.CENTER_VCENTER: + if stagger == esmpy.StaggerLoc.CENTER_VCENTER: slc2 = slc - elif stagger == ESMF.StaggerLoc.EDGE1_VCENTER: + elif stagger == esmpy.StaggerLoc.EDGE1_VCENTER: #slc[0] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1], slc[2]) - elif stagger == ESMF.StaggerLoc.EDGE2_VCENTER: + elif stagger == esmpy.StaggerLoc.EDGE2_VCENTER: #slc[1] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step), slc[2]) - elif stagger == ESMF.StaggerLoc.CORNER_VCENTER: + elif stagger == esmpy.StaggerLoc.CORNER_VCENTER: #slc[0] + 1 #slc[1] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slice(slc[1].start, slc[1].stop + 1, slc[1].step), slc[2]) - elif stagger == ESMF.StaggerLoc.CENTER_VFACE: + elif stagger == esmpy.StaggerLoc.CENTER_VFACE: #slc[2] + 1 slc2 = (slc[0], slc[1], slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.EDGE1_VFACE: + elif stagger == esmpy.StaggerLoc.EDGE1_VFACE: #slc[0] + 1 #slc[2] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1], slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.EDGE2_VFACE: + elif stagger == esmpy.StaggerLoc.EDGE2_VFACE: #slc[1] + 1 #slc[2] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step), slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.CORNER_VFACE: + elif stagger == esmpy.StaggerLoc.CORNER_VFACE: #slc[0] + 1 #slc[1] + 1 #slc[2] + 1