def test_identical_remapping(self, input_dir, output_dir): """ Remap between two identical grids """ my_dir = os.path.dirname(os.path.realpath(__file__)) cmd = [os.path.join(my_dir, '../', 'remapweights.py')] mom_hgrid = os.path.join(input_dir, 'grid_spec.nc') mom_mask = os.path.join(input_dir, 'grid_spec.nc') output = os.path.join(output_dir, 'MOM_MOM_conserve.nc') args = [ 'MOM', 'MOM', '--src_grid', mom_hgrid, '--dest_grid', mom_hgrid, '--output', output ] ret = sp.call(cmd + args) assert ret == 0 assert os.path.exists(output) # Only use these to pull out the dimensions of the grids. mom = MomGrid.fromfile(mom_hgrid, mask_file=mom_mask) src = np.empty_like(mom.x_t) for i in range(src.shape[0]): src[i, :] = i remap(src, output, src.shape)
def main(): parser = argparse.ArgumentParser() parser.add_argument('woa_input', help='The WOA input file.') parser.add_argument('ocean_hgrid', help='The horizontal MOM grid definition to remap to') parser.add_argument( 'old_salt_sfc_restore', help='The old salt sfc restoring file. Needed for metadata.') parser.add_argument('output', help='salt_sfc_restore.nc file for MOM5') parser.add_argument( '--interpolation_weights', default=None, help='Interpolation weights, file if not given this will be created.') parser.add_argument('--method', default='patch', help=""" Interpolation method, passed to ESMF_RegridWeightGen.""" ) parser.add_argument('--npes', default=None, help=""" The number of PEs to use. Default is 1/2 of available.""" ) args = parser.parse_args() if args.npes is None: import multiprocessing as mp args.npes = mp.cpu_count() // 2 src_grid = WoaGrid(args.woa_input, calc_areas=False) dest_grid = MomGrid.fromfile(args.ocean_hgrid, calc_areas=False) dest_res = (dest_grid.num_lat_points, dest_grid.num_lon_points) if args.interpolation_weights is None: weights = create_weights(src_grid, dest_grid, args.npes, args.method) else: weights = args.interpolation_weights with nc.Dataset(args.woa_input) as f: src = f.variables['so'][:] dest = np.zeros((src.shape[0], dest_res[0], dest_res[1])) for t in range(src.shape[0]): smooth_src = smooth2d(src[t, :, :]) dest[t, :, :] = remap(smooth_src, weights, dest_res) if 'conserve' in args.method: rel_err = calc_regridding_err(weights, smooth_src, dest[t, :, :]) print('relative error {}'.format(rel_err)) assert rel_err < 1e-14 shutil.copyfile(args.old_salt_sfc_restore, args.output) with nc.Dataset(args.output, 'r+') as f: f.variables['salt'][:] = dest
def test_convert_mom_to_cice(self, input_dir, output_dir): """ Read in a MOM grid and write out a cice grid at the same resolution. """ mask = os.path.join(input_dir, 'ocean_01_mask.nc') hgrid = os.path.join(input_dir, 'ocean_01_hgrid.nc') mom = MomGrid.fromfile(hgrid, mask_file=mask) cice = CiceGrid.fromgrid(mom) grid_file = os.path.join(output_dir, 'grid.nc') mask_file = os.path.join(output_dir, 'kmt.nc') cice.write(grid_file, mask_file)
def get_grid(filename): try: grid = MomGrid.fromfile(filename) return grid except KeyError as e: print("Not a mom grid: ", type(e), str(e)) try: grid = WoaGrid(filename) return grid except KeyError as e: print("Not a WOA grid: ", type(e), str(e))
def main(): parser = argparse.ArgumentParser() parser.add_argument('woa_input', help='The WOA input file.') parser.add_argument('ocean_hgrid', help='The horizontal MOM grid definition to remap to') parser.add_argument('old_salt_sfc_restore', help='The old salt sfc restoring file. Needed for metadata.') parser.add_argument('output', help='salt_sfc_restore.nc file for MOM5') parser.add_argument('--interpolation_weights', default=None, help='Interpolation weights, file if not given this will be created.') parser.add_argument('--method', default='patch', help=""" Interpolation method, passed to ESMF_RegridWeightGen.""") parser.add_argument('--npes', default=None, help=""" The number of PEs to use. Default is 1/2 of available.""") args = parser.parse_args() if args.npes is None: import multiprocessing as mp args.npes = mp.cpu_count() // 2 src_grid = WoaGrid(args.woa_input, calc_areas=False) dest_grid = MomGrid.fromfile(args.ocean_hgrid, calc_areas=False) dest_res = (dest_grid.num_lat_points, dest_grid.num_lon_points) if args.interpolation_weights is None: weights = create_weights(src_grid, dest_grid, args.npes, 'conserve') else: weights = args.interpolation_weights with nc.Dataset(args.woa_input) as f: src = f.variables['so'][:] dest = np.zeros((src.shape[0], dest_res[0], dest_res[1])) for t in range(src.shape[0]): smooth_src = smooth2d(src[t, :, :]) dest[t, :, :] = remap(smooth_src, weights, dest_res) if 'conserve' in args.method: rel_err = calc_regridding_err(weights, smooth_src, dest[t, :, :]) print('relative error {}'.format(rel_err)) assert rel_err < 1e-14 shutil.copyfile(args.old_salt_sfc_restore, args.output) with nc.Dataset(args.output, 'r+') as f: import pdb pdb.set_trace() f.variables['salt'][:] = dest
def remap_to_tenth(input_dir, output_dir, src_field, weights=None): """ Remap MOM quarter degree to MOM tenth. This is used to remap OASIS and CICE restarts. """ quarter_hgrid = os.path.join(input_dir, 'ocean_hgrid.nc') quarter_mask = os.path.join(input_dir, 'ocean_mask.nc') mom_quarter = MomGrid.fromfile(quarter_hgrid, mask_file=quarter_mask) tenth_hgrid = os.path.join(input_dir, 'ocean_01_hgrid.nc') tenth_mask = os.path.join(input_dir, 'ocean_01_mask.nc') mom_tenth = MomGrid.fromfile(tenth_hgrid) # The src_field has land points, fill these in to avoid masking mess. new_src_field = fill_mask_with_nearest_neighbour(src_field, mom_quarter.mask_t) if weights is None: my_dir = os.path.dirname(os.path.realpath(__file__)) weights = os.path.join(output_dir, 'MOM025_MOM10th_conserve.nc') cmd = [os.path.join(my_dir, '../', 'remapweights.py')] args = [ 'MOM', 'MOM', '--src_grid', quarter_hgrid, '--dest_grid', tenth_hgrid, '--dest_mask', tenth_mask, '--method', 'conserve', '--output', weights ] ret = sp.call(cmd + args) assert ret == 0 assert os.path.exists(weights) dest_field = remap(new_src_field, weights, (mom_tenth.num_lat_points, mom_tenth.num_lon_points)) return dest_field, weights
def remap_atm_to_ocean(input_dir, output_dir, mom_hgrid, mom_mask, src=None, method='conserve', core2_or_jra='CORE2'): my_dir = os.path.dirname(os.path.realpath(__file__)) cmd = [os.path.join(my_dir, '../', 'remapweights.py')] if core2_or_jra == 'CORE2': atm_hgrid = os.path.join(input_dir, 't_10.0001.nc') atm_grid = Core2Grid(atm_hgrid) elif core2_or_jra == 'JRA55': atm_hgrid = os.path.join(input_dir, 't_10.1984.30Jun2016.nc') atm_grid = Jra55Grid(atm_hgrid) elif core2_or_jra == 'JRA55_river': atm_hgrid = os.path.join(input_dir, 'RYF.runoff_all.1984_1985.nc') atm_grid = Jra55RiverGrid(atm_hgrid) else: assert False weights = os.path.join(output_dir, 'ATM_MOM_conserve.nc') t0 = time.time() args = [ core2_or_jra, 'MOM', '--src_grid', atm_hgrid, '--dest_grid', mom_hgrid, '--dest_mask', mom_mask, '--method', method, '--output', weights ] ret = sp.call(cmd + args) t1 = time.time() assert ret == 0 assert os.path.exists(weights) # Only use these to pull out the dimensions of the grids. mom = MomGrid.fromfile(mom_hgrid, mask_file=mom_mask) if src is None: src = np.empty_like(atm_grid.x_t) for i in range(src.shape[0]): src[i, :] = i dest = remap(src, weights, (mom.num_lat_points, mom.num_lon_points)) return src, dest, weights, t1 - t0
def main(): parser = argparse.ArgumentParser() parser.add_argument('ocean_hgrid', help='ocean_mask.nc file') parser.add_argument('ocean_mask', help='ocean_hgrid.nc file') args = parser.parse_args() mom = MomGrid.fromfile(args.ocean_hgrid, mask_file=args.ocean_mask) # FIXME: # MOM dx is at the cell centre while HTN is on the Northern boundary # MOM dy is at the cell centre while HTE is on the Eastern boundary cice = CiceGrid.fromgrid(mom) grid_file = os.path.join('grid.nc') mask_file = os.path.join('kmt.nc') cice.write(grid_file, mask_file)
def factory(model_name, model_hgrid, model_mask, model_rows=None, model_cols=None): if model_name == 'MOM': model_grid = MomGrid.fromfile(model_hgrid, mask_file=model_mask) elif model_name == 'WOA': model_grid = WoaGrid(model_hgrid, mask_file=model_mask) elif model_name == 'CICE': model_grid = CiceGrid.fromfile(model_hgrid, mask_file=model_mask) elif model_name == 'NEMO': model_grid = NemoGrid(model_hgrid, mask_file=model_mask) elif model_name == 'SPE': if model_rows is None: model_rows = 64 if model_cols is None: model_rows = 128 model_grid = T42Grid(model_cols, model_rows, 1, model_mask, description='Spectral') elif model_name == 'FVO': if model_rows is None: model_rows = 64 if model_cols is None: model_rows = 128 model_grid = FV300Grid(model_cols, model_rows, 1, model_mask, description='FV') elif model_name == 'CORE2': model_grid = Core2Grid(model_hgrid) elif model_name == 'JRA55': model_grid = Jra55Grid(model_hgrid) else: assert False return model_grid
def test_remap_restarts_tenth(self, input_dir, output_dir): """ Remap restarts from 0.25 to 0.1 degree. """ # Input file are at a 1/4 degree. files = [ 'monthly_sstsss.nc', 'i2o.nc', 'i2a.nc', 'o2i.nc', 'u_star.nc' ] mom = MomGrid.fromfile(os.path.join(input_dir, 'ocean_01_hgrid.nc')) weights = None for fname in files: with nc.Dataset(os.path.join(output_dir, fname), 'w') as fd: with nc.Dataset(os.path.join(input_dir, fname), 'r') as fs: assert 'ny' in fs.dimensions assert 'nx' in fs.dimensions fd.createDimension('ny', mom.num_lat_points) fd.createDimension('nx', mom.num_lon_points) for vname in fs.variables: if vname == 'time': continue vd = fd.createVariable(vname, 'f8', ('ny', 'nx')) if len(fs.variables[vname].shape) == 3: src = fs.variables[vname][0, :, :] else: src = fs.variables[vname][:, :] vd[:], weights = remap_to_tenth( input_dir, output_dir, src, weights) for fname in files: assert os.path.exists(os.path.join(output_dir, fname))
def main(): parser = argparse.ArgumentParser() parser.add_argument('input_dir', help=""" The ACCESS-OM2 input directory.""") parser.add_argument('jra55_input', help=""" The JRA55 input directory.""") parser.add_argument('--atm', default=None, help=""" Atmosphere grid to regrid from, can be one of: CORE2, JRA55, JRA55_runoff""") parser.add_argument('--ocean', default=None, help=""" Ocean grid to regrid to, can be one of: MOM1, MOM01, MOM025""") parser.add_argument('--method', default=None, help=""" The interpolation method to use.""") parser.add_argument('--npes', default=1, help=""" The number of PEs to use.""") args = parser.parse_args() atm_options = ['JRA55', 'JRA55_runoff', 'CORE2'] ocean_options = ['MOM1', 'MOM025', 'MOM01'] method_options = ['patch', 'conserve2nd'] if args.atm is None: args.atm = atm_options else: if args.atm not in atm_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.atm = [args.atm] if args.ocean is None: args.ocean = ocean_options else: if args.ocean not in ocean_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.ocean = [args.ocean] if args.method is None: args.method = method_options else: args.method = [args.method] grid_file_dict = find_grid_defs(args.input_dir, args.jra55_input) for ocean in args.ocean: for atm in args.atm: for method in args.method: if atm == 'CORE2': src_grid = Core2Grid(grid_file_dict[atm]) elif atm == 'JRA55': src_grid = Jra55Grid(grid_file_dict[atm]) else: src_grid = Jra55RiverGrid(grid_file_dict[atm]) umask_file = grid_file_dict[ocean][1] dest_grid = MomGrid.fromfile(grid_file_dict[ocean][0], mask_file=umask_file) weights = create_weights(src_grid, dest_grid, args.npes, method) weights = convert_to_scrip_output(weights) shutil.move(weights, '{}_{}_{}.nc'.format(atm, ocean, method)) return 0
def remap_to_mom(input_file, mom_hgrid, mom_mask, output_file, method='conserve', varname='runoff', verbose=False, clobber=False): """ Remapping JRA and check that it is conservative. It will be necessary to use a destination mask. We want to move all points from src into unmasked parts of the destination. """ if verbose: print("Opening input file: {}".format(input_file)) oasis_grids_dir = os.environ["OASIS_GRIDS_DIR"] cmd = [os.path.join(oasis_grids_dir, 'remapweights.py')] # input_grid = Jra55Grid(input_file) output_dir = os.path.dirname(output_file) if verbose: print("Output directory: {}".format(output_dir)) weights = os.path.join(output_dir, 'JRA_MOM_conserve.nc') if not os.path.exists(weights): args = [ 'JRA55', 'MOM', '--src_grid', input_file, '--dest_grid', mom_hgrid, '--dest_mask', mom_mask, '--method', method, '--output', weights ] if verbose: print("Generating weights file : {} using\n{}".format( weights, " ".join(cmd + args))) ret = sp.call(cmd + args) assert ret == 0 assert os.path.exists(weights) # Only use these to pull out the dimensions of the grids. mom = MomGrid.fromfile(mom_hgrid, mask_file=mom_mask) with nc.Dataset(input_file) as f: var = f.variables[varname] if "time" in f.variables: time = f.variables["time"] time_units = time.units else: time = numpy.arange(0, var.shape[0]) time_units = "days since 1900-01-01" create_mom_output(mom, output_file, time_units) for idx in range(var.shape[0]): src = var[idx, :] if verbose: print("Remapping using weights for index: {}".format(idx)) dest = remap(src, weights, (mom.num_lat_points, mom.num_lon_points)) rel_err = calc_regridding_err(weights, src, dest) print('ESMF relative error {}'.format(rel_err)) write_mom_output(output_file, varname, var.long_name, var.units, dest, idx, time[idx])
def main(): parser = argparse.ArgumentParser() parser.add_argument('input_dir', help=""" The ACCESS-OM2 input directory.""") parser.add_argument('jra55_input', help=""" The JRA55 input directory.""") parser.add_argument('core_input', help=""" The CORE input directory.""") parser.add_argument('--atm', default=None, help=""" Atmosphere grid to regrid from, can be one of: CORE2, JRA55, JRA55_runoff, Daitren_runoff""") parser.add_argument('--ocean', default=None, help=""" Ocean grid to regrid to, can be one of: MOM1, MOM01, MOM025""") parser.add_argument('--method', default=None, help=""" The interpolation method to use, can be patch, conserve or conserve2nd""" ) parser.add_argument('--npes', default=None, help=""" The number of PEs to use.""") parser.add_argument('--unmask_dest', action='store_true', help='Ignore destination grid mask') args = parser.parse_args() atm_options = ['JRA55', 'JRA55_runoff', 'CORE2', 'Daitren_runoff'] ocean_options = ['MOM1', 'MOM025', 'MOM01'] method_options = ['patch', 'conserve', 'conserve2nd'] if args.atm is None: args.atm = atm_options else: if args.atm not in atm_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.atm = [args.atm] if args.ocean is None: args.ocean = ocean_options else: if args.ocean not in ocean_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.ocean = [args.ocean] if args.method is None: args.method = method_options else: args.method = [args.method] if args.npes is None: import multiprocessing as mp args.npes = mp.cpu_count() // 2 grid_file_dict = find_grid_defs(args.input_dir, args.jra55_input, args.core_input) for ocean in args.ocean: umask_file = grid_file_dict[ocean][1] dest_grid = MomGrid.fromfile(grid_file_dict[ocean][0], mask_file=umask_file) for atm in args.atm: if atm == 'CORE2': src_grid = Core2Grid(grid_file_dict[atm]) elif atm == 'Daitren_runoff': src_grid = DaitrenRunoffGrid(grid_file_dict[atm]) elif atm == 'JRA55': src_grid = Jra55Grid(grid_file_dict[atm]) elif atm == 'JRA55_runoff': src_grid = Jra55RiverGrid(grid_file_dict[atm], calc_areas=False) else: print('Unrecognised atmosphere grid: {}'.format(atm)) return 1 for method in args.method: weights = create_weights(src_grid, dest_grid, args.npes, method, unmasked_dest=args.unmask_dest) if not weights: return 1 weights = convert_to_scrip_output(weights) if not weights: return 1 shutil.move(weights, '{}_{}_{}.nc'.format(atm, ocean, method)) return 0
def main(): parser = argparse.ArgumentParser() parser.add_argument('input_dir', help=""" The ACCESS-OM2 input directory.""") parser.add_argument('jra55_input', help=""" The JRA55 input directory.""") parser.add_argument('core_input', help=""" The CORE input directory.""") parser.add_argument('--atm', default=None, help=""" Atmosphere grid to regrid from, can be one of: CORE2, JRA55, JRA55_runoff, Daitren_runoff""") parser.add_argument('--ocean', default=None, help=""" Ocean grid to regrid to, can be one of: MOM1, MOM01, MOM025""") parser.add_argument('--method', default=None, help=""" The interpolation method to use, can be patch or conserve2nd""") parser.add_argument('--npes', default=None, help=""" The number of PEs to use.""") args = parser.parse_args() atm_options = ['JRA55', 'JRA55_runoff', 'CORE2', 'Daitren_runoff'] ocean_options = ['MOM1', 'MOM025', 'MOM01'] method_options = ['patch', 'conserve2nd'] if args.atm is None: args.atm = atm_options else: if args.atm not in atm_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.atm = [args.atm] if args.ocean is None: args.ocean = ocean_options else: if args.ocean not in ocean_options: print("Error: bad atm grid.", file=sys.stderr) parser.print_help() return 1 args.ocean = [args.ocean] if args.method is None: args.method = method_options else: args.method = [args.method] if args.npes is None: import multiprocessing as mp args.npes = mp.cpu_count() // 2 grid_file_dict = find_grid_defs(args.input_dir, args.jra55_input, args.core_input) for ocean in args.ocean: umask_file = grid_file_dict[ocean][1] dest_grid = MomGrid.fromfile(grid_file_dict[ocean][0], mask_file=umask_file) for atm in args.atm: if atm == 'CORE2': src_grid = Core2Grid(grid_file_dict[atm]) elif atm == 'Daitren_runoff': src_grid = DaitrenRunoffGrid(grid_file_dict[atm]) elif atm == 'JRA55': src_grid = Jra55Grid(grid_file_dict[atm]) elif atm == 'JRA55_runoff': src_grid = Jra55RiverGrid(grid_file_dict[atm], calc_areas=False) else: print('Unrecognised atmosphere grid: {}'.format(atm)) return 1 for method in args.method: weights = create_weights(src_grid, dest_grid, args.npes, method) if not weights: return 1 weights = convert_to_scrip_output(weights) if not weights: return 1 shutil.move(weights, '{}_{}_{}.nc'.format(atm, ocean, method)) return 0