def make_netcdf_cube_voronoi(cs_obj, fpath): up_size = cs_obj.up_size # max number of voronoi vertices # 6 if nomal, 8 if ne6np4 corner_max_size = 6 center_xyzs = np.zeros((up_size,3), 'f8') center_latlons = np.zeros((up_size,2), 'f8') corner_xyzs = np.zeros((up_size,corner_max_size,3), 'f8') corner_latlons = np.zeros((up_size,corner_max_size,2), 'f8') corner_sizes = np.zeros(up_size, 'i4') corner_areas = np.zeros(up_size, 'f8') for dst in range(up_size): center_xyzs[dst,:] = cs_obj.xyzs[dst] center_latlons[dst,:] = cs_obj.latlons[dst] voronoi_xyzs = cs_obj.get_voronoi(dst) for i, corner_xyz in enumerate(voronoi_xyzs): corner_xyzs[dst,i,:] = corner_xyz corner_latlons[dst,i,:] = xyz2latlon(*corner_xyz) corner_sizes[dst] = len(voronoi_xyzs) corner_areas[dst] = area_polygon(voronoi_xyzs) #------------------------------------------------------------ # Save as NetCDF #------------------------------------------------------------ ncf = nc.Dataset(fpath, 'w', format='NETCDF3_64BIT') # for pnetcdf ncf.description = 'Voronoi diagram on the Cubed-sphere' ncf.coordinates = 'cartesian' ncf.rotated = str(cs_obj.rotated).lower() ncf.ne = cs_obj.ne ncf.ngq = cs_obj.ngq ncf.ep_size = cs_obj.ep_size ncf.up_size = up_size ncf.createDimension('up_size', up_size) ncf.createDimension('corner_max_size', corner_max_size) ncf.createDimension('3', 3) ncf.createDimension('2', 2) vcenter_xyzs = ncf.createVariable('center_xyzs', 'f8', ('up_size','3')) vcenter_lls = ncf.createVariable('center_latlons', 'f8', ('up_size','2')) vcorner_xyzs = ncf.createVariable('corner_xyzs', 'f8', ('up_size','corner_max_size','3')) vcorner_lls = ncf.createVariable('corner_latlons', 'f8', ('up_size','corner_max_size','2')) vcorner_sizes = ncf.createVariable('corner_sizes', 'i4', ('up_size',)) vcorner_areas = ncf.createVariable('corner_areas', 'f8', ('up_size',)) vcenter_xyzs[:] = center_xyzs[:] vcenter_lls[:] = center_latlons[:] vcorner_xyzs[:] = corner_xyzs[:] vcorner_lls[:] = corner_latlons[:] vcorner_sizes[:] = corner_sizes[:] vcorner_areas[:] = corner_areas[:] ncf.close()
def test_ll_voronoi_area(): """ LatlonGridRemap.get_voronoi(): check the sphere area """ from cube_remap import LatlonGridRemap from util.geometry.sphere import area_polygon from math import fsum, pi from util.convert_coord.cart_ll import latlon2xyz nlat, nlon = 90, 180 # nlat, nlon = 180, 360 # nlat, nlon = 360, 720 # nlat, nlon = 720, 1440 ll_obj = LatlonGridRemap(nlat, nlon) area_list = list() for idx in xrange(ll_obj.nsize): # latlons = ll_obj.get_voronoi(idx) # xyzs = [latlon2xyz(*latlon) for latlon in latlons] xyzs = ll_obj.get_voronoi(idx) area_list.append(area_polygon(xyzs)) aa_equal(fsum(area_list), 4 * pi, 12) """
def test_cs_voronoi_area(): """ CubeGridRemap.get_voronoi(): check the sphere area, ne=3 """ from cube_remap import CubeGridRemap from util.geometry.sphere import area_polygon from math import fsum, pi from util.convert_coord.cart_cs import xyp2xyz ne, ngq = 3, 4 rotated = False cube = CubeGridRemap(ne, ngq, rotated) area_list = list() for uid in xrange(cube.up_size): # xy_vts, vor_obj = cube.get_voronoi_scipy(uid) # xyzs = [xyp2xyz(x,y,1) for x,y in xy_vts] # area_list.append( area_polygon(xyzs) ) xyzs = cube.get_voronoi(uid) area_list.append(area_polygon(xyzs)) aa_equal(fsum(area_list), 4 * pi, 15) """
def make_remap_matrix(self, debug=False): dst_obj = self.dst_obj src_obj = self.src_obj dsw_dict = dict() # {dst:[(s,w),(s,w),...],...} if debug: ipoly_dict = dict() # {dst:[(src,ipoly,iarea),...],..} for dst, (lat0,lon0) in enumerate(dst_obj.latlons): dst_poly = dst_obj.get_voronoi(dst) dst_area = area_polygon(dst_poly) inout = pt_in_polygon(dst_poly, latlon2xyz(lat0,lon0)) if inout != 'in': print('dst',dst) print('latlon_in_poly?', inout) idx1, idx2, idx3, idx4 = src_obj.get_surround_idxs(lat0, lon0) candidates = set([idx1, idx2, idx3, idx4]) if -1 in candidates: candidates.remove(-1) checked_srcs = set() dsw_dict[dst] = list() while len(candidates) > 0: #print('\t', checked_srcs) src = candidates.pop() src_poly = src_obj.get_voronoi(src) ipoly = intersect_two_polygons(dst_poly, src_poly) checked_srcs.add(src) if ipoly != None: iarea = area_polygon(ipoly) area_ratio = iarea/dst_area if area_ratio > 1e-10: dsw_dict[dst].append( (src, area_ratio) ) nbrs = set(src_obj.get_neighbors(src)) candidates.update(nbrs - checked_srcs) if debug: ipoly_dict[dst].append( (src,ipoly,iarea) ) if debug: self.save_netcdf_ipoly(ipoly_dict) return self.make_remap_matrix_from_dsw_dict(dsw_dict)
def make_remap_matrix_mpi(self, debug=False): from mpi4py import MPI comm = MPI.COMM_WORLD nproc = comm.Get_size() myrank = comm.Get_rank() if nproc == 1: return self.make_remap_matrix() dst_obj = self.dst_obj src_obj = self.src_obj chunk_size = dst_obj.nsize//nproc//10 dsw_dict = dict() # {dst:[(src,wgt),(src,wgt),...],...} if debug: ipoly_dict = dict() # {dst:[(src,ipoly,iarea),...],..} if myrank == 0: start = 0 while start < dst_obj.nsize: rank = comm.recv(source=MPI.ANY_SOURCE, tag=0) comm.send(start, dest=rank, tag=10) start += chunk_size for i in range(nproc-1): rank = comm.recv(source=MPI.ANY_SOURCE, tag=0) comm.send('quit', dest=rank, tag=10) slave_dsw_dict = comm.recv(source=rank, tag=20) dsw_dict.update(slave_dsw_dict) if debug: slave_ipoly_dict = comm.recv(source=rank, tag=30) ipoly_dict.update(slave_src_poly_dict) self.save_netcdf_ipoly(ipoly_dict) return self.make_remap_matrix_from_dsw_dict(dsw_dict) else: while True: comm.send(myrank, dest=0, tag=0) msg = comm.recv(source=0, tag=10) if msg == 'quit': print("Slave rank {} quit.".format(myrank)) comm.send(dsw_dict, dest=0, tag=20) if debug: comm.send(ipoly_dict, dest=0, tag=30) return None, None, None start = msg end = start + chunk_size end = dst_obj.nsize if end > dst_obj.nsize else end print("rank {}: {} ~ {} ({} %%)".format(myrank, start, end, end/dst_obj.nsize*100)) for dst in range(start,end): lat0, lon0 = dst_obj.latlons[dst] dst_poly = dst_obj.get_voronoi(dst) dst_area = area_polygon(dst_poly) idx1, idx2, idx3, idx4 = src_obj.get_surround_idxs(lat0, lon0) candidates = set([idx1, idx2, idx3, idx4]) if -1 in candidates: candidates.remove(-1) checked_srcs = set() dsw_dict[dst] = list() if debug: ipoly_dict[dst] = list() while len(candidates) > 0: src = candidates.pop() src_poly = src_obj.get_voronoi(src) ipoly = intersect_two_polygons(dst_poly, src_poly) checked_srcs.add(src) if ipoly != None: iarea = area_polygon(ipoly) area_ratio = iarea/dst_area if area_ratio > 1e-10: dsw_dict[dst].append( (src, area_ratio) ) nbrs = set(src_obj.get_neighbors(src)) candidates.update(nbrs - checked_srcs) if debug: ipoly_dict[dst].append( (src,ipoly,iarea) )