def build_analyticfieldgrid(field, grid): ''' PRECONDITIONS: An ESMP_Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. ''' # get the field pointer first fieldPtr = ESMP.ESMP_FieldGetPtr(field) # get the grid bounds and coordinate pointers exLB, exUB = ESMP.ESMP_GridGetCoord(grid, ESMP.ESMP_STAGGERLOC_CENTER) # get the coordinate pointers and set the coordinates [x,y] = [0, 1] gridXCoord = ESMP.ESMP_GridGetCoordPtr(grid, x, ESMP.ESMP_STAGGERLOC_CENTER) gridYCoord = ESMP.ESMP_GridGetCoordPtr(grid, y, ESMP.ESMP_STAGGERLOC_CENTER) #print "Grid center coordinates" p = 0 for i1 in range(exLB[1], exUB[1]): for i0 in range(exLB[0], exUB[0]): xc = gridXCoord[p] yc = gridYCoord[p] fieldPtr[p] = 20.0+xc+yc #fieldPtr[p] = 20.0+xc*yc+yc**2 #print '[{0},{1}] = {2}'.format(xc,yc,fieldPtr[p]) p = p + 1 #print "\n" return field
def esmfGrid(grid, cds, sloc): """ @param grid ESMF grid @param cds list of coordinates @param sloc ESMP staggerlocation """ # Destination Centers ESMP.ESMP_GridAddCoord(grid, staggerloc = sloc) lo, hi = ESMP.ESMP_GridGetCoord(grid, staggerloc = sloc) ndims = len(lo) # Dimensions for local processor Ntot = reduce(operator.mul, [hi[i] - lo[i] for i in range(ndims)]) ijkBE = [] shape = [] for i in range(ndims): ind = (ndims-1)-i ijkBE.append(slice(lo[ind], hi[ind], None)) shape.append(hi[ind] - lo[ind]) print ijkBE xyzPtr = [] for i in range(ndims): xyzPtr.append(ESMP.ESMP_GridGetCoordPtr(grid, i, staggerloc = sloc)) xyzPtr[i][:] = cds[i][ijkBE].flat shape = tuple(shape) return xyzPtr, ijkBE, shape
def compare_fields(field1, field2): ''' PRECONDITIONS: Two ESMP_Fields have been created and a comparison of the the values is desired between 'srcfield' and 'dstfield'. POSTCONDITIONS: The values on 'srcfield' and 'dstfield' are compared. returns True if the fileds are comparable (success) ''' # get the data pointers for the fields field1ptr = ESMP.ESMP_FieldGetPtr(field1) field2ptr = ESMP.ESMP_FieldGetPtr(field2) # compare point values of field1 to field2 # first verify they are the same size if (field1.size != field2.size): raise NameError('compare_fields: Fields must be the same size!') # initialize to True, and check for False point values correct = True totalErr = 0.0 for i in range(field1.size): err = abs(field1ptr[i] - field2ptr[i])/abs(field2ptr[i]) if err > .06: correct = False print "ACCURACY ERROR - "+str(err) print "field1 = {0} : field2 = {1}\n".format(field1ptr[i], field2ptr[i]) totalErr += err if correct: print " - PASS - Total Error = "+str(totalErr) return True else: print " - FAIL - Total Error = "+str(totalErr) return False
def test1(self): comm = MPI.COMM_WORLD pe1 = comm.Get_rank() nprocs1 = comm.Get_size() vm = ESMP.ESMP_VMGetGlobal() pe2, nprocs2 = ESMP.ESMP_VMGet(vm) self.assertEqual(pe1, pe2) self.assertEqual(nprocs1, nprocs2)
def __init__(self, maxIndex): self.grid = ESMP.ESMP_GridCreateNoPeriDim(maxIndex, coordSys=COORDSYS) ESMP.ESMP_GridAddCoord(self.grid, staggerloc=CENTER) self.field = ESMP.ESMP_FieldCreateGrid(self.grid, 'srcFeld1', staggerloc=CENTER, typekind=R4)
def setCellAreas(self, areas): """ Set the cell areas @param areas numpy array """ ESMP.ESMP_GridAddItem(self.grid, item=ESMP.ESMP_GRIDITEM_AREA) areaPtr = ESMP.ESMP_GridGetItem(self.grid, item=ESMP.ESMP_GRIDITEM_AREA) areaPtr[:] = areas.flat self.cellAreasSet = True
def setMask(self, mask): """ Set mask array. In ESMF, the mask is applied to cells. @param mask numpy array. 1 is invalid by default. This array exists on all procs """ ESMP.ESMP_GridAddItem(self.grid, item=ESMP.ESMP_GRIDITEM_MASK) maskPtr = ESMP.ESMP_GridGetItem(self.grid, item=ESMP.ESMP_GRIDITEM_MASK) slab = self.getLocalSlab(CENTER) maskPtr[:] = mask[slab].flat
def run_regridding(srcfield, dstfield): ''' PRECONDITIONS: Two ESMP_Fields have been created and a regridding operation is desired from 'srcfield' to 'dstfield'. POSTCONDITIONS: An ESMP regridding operation has set the data on 'dstfield'. ''' # call the regridding functions routehandle = ESMP.ESMP_FieldRegridStore(srcfield, dstfield, regridmethod=ESMP.ESMP_REGRIDMETHOD_CONSERVE, unmappedaction=ESMP.ESMP_UNMAPPEDACTION_ERROR) ESMP.ESMP_FieldRegrid(srcfield, dstfield, routehandle) ESMP.ESMP_FieldRegridRelease(routehandle) return dstfield
def __init__(self, esmfGrid, name, datatype, staggerloc = CENTER): """ Creator for structured ESMF Field @param esmfGrid instance of an ESMP_Grid @param name field name (must be unique) @param datatype data type, one of 'float64', 'float32', 'int64', or 'int32' (or equivalent numpy dtype) @param staggerloc ESMP_STAGGERLOC_CENTER ESMP_STAGGERLOC_CORNER """ # field object self.field = None # the local processor rank self.pe = 0 # the number of processors self.nprocs = 1 # associated grid self.grid = esmfGrid # staggering self.staggerloc = staggerloc # communicator self.comm = None try: from mpi4py import MPI self.comm = MPI.COMM_WORLD except: pass vm = ESMP.ESMP_VMGetGlobal() self.pe, self.nprocs = ESMP.ESMP_VMGet(vm) etype = None sdatatype = str(datatype) # in case user passes a numpy dtype if re.search('float64', sdatatype): etype = R8 elif re.search('float32', sdatatype): etype = R4 elif re.search('int64', sdatatype): etype = I8 elif re.search('int32', sdatatype): etype = I4 else: msg = 'esmf.EsmfStructField.__init__: ERROR invalid type %s' % datatype raise RegridError, msg self.field = ESMP.ESMP_FieldCreateGrid(esmfGrid.grid, name, staggerloc = staggerloc, typekind = etype)
def build_analyticfield(field, nodeCoord, elemType, elemConn): ''' PRECONDITIONS: An ESMP_Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. ''' # get the field pointer first fieldPtr = ESMP.ESMP_FieldGetPtr(field, 0) # set the field to a vanilla initial field for now #print "Mesh center coordinates" offset = 0 for i in range(field.size): # this routine assumes this field is on elements if (elemType[i] == ESMP.ESMP_MESHELEMTYPE_TRI): raise NameError("Cannot compute a non-constant analytic field for a mesh\ with triangular elements!") x1 = nodeCoord[(elemConn[offset])*2] x2 = nodeCoord[(elemConn[offset+1])*2] y1 = nodeCoord[(elemConn[offset+1])*2+1] y2 = nodeCoord[(elemConn[offset+3])*2+1] x = (x1+x2)/2.0 y = (y1+y2)/2.0 fieldPtr[i] = 20.0+x+y #fieldPtr[i] = 20.0+x*y+y**2 #print '[{0},{1}] = {2}'.format(x,y,fieldPtr[i]) offset = offset + 4 #print "\n" return field
def test_test1(self): f1 = Foo() grid = ESMP.ESMP_GridCreateNoPeriDim( numpy.array([3, 4], dtype=numpy.int32)) f2 = Foo() del f1 f1 = Foo()
def setCoords(self, coords, staggerloc = CENTER, globalIndexing = False): """ Populate the grid with staggered coordinates (e.g. corner or center). @param coords The curvilinear coordinates of the grid. List of numpy arrays. Must exist on all procs. @param staggerloc The stagger location ESMP.ESMP_STAGGERLOC_CENTER (default) ESMP.ESMP_STAGGERLOC_CORNER @param globalIndexing if True array was allocated over global index space, otherwise array was allocated over local index space on this processor. This is only relevant if rootPe is None Note: coord dims in cdms2 are ordered in y, x, but ESMF expects x, y, hence the dimensions are reversed here. """ # allocate space for coordinates, can only add coordinates once for i in range(self.ndims): ptr = ESMP.ESMP_GridGetCoordPtr(self.grid, i, staggerloc) if globalIndexing: slab = self.getLocalSlab(staggerloc) # Populate self.grid with coordinates or the bounds as needed ptr[:] = coords[self.ndims-i-1][slab].flat else: ptr[:] = coords[self.ndims-i-1].flat
def startCheckESMP(self): ''' Calls ESMP.ESMP_Initialize and registers stopESMP with atexit when called the first time. Subsequent calls only return whether or not ESMP is initialized. Registering stopESMP with atexit ensures the ESMP.ESMP_Finalize will always be called prior to exiting Python. Arguments: None Returns: True - if ESMP_Initialize has been called, either as a result of this call or from a previous call False - if stopESMP has called ESMP_Finalize ''' # Return False if attempting to re-initialize if self.__esmp_finalized: return False # Call ESMP_Initialize if not already done previously if not self.__esmp_initialized: ESMP.ESMP_Initialize() atexit.register(self.stopESMP) self.__esmp_initialized = True # Return True if ESMP_Intialize had already or has now been called return True
def stopESMP(self, delete_log=False): ''' Calls ESMP.ESMP_Finalize if ESMP had been initialized using startCheckESMP. This function is registered with atexit by startCheckESMP when it calls ESMP.ESMP_Initialize to ensure ESMP.ESMP_Finalize is always called before exiting Python. However, this function can be called directly (presumably to delete the log file) before exiting without causing problems. Arguments: delete_log: if True, the ESMF log file 'PET0.ESMF_LogFile' will be deleted after ESMP.ESMP_Finalize is called. Any failure to delete the log file is silently ignored. Returns: None ''' # If ESMP not initialize, or already finalized, just return if not self.__esmp_initialized: return if self.__esmp_finalized: return # Call ESMP_Finalize and set flags indicating this has been done ESMP.ESMP_Finalize() self.__esmp_initialized = False self.__esmp_finalized = True # Optionally delete the ESMF log file if delete_log: try: os.remove('PET0.ESMF_LogFile') except Exception: pass
def getCoords(self, dim, staggerloc): """ Return the coordinates for a dimension @param dim desired dimension (zero based indexing) @param staggerloc Stagger location """ gridPtr = ESMP.ESMP_GridGetCoordPtr(self.grid, dim, staggerloc) shp = self.getCoordShape(staggerloc) return numpy.reshape(gridPtr, shp)
def setData(self, data, slab): """ @param data numpy array @param slab tuple of slices """ fieldPtr = ESMP.ESMP_FieldGetPtr(self.field) fieldPtr[:] = data[slab].flat return fieldPtr
def create_ESMPfield(mesh, name): ''' PRECONDITIONS: An ESMP_Mesh has been created, and 'name' is a string that will be used to initialize the name of a new ESMP_Field. POSTCONDITIONS: An ESMP_Field has been created. ''' field = ESMP.ESMP_FieldCreate(mesh, name, meshloc=ESMP.ESMP_MESHLOC_ELEMENT) return field
def getLoHiBounds(self, staggerloc): """ Get the local lo/hi index values for the coordinates (per processor) (hi is not inclusive, lo <= index < hi) @param staggerloc e.g. ESMP.ESMP_STAGGERLOC_CENTER @return lo, hi lists """ lo, hi = ESMP.ESMP_GridGetCoord(self.grid, staggerloc) # reverse order since ESMF follows fortran order return lo[::-1], hi[::-1]
def getCellAreas(self): """ @return cell areas or None if setCellAreas was not called """ if self.cellAreasSet: areaPtr = ESMP.ESMP_GridGetItem(self.grid, item = ESMP.ESMP_GRIDITEM_AREA) return numpy.reshape(areaPtr, self.shape) else: return None
def create_ESMPfieldgrid(grid, name): ''' PRECONDITIONS: An ESMP_Grid has been created, and 'name' is a string that will be used to initialize the name of a new ESMP_Field. POSTCONDITIONS: An ESMP_Field has been created. ''' # defaults to center staggerloc field = ESMP.ESMP_FieldCreateGrid(grid, name) return field
def getDstAreas(self, rootPe): """ Get the dst grid areas as used by conservative interpolation @param rootPe None is local areas are returned, otherwise provide rootPe and the data will be gathered @return numpy array or None if interpolation is not conservative """ if self.srcAreaField is not None: ESMP.ESMP_FieldRegridGetArea(self.dstAreaField.field) return self.dstAreaField.getData(rootPe = rootPe) return None
def create_ESMPmesh_3x3(): ''' PRECONDITIONS: ESMP is initialized. POSTCONDITIONS: An ESMP_Mesh (3x3) has been created and returned as 'mesh'. ''' # Two parametric dimensions, and three spatial dimensions mesh = ESMP.ESMP_MeshCreate(2,2) mesh, nodeCoord, elemType, elemConn = mesh_create_3x3(mesh) return mesh, nodeCoord, elemType, elemConn
def test_test1(self): # create two unique ESMP_Mesh objects grid = grid_create() mesh, nodeCoord, elemType, elemConn = create_ESMPmesh_3x3() ''' # this is for grid to mesh # create ESMP_Field objects on the Meshes srcfield = create_ESMPfieldgrid(grid, 'srcfield') dstfield = create_ESMPfield(mesh, 'dstfield') dstfield2 = create_ESMPfield(mesh, 'dstfield_exact') # initialize the Fields to an analytic function srcfield = build_analyticfieldgrid(srcfield, grid) dstfield2 = build_analyticfield(dstfield2, nodeCoord, elemType, elemConn) ''' # this is for mesh to grid # create ESMP_Field objects on the Meshes srcfield = create_ESMPfield(mesh, 'srcfield') dstfield = create_ESMPfieldgrid(grid, 'dstfield') dstfield2 = create_ESMPfieldgrid(grid, 'dstfield_exact') # initialize the Fields to an analytic function srcfield = build_analyticfield(srcfield, nodeCoord, elemType, elemConn) dstfield2 = build_analyticfieldgrid(dstfield2, grid) # run the ESMF regridding dstfield = run_regridding(srcfield, dstfield) # compare results and output PASS or FAIL ok = compare_fields(dstfield, dstfield2) # clean up ESMP.ESMP_FieldDestroy(srcfield) ESMP.ESMP_FieldDestroy(dstfield) ESMP.ESMP_FieldDestroy(dstfield2) ESMP.ESMP_GridDestroy(grid) ESMP.ESMP_MeshDestroy(mesh) self.assertEqual(ok, True)
def __init__(self, numTopoDims, numSpaceDims): """ Constructor @param numTopoDims number of topological dimensions @param numSpaceDims number of space dimensions """ # handle to the grid object self.grid = None # whether or not nodes were added self.nodesAdded = False # whether or not cells were added self.cellsAdded = False # the local processor rank self.pe = 0 # number of processors self.nprocs = 1 # communicator self.comm = None vm = ESMP.ESMP_VMGetGlobal() self.pe, self.nprocs = ESMP.ESMP_VMGet(vm) self.grid = ESMP.ESMP_MeshCreate(numTopoDims, numSpaceDims)
def setNodes(self, indices, coords, peOwners=None): """ Set the nodal coordinates @param indices Ids of the nodes (0-based) @param coords nodal coordinates @param peOwners processor ranks where the coordinates reside (0-based) """ n = len(indices) if not self.nodesAdded: if peOwners is None: peOwners = numpy.ones((n,), numpy.int32) * self.pe # node indices are 1-based indices += 1 ESMP.ESMP_MeshAddNodes(self.grid, n, indices, coords, peOwners) self.nodesAdded = True
def setCells(self, cellIndices, cellTypes, connectivity, cellMask=None, cellAreas=None): """ Set Cell connectivity @param cell indices (0-based) @param cellTypes one of ESMP_MESHELEMTYPE_{TRI,QUAD,TETRA,HEX} @param connectivity node connectivity array, see below for node ordering @param cellMask @param cellAreas area (volume) of each cell 3 4 ---------- 3 / \ | | / \ | | / \ | | / \ | | / \ | | 1 --------- 2 1 ---------- 2 3 8---------------7 /|\ /| /| / | \ / | / | / | \ / | / | / | \ / | / | / | \ 5---------------6 | 4-----|-----2 | | | | \ | / | 4----------|----3 \ | / | / | / \ | / | / | / \ | / | / | / \|/ |/ |/ 1 1---------------2 ESMP_MESHELEMTYPE_TETRA ESMP_MESHELEMTYPE_HEX """ n = len(cellIndices) if not self.cellsAdded: # node/cell indices are 1-based in ESMP cellIndices += 1 ESMP.ESMP_MeshAddElements(self.grid, n, cellIndices, cellTypes, connectivity, elementMask=cellMask, elementArea=cellAreas) self.cellsAdded = True
def __call__(self, srcField=None, dstField=None): """ Apply interpolation weights @param srcField source field (or None if src field passed to constructor is to be used) @param dstField destination field (or None if dst field passed to constructor is to be used) """ if srcField == None: srcField = self.srcField if dstField == None: dstField = self.dstField # default is keep the masked values intact zeroregion = ESMP.ESMP_REGION_SELECT if self.regridMethod == CONSERVE: zeroregion = None # will initalize to zero ESMP.ESMP_FieldRegrid(srcField.field, dstField.field, self.regridHandle, zeroregion = zeroregion)
def XXtest0_ESMP(self): import scipy.io.netcdf srcF = scipy.io.netcdf.netcdf_file( 'so_Omon_ACCESS1-0_historical_r1i1p1_185001-185412_2timesteps.nc') so = srcF.variables['so'][0, 0, ...] missing_value = 1.e20 srcGrd = [srcF.variables['lat'][:], srcF.variables['lon'][:]] srcBounds = _getCorners([ srcF.variables['lat_vertices'][:], srcF.variables['lon_vertices'][:] ]) lat1dBounds = numpy.arange(-90.0, 90.001, 5.0) lon1dBounds = numpy.arange(-180.0, 180.001, 5.0) lat1dCenter = 0.5 * (lat1dBounds[:-1] + lat1dBounds[1:]) lon1dCenter = 0.5 * (lon1dBounds[:-1] + lon1dBounds[1:]) lat2dBounds = numpy.outer( lat1dBounds, numpy.ones((len(lon1dBounds), ), lon1dBounds.dtype)) lon2dBounds = numpy.outer( numpy.ones((len(lat1dBounds), ), lat1dBounds.dtype), lon1dBounds) lat2dCenter = numpy.outer( lat1dCenter, numpy.ones((len(lon1dCenter), ), lon1dCenter.dtype)) lon2dCenter = numpy.outer( numpy.ones((len(lat1dCenter), ), lat1dCenter.dtype), lon1dCenter) dstGrd = [lat2dCenter, lon2dCenter] dstBounds = [lat2dBounds, lon2dBounds] coordSys = ESMP.ESMP_COORDSYS_SPH_DEG # ESMP.ESMP_COORDSYS_CART fails srcDims = srcGrd[0].shape dstDims = dstGrd[0].shape # do we need to revert the order here? srcMaxIndex = numpy.array(srcDims[::-1], numpy.int32) # number of cells dstMaxIndex = numpy.array(dstDims[::-1], numpy.int32) # number of cells # grids srcGrid = ESMP.ESMP_GridCreateNoPeriDim(srcMaxIndex, coordSys=coordSys) dstGrid = ESMP.ESMP_GridCreateNoPeriDim(dstMaxIndex, coordSys=coordSys) # it's a good idea to always add the nodal coordinates ESMP.ESMP_GridAddCoord(srcGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CORNER) ESMP.ESMP_GridAddCoord(srcGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) ESMP.ESMP_GridAddCoord(dstGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CORNER) ESMP.ESMP_GridAddCoord(dstGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) # masks ESMP.ESMP_GridAddItem(srcGrid, item=ESMP.ESMP_GRIDITEM_MASK) srcGridMaskPtr = ESMP.ESMP_GridGetItem(srcGrid, item=ESMP.ESMP_GRIDITEM_MASK) ESMP.ESMP_GridAddItem(dstGrid, item=ESMP.ESMP_GRIDITEM_MASK) dstGridMaskPtr = ESMP.ESMP_GridGetItem(dstGrid, item=ESMP.ESMP_GRIDITEM_MASK) # get pointer to coordinates array and dimensions # src srcXCorner = ESMP.ESMP_GridGetCoordPtr(srcGrid, 0, ESMP.ESMP_STAGGERLOC_CORNER) srcYCorner = ESMP.ESMP_GridGetCoordPtr(srcGrid, 1, ESMP.ESMP_STAGGERLOC_CORNER) srcLoCorner, srcHiCorner = ESMP.ESMP_GridGetCoord( srcGrid, ESMP.ESMP_STAGGERLOC_CORNER) srcXCenter = ESMP.ESMP_GridGetCoordPtr(srcGrid, 0, ESMP.ESMP_STAGGERLOC_CENTER) srcYCenter = ESMP.ESMP_GridGetCoordPtr(srcGrid, 1, ESMP.ESMP_STAGGERLOC_CENTER) srcLoCenter, srcHiCenter = ESMP.ESMP_GridGetCoord( srcGrid, ESMP.ESMP_STAGGERLOC_CENTER) # dst dstXCorner = ESMP.ESMP_GridGetCoordPtr(dstGrid, 0, ESMP.ESMP_STAGGERLOC_CORNER) dstYCorner = ESMP.ESMP_GridGetCoordPtr(dstGrid, 1, ESMP.ESMP_STAGGERLOC_CORNER) dstLoCorner, dstHiCorner = ESMP.ESMP_GridGetCoord( dstGrid, ESMP.ESMP_STAGGERLOC_CORNER) dstXCenter = ESMP.ESMP_GridGetCoordPtr(dstGrid, 0, ESMP.ESMP_STAGGERLOC_CENTER) dstYCenter = ESMP.ESMP_GridGetCoordPtr(dstGrid, 1, ESMP.ESMP_STAGGERLOC_CENTER) dstLoCenter, dstHiCenter = ESMP.ESMP_GridGetCoord( dstGrid, ESMP.ESMP_STAGGERLOC_CENTER) # fields srcFld = ESMP.ESMP_FieldCreateGrid( srcGrid, 'srcFld', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) dstFld = ESMP.ESMP_FieldCreateGrid( dstGrid, 'dstFld', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) srcAreaField = ESMP.ESMP_FieldCreateGrid( srcGrid, 'srcAreas', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) dstAreaField = ESMP.ESMP_FieldCreateGrid( dstGrid, 'dstAreas', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) srcFracField = ESMP.ESMP_FieldCreateGrid( srcGrid, 'srcFracAreas', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) dstFracField = ESMP.ESMP_FieldCreateGrid( dstGrid, 'dstFracAreas', typekind=ESMP.ESMP_TYPEKIND_R8, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) srcFieldPtr = ESMP.ESMP_FieldGetPtr(srcFld) srcFracPtr = ESMP.ESMP_FieldGetPtr(srcFracField) dstFieldPtr = ESMP.ESMP_FieldGetPtr(dstFld) dstFracPtr = ESMP.ESMP_FieldGetPtr(dstFracField) # set the coordinates and field values. In ESMP, arrays are column major! # src-corners srcNx1 = srcHiCorner[0] - srcLoCorner[0] srcNy1 = srcHiCorner[1] - srcLoCorner[1] srcYCorner[:] = srcBounds[0][srcLoCorner[1]:srcHiCorner[1], srcLoCorner[0]:srcHiCorner[0]].flat srcXCorner[:] = srcBounds[1][srcLoCorner[1]:srcHiCorner[1], srcLoCorner[0]:srcHiCorner[0]].flat # src-center coordinates, field, and mask srcNx = srcHiCenter[0] - srcLoCenter[0] srcNy = srcHiCenter[1] - srcLoCenter[1] yc = numpy.array(srcGrd[0][srcLoCenter[1]:srcHiCenter[1], srcLoCenter[0]:srcHiCenter[0]]) xc = numpy.array(srcGrd[1][srcLoCenter[1]:srcHiCenter[1], srcLoCenter[0]:srcHiCenter[0]]) srcYCenter[:] = yc.flat srcXCenter[:] = xc.flat msk = numpy.array(so[srcLoCenter[1]:srcHiCenter[1], srcLoCenter[0]:srcHiCenter[0]] \ == missing_value, numpy.int32) srcGridMaskPtr[:] = msk.flat fld = numpy.array( so[srcLoCenter[1]:srcHiCenter[1], srcLoCenter[0]:srcHiCenter[0]], so.dtype) # set to zero where masked fld *= (1 - msk) srcFieldPtr[:] = fld.flat srcFracPtr[:] = 1.0 # dst-corners dstNx1 = dstHiCorner[0] - dstLoCorner[0] dstNy1 = dstHiCorner[1] - dstLoCorner[1] dstYCorner[:] = dstBounds[0][dstLoCorner[1]:dstHiCorner[1], dstLoCorner[0]:dstHiCorner[0]].flat dstXCorner[:] = dstBounds[1][dstLoCorner[1]:dstHiCorner[1], dstLoCorner[0]:dstHiCorner[0]].flat # dst-center coordinates, field, and mask dstNx = dstHiCenter[0] - dstLoCenter[0] dstNy = dstHiCenter[1] - dstLoCenter[1] yc = numpy.array(dstGrd[0][dstLoCenter[1]:dstHiCenter[1], dstLoCenter[0]:dstHiCenter[0]]) xc = numpy.array(dstGrd[1][dstLoCenter[1]:dstHiCenter[1], dstLoCenter[0]:dstHiCenter[0]]) dstYCenter[:] = yc.flat dstXCenter[:] = xc.flat dstGridMaskPtr[:] = 0 dstFieldPtr[:] = missing_value dstFracPtr[:] = 1.0 # interpolation maskVals = numpy.array([1], numpy.int32) # values defining mask regrid = ESMP.ESMP_FieldRegridStore( srcFld, dstFld, srcMaskValues=maskVals, dstMaskValues=maskVals, regridmethod=ESMP.ESMP_REGRIDMETHOD_CONSERVE, unmappedaction=ESMP.ESMP_UNMAPPEDACTION_IGNORE, srcFracField=srcFracField, dstFracField=dstFracField) ESMP.ESMP_FieldRegrid(srcFld, dstFld, regrid) # get the cell areas ESMP.ESMP_FieldRegridGetArea(srcAreaField) ESMP.ESMP_FieldRegridGetArea(dstAreaField) srcAreasPtr = ESMP.ESMP_FieldGetPtr(srcAreaField) dstAreasPtr = ESMP.ESMP_FieldGetPtr(dstAreaField) srcFracPtr = ESMP.ESMP_FieldGetPtr(srcFracField) dstFracPtr = ESMP.ESMP_FieldGetPtr(dstFracField) # check conservation srcFldSum, dstFldSum = srcFieldPtr.sum(), dstFieldPtr.sum() srcFldIntegral = (srcFieldPtr * srcAreasPtr * srcFracPtr).sum() dstFldIntegral = (dstFieldPtr * dstAreasPtr * dstFracPtr).sum() lackConservLocal = srcFldIntegral - dstFldIntegral # check for nans if numpy.isnan(srcFracPtr).sum() > 0: print '[%d] *** %d Nans found in srcFracPtr!!' % ( self.pe, numpy.isnan().sum(srcFracPtr)) if numpy.isnan(dstFracPtr).sum() > 0: print '[%d] *** %d Nans found in dstFracPtr!!' % ( self.pe, numpy.isnan().sum(dstFracPtr)) print '[%d] checksum of src: %g checksum of dst: %g' % ( self.pe, srcFldSum, dstFldSum) print '[%d] src total area integral: %g dst total area integral: %g diff: %g\n' % \ (self.pe, srcFldIntegral, dstFldIntegral, lackConservLocal) if HAS_MPI: lackConserv = MPI.COMM_WORLD.reduce(lackConservLocal, op=MPI.SUM, root=0) else: lackConserv = lackConservLocal if self.pe == 0: print 'ROOT: total lack of conservation (should be small): %f' % lackConserv # cleanup ESMP.ESMP_FieldRegridRelease(regrid) ESMP.ESMP_FieldDestroy(srcAreaField) ESMP.ESMP_FieldDestroy(dstAreaField) ESMP.ESMP_FieldDestroy(srcFracField) ESMP.ESMP_FieldDestroy(dstFracField) ESMP.ESMP_FieldDestroy(srcFld) ESMP.ESMP_FieldDestroy(dstFld) ESMP.ESMP_GridDestroy(srcGrid) ESMP.ESMP_GridDestroy(dstGrid)
verbose=True, diag=diag) print cltInterp.sum() n = reduce(lambda x, y: x * y, cltInterp.shape) self.assertLess(abs(cltInterp.sum() - 696921.0) / n, 0.3) if PLOT: pylab.pcolor(ta.getLongitude()[:], ta.getLatitude()[:], cltInterp) pylab.colorbar() pylab.title('cltInterp') self.assertEqual(True, True) def test2_mkCyclic(self): import regrid2 y = numpy.array([-90.0 + i * 30.0 for i in range(7)]) x = numpy.array([(i + 0.5) * 60.0 for i in range(6)]) yy = regrid2.gsRegrid.getTensorProduct(y, 0, [len(y), len(x)]) xx = regrid2.gsRegrid.getTensorProduct(x, 1, [len(y), len(x)]) coords = [yy, xx] dims = [len(y), len(x)] newCoords, newDims = regrid2.gsRegrid.makeCoordsCyclic(coords, dims) self.assertEqual(newDims[-1], dims[-1] + 1) if __name__ == '__main__': print "" # Spacer ESMP.ESMP_Initialize() suite = unittest.TestLoader().loadTestsFromTestCase(TestTasRegrid) unittest.TextTestRunner(verbosity=1).run(suite) if PLOT: pylab.show()
def test_2d_esmf_native(self): print 'running test_2d_esmf_native...' f = cdms2.open(sys.prefix + \ '/sample_data/so_Omon_ACCESS1-0_historical_r1i1p1_185001-185412_2timesteps.nc') so = f('so')[0, 0, :, :] clt = cdms2.open(sys.prefix + '/sample_data/clt.nc')('clt')[0, :, :] cltBounds = clt.getGrid().getBounds() tic = time.time() ny, nx = clt.shape yb = numpy.zeros((ny + 1, ), numpy.float32) yb[:ny] = cltBounds[0][:, 0] yb[ny] = cltBounds[0][ny - 1, 1] xb = numpy.zeros((nx + 1, ), numpy.float32) xb[:nx] = cltBounds[1][:, 0] xb[nx] = cltBounds[1][nx - 1, 1] # make curvilinear dstLatCorner = numpy.outer(yb, numpy.ones((nx + 1, ), numpy.float32)) dstLonCorner = numpy.outer(numpy.ones((ny + 1, ), numpy.float32), xb) ny, nx = so.shape soBounds = so.getGrid().getBounds() srcLatCorner = numpy.zeros((ny + 1, nx + 1), numpy.float32) srcLatCorner[:ny, :nx] = soBounds[0][:, :, 0] srcLatCorner[:ny, nx] = soBounds[0][:ny, nx - 1, 1] srcLatCorner[ny, nx] = soBounds[0][ny - 1, nx - 1, 2] srcLatCorner[ny, :nx] = soBounds[0][ny - 1, :nx, 3] srcLonCorner = numpy.zeros((ny + 1, nx + 1), numpy.float32) srcLonCorner[:ny, :nx] = soBounds[1][:, :, 0] srcLonCorner[:ny, nx] = soBounds[1][:ny, nx - 1, 1] srcLonCorner[ny, nx] = soBounds[1][ny - 1, nx - 1, 2] srcLonCorner[ny, :nx] = soBounds[1][ny - 1, :nx, 3] # create grid srcMaxIndex = numpy.array(so.shape[::-1], dtype=numpy.int32) srcGrid = ESMP.ESMP_GridCreateNoPeriDim( srcMaxIndex, coordSys=ESMP.ESMP_COORDSYS_SPH_DEG) ESMP.ESMP_GridAddCoord(srcGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) ESMP.ESMP_GridAddCoord(srcGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CORNER) srcDimsCenter = ESMP.ESMP_GridGetCoord(srcGrid, ESMP.ESMP_STAGGERLOC_CENTER) srcDimsCorner = ESMP.ESMP_GridGetCoord(srcGrid, ESMP.ESMP_STAGGERLOC_CORNER) srcXCenter = ESMP.ESMP_GridGetCoordPtr(srcGrid, 0, ESMP.ESMP_STAGGERLOC_CENTER) srcYCenter = ESMP.ESMP_GridGetCoordPtr(srcGrid, 1, ESMP.ESMP_STAGGERLOC_CENTER) srcXCorner = ESMP.ESMP_GridGetCoordPtr(srcGrid, 0, ESMP.ESMP_STAGGERLOC_CORNER) srcYCorner = ESMP.ESMP_GridGetCoordPtr(srcGrid, 1, ESMP.ESMP_STAGGERLOC_CORNER) dstMaxIndex = numpy.array(clt.shape[::-1], dtype=numpy.int32) dstGrid = ESMP.ESMP_GridCreateNoPeriDim( dstMaxIndex, coordSys=ESMP.ESMP_COORDSYS_SPH_DEG) ESMP.ESMP_GridAddCoord(dstGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) ESMP.ESMP_GridAddCoord(dstGrid, staggerloc=ESMP.ESMP_STAGGERLOC_CORNER) dstDimsCenter = ESMP.ESMP_GridGetCoord(dstGrid, ESMP.ESMP_STAGGERLOC_CENTER) dstDimsCorner = ESMP.ESMP_GridGetCoord(dstGrid, ESMP.ESMP_STAGGERLOC_CORNER) dstXCenter = ESMP.ESMP_GridGetCoordPtr(dstGrid, 0, ESMP.ESMP_STAGGERLOC_CENTER) dstYCenter = ESMP.ESMP_GridGetCoordPtr(dstGrid, 1, ESMP.ESMP_STAGGERLOC_CENTER) dstXCorner = ESMP.ESMP_GridGetCoordPtr(dstGrid, 0, ESMP.ESMP_STAGGERLOC_CORNER) dstYCorner = ESMP.ESMP_GridGetCoordPtr(dstGrid, 1, ESMP.ESMP_STAGGERLOC_CORNER) # mask ESMP.ESMP_GridAddItem(srcGrid, item=ESMP.ESMP_GRIDITEM_MASK) srcMask = ESMP.ESMP_GridGetItem(srcGrid, item=ESMP.ESMP_GRIDITEM_MASK) # create field srcFld = ESMP.ESMP_FieldCreateGrid( srcGrid, 'srcFld', typekind=ESMP.ESMP_TYPEKIND_R4, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) srcFldPtr = ESMP.ESMP_FieldGetPtr(srcFld) srcFld2 = ESMP.ESMP_FieldCreateGrid( srcGrid, 'srcFld2', typekind=ESMP.ESMP_TYPEKIND_R4, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) srcFldPtr2 = ESMP.ESMP_FieldGetPtr(srcFld2) dstFld = ESMP.ESMP_FieldCreateGrid( dstGrid, 'dstFld', typekind=ESMP.ESMP_TYPEKIND_R4, staggerloc=ESMP.ESMP_STAGGERLOC_CENTER) dstFldPtr = ESMP.ESMP_FieldGetPtr(dstFld) # set coords, mask, and field values for src and dst srcNtotCenter = reduce(operator.mul, [srcDimsCenter[1][i] - srcDimsCenter[0][i] \ for i in range(2)]) srcNtotCorner = reduce(operator.mul, [srcDimsCorner[1][i] - srcDimsCorner[0][i] \ for i in range(2)]) srcJCenterBeg = srcDimsCenter[0][1] srcJCenterEnd = srcDimsCenter[1][1] srcJCornerBeg = srcDimsCorner[0][1] srcJCornerEnd = srcDimsCorner[1][1] srcICenterBeg = srcDimsCenter[0][0] srcICenterEnd = srcDimsCenter[1][0] srcICornerBeg = srcDimsCorner[0][0] srcICornerEnd = srcDimsCorner[1][0] srcLonCenter = so.getLongitude() srcLatCenter = so.getLatitude() srcXCenter[:] = numpy.reshape( srcLonCenter[srcJCenterBeg:srcJCenterEnd, srcICenterBeg:srcICenterEnd], (srcNtotCenter, )) srcYCenter[:] = numpy.reshape( srcLatCenter[srcJCenterBeg:srcJCenterEnd, srcICenterBeg:srcICenterEnd], (srcNtotCenter, )) srcXCorner[:] = numpy.reshape( srcLonCorner[srcJCornerBeg:srcJCornerEnd, srcICornerBeg:srcICornerEnd], (srcNtotCorner, )) srcYCorner[:] = numpy.reshape( srcLatCorner[srcJCornerBeg:srcJCornerEnd, srcICornerBeg:srcICornerEnd], (srcNtotCorner, )) srcFldPtr[:] = numpy.reshape( so[srcJCenterBeg:srcJCenterEnd, srcICenterBeg:srcICenterEnd], (srcNtotCenter, )) srcMask[:] = (srcFldPtr == so.missing_value) dstNtotCenter = reduce( operator.mul, [dstDimsCenter[1][i] - dstDimsCenter[0][i] for i in range(2)]) dstNtotCorner = reduce( operator.mul, [dstDimsCorner[1][i] - dstDimsCorner[0][i] for i in range(2)]) # clt grid is rectilinear, transform to curvilinear lons = clt.getGrid().getLongitude() lats = clt.getGrid().getLatitude() ny, nx = dstDimsCenter[1][1] - dstDimsCenter[0][1], dstDimsCenter[1][ 0] - dstDimsCenter[0][0] yy = numpy.outer(lats[dstDimsCenter[0][1]:dstDimsCenter[1][1]], numpy.ones((nx, ), dtype=numpy.float32)) xx = numpy.outer(numpy.ones((ny, ), dtype=numpy.float32), lons[dstDimsCenter[0][0]:dstDimsCenter[1][0]]) y = yy.reshape((dstNtotCenter, )) x = xx.reshape((dstNtotCenter, )) dstXCenter[:] = x[:] dstYCenter[:] = y[:] dstXCorner[:] = numpy.reshape( dstLonCorner[dstDimsCorner[0][1]:dstDimsCorner[1][1], dstDimsCorner[0][0]:dstDimsCorner[1][0]], (dstNtotCorner, )) dstYCorner[:] = numpy.reshape( dstLatCorner[dstDimsCorner[0][1]:dstDimsCorner[1][1], dstDimsCorner[0][0]:dstDimsCorner[1][0]], (dstNtotCorner, )) dstFldPtr[:] = 0 # regrid forward and backward maskVals = numpy.array([1], numpy.int32) # values defining mask regrid1 = ESMP.ESMP_FieldRegridStore( srcFld, dstFld, srcMaskValues=maskVals, dstMaskValues=None, regridmethod=ESMP.ESMP_REGRIDMETHOD_CONSERVE, unmappedaction=ESMP.ESMP_UNMAPPEDACTION_IGNORE, srcFracField=None, dstFracField=None) ESMP.ESMP_FieldRegrid(srcFld, dstFld, regrid1) jbeg, jend = dstDimsCenter[0][1], dstDimsCenter[1][1] ibeg, iend = dstDimsCenter[0][0], dstDimsCenter[1][0] soInterp = numpy.reshape(dstFldPtr, (jend - jbeg, iend - ibeg)) regrid2 = ESMP.ESMP_FieldRegridStore( dstFld, srcFld2, srcMaskValues=None, dstMaskValues=None, regridmethod=ESMP.ESMP_REGRIDMETHOD_CONSERVE, unmappedaction=ESMP.ESMP_UNMAPPEDACTION_IGNORE, srcFracField=None, dstFracField=None) ESMP.ESMP_FieldRegrid(dstFld, srcFld2, regrid2) jbeg, jend = srcDimsCenter[0][1], srcDimsCenter[1][1] ibeg, iend = srcDimsCenter[0][0], srcDimsCenter[1][0] soInterpInterp = numpy.reshape(srcFldPtr2, (jend - jbeg, iend - ibeg)) toc = time.time() avgdiff = numpy.sum(so[jbeg:jend, ibeg:iend] - soInterpInterp) / float(srcNtotCenter) print 'avgdiff = ', avgdiff self.assertLess(abs(avgdiff), 3.0) if PLOT: pylab.figure(1) pylab.subplot(2, 2, 1) pylab.pcolor(so, vmin=20.0, vmax=40.0) pylab.colorbar() pylab.title('ESMF conserve native: so') pylab.subplot(2, 2, 2) pylab.pcolor(soInterp, vmin=20.0, vmax=40.0) pylab.colorbar() pylab.title('ESMF conserve native: soInterp') pylab.subplot(2, 2, 3) pylab.pcolor(soInterpInterp, vmin=20.0, vmax=40.0) pylab.colorbar() pylab.title('ESMF conserve native: soInterpInterp') pylab.subplot(2, 2, 4) pylab.pcolor(so[jbeg:jend, ibeg:iend] - soInterpInterp, vmin=-0.5, vmax=0.5) pylab.colorbar() pylab.title('ESMF conserve native: error') # clean up ESMP.ESMP_FieldRegridRelease(regrid2) ESMP.ESMP_FieldRegridRelease(regrid1) ESMP.ESMP_FieldDestroy(dstFld) ESMP.ESMP_GridDestroy(dstGrid) ESMP.ESMP_FieldDestroy(srcFld) ESMP.ESMP_FieldDestroy(srcFld2) ESMP.ESMP_GridDestroy(srcGrid)