ClimaCoreTempestRemap.jl
ClimaCoreTempestRemap.jl provides an interfaces for using ClimaCore data with the TempestRemap remapping package, by Paul Ullrich.
Interface
Online remap
ClimaCoreTempestRemap.LinearMap
— TypeLinearMap{S, T, W, I, V}
stores information on the TempestRemap map and the source and target data:
where:
source_space
andtarget_space
are ClimaCore's 2D spaces.weights
is a vector of remapping weights. (length = number of overlap-mesh nodes).source_local_idxs
a 3-element Tuple with 3 index vectors, representing local (i,j,elem) indices on the source mesh. (length of each index vector = number of overlap-mesh nodes)target_local_idxs
is the same assource_local_idxs
but for the target mesh.row_indices
are the target row indices from TempestRemap. (length = number of overlap-mesh nodes)out_type
string that defines the output type.
ClimaCoreTempestRemap.generate_map
— Functiongenerate_map(target_space, source_space; in_type="cgll", out_type="cgll")
Generate the remapping weights from TempestRemap, returning a LinearMap
object. This should only be called once.
ClimaCoreTempestRemap.remap!
— Functionremap!(target::IJFH{S, Nqt}, R::LinearMap, source::IJFH{S, Nqs})
remap!(target::Fields.Field, R::LinearMap, source::Fields.Field)
Applies the remapping R
to a source
Field and stores the result in target
.
ClimaCoreTempestRemap.remap
— Functionremap(R::LinearMap, source::Field)
Applies the remapping R
to a source
Field, allocating a new field in the output.
Mesh export
ClimaCoreTempestRemap.write_exodus
— Functionwrite_exodus(filename, topology::Topology2D; normalize_coordinates=true)
Write the topology to an Exodus-formatted NetCDF file.
It tries to adhere to the Exodus II specification, but it is primarily intended for use with TempestRemap.
Note: the generated meshes will use a different ordering of nodes and elements than those generated by TempestRemap itself.
When using this function with a distributed topology input for MPI, it should only be called on a single process.
Options:
normalize_coordinates
: if true, the coordinates are normalized to be on the unit sphere (this is required for use with TempestRemap)
References
- EXODUS II: A finite element data model: https://www.osti.gov/biblio/10102115-exodus-ii-finite-element-data-model
NetCDF data export
ClimaCoreTempestRemap.def_time_coord
— Functiondef_time_coord(nc::NCDataset, length=Inf, eltype=Float64;
units = "seconds since 2020-01-01 00:00:00"
kwargs...
)
Deine a time coordinate (dimension + variable) "time"
in the NetCDF dataset nc
. By default its length is set to be unlimited. The variable corresponding to the coordinate is returned.
Additional attributes can be added as keyword arguments.
Example
timevar = add_time_coord!(nc; units = "seconds since 2020-01-01 00:00:00",)
timevar[:] = collect(0.0:0.5:60)
ClimaCoreTempestRemap.def_space_coord
— Functiondef_space_coord(nc::NCDataset, space::Spaces.AbstractSpace; type = "dgll")
Add spatial dimensions for space
in the NetCDF dataset nc
, compatible with the type used by remap_weights
.
If a compatible dimension already exists, it will be reused.
CommonDataModel.defVar
— MethodNCDatasets.defVar(nc::NCDataset, name, field::Field, extradims=())
Define a new variable in nc
named name
of suitable for storing field
, along with any further dimensions specified in extradims
. The new variable is returned.
This does not write any data to the variable.
Base.setindex!
— Methodvar[:, extraidx...] = field
Write the data in field
to a NetCDF variable var
. extraidx
are any extra indices of var
.
Appropriate spatial dimensions should already be defined by defVar
.
# Given a collection of fields U, write them as a single array to a NetCDF file.
def_space_coord(nc, space)
nc_time = def_time_coord(nc)
nc_u = defVar(nc, "u", Float64, space, ("time",))
for (i,t) in enumerate(times)
nc_time[i] = t
nc_u[:,i] = U[i]
end
Wrapper functions
ClimaCoreTempestRemap.rll_mesh
— Functionrll_mesh(filename::AbstractString; nlat=90, nlon = round(Int, nlat * 1.6); verbose=false)
Create a regular latitude-longitude (RLL) mesh and write it to filename
in Exodus format. nlat
is the number of latitudinal cells, and nlon
is the number of longitudinal cells.
Set verbose=true
to print information.
ClimaCoreTempestRemap.overlap_mesh
— Functionoverlap_mesh(outfile::AbstractString, meshfile_a::AbstractString, meshfile_b::AbstractString; verbose=false)
Create the overlap mesh of meshfile_a
and meshfile_b
and write it to outfile
. All files should be in Exodus format.
Set verbose=true
to print information.
ClimaCoreTempestRemap.remap_weights
— Functionremap_weights(
weightfile::AbstractString,
meshfile_in::AbstractString,
meshfile_out::AbstractString,
meshfile_overlap::AbstractString;
verbose=false,
kwargs...
)
Create a file weightfile
in SCRIP format containing the remapping weights from meshfile_in
to meshfile_out
, where meshfile_overlap
is constructed via overlap_mesh
.
Keyword arguments are passed as command-line options. These include:
in_type
/out_type
: the type of the input and output mesh:"fv"
(default): finite volume (one value per element)"cgll"
: continuous GLL finite element method (a single value for colocated nodes)"dgll"
: discontinuous GLL finite element method (duplicate values for colocated nodes)
- 'innp'/'outnp': Order of input and output meshes
- 'mono': Monotonicity of remapping
Set mono = true
for monotone remapping Set verbose=true
to print information.
ClimaCoreTempestRemap.apply_remap
— Functionapply_remap(outfile::AbstractString, infile::AbstractString, weightfile::AbstractString, vars; verbose=false)
Remap the NetCDF file infile
to outfile
, using the remapping weights weightfile
constructed via remap_weights
. vars
should be a collection of variable names to remap.
Set verbose=true
to print information.
Example
The following example converts an OrdinaryDiffEq solution object sol
to a netcdf file, and remaps it to an regular latitude-longitude (RLL) grid.
using ClimaCore: Geometry, Meshes, Domains, Topologies, Spaces, Quadratures
using NCDatasets, ClimaCoreTempestRemap
# sol is the integrator solution
# cspace is the center extrduded space
# fspace is the face extruded space
# the issue is that the Space types changed since this changed
# we can reconstruct it by digging around a bit
Nq = Quadratures.degrees_of_freedom(Spaces.quadrature_style(cspace))
datafile_cc = "test.nc"
NCDataset(datafile_cc, "c") do nc
# defines the appropriate dimensions and variables for a space coordinate
def_space_coord(nc, cspace, type = "cgll")
def_space_coord(nc, fspace, type = "cgll")
# defines the appropriate dimensions and variables for a time coordinate (by default, unlimited size)
nc_time = def_time_coord(nc)
# define variables
nc_rho = defVar(nc, "rho", Float64, cspace, ("time",))
nc_theta = defVar(nc, "theta", Float64, cspace, ("time",))
nc_u = defVar(nc, "u", Float64, cspace, ("time",))
nc_v = defVar(nc, "v", Float64, cspace, ("time",))
nc_w = defVar(nc, "w", Float64, fspace, ("time",))
# write data to netcdf file
for i = 1:length(sol.u)
nc_time[i] = sol.t[i]
# extract fields and convert to orthogonal coordinates
Yc = sol.u[i].Yc
uₕ = Geometry.UVVector.(sol.u[i].uₕ)
w = Geometry.WVector.(sol.u[i].w)
# write fields to file
nc_rho[:,i] = Yc.ρ
nc_theta[:,i] = Yc.ρθ ./ Yc.ρ
nc_u[:,i] = map(u -> u.u, uₕ)
nc_v[:,i] = map(u -> u.v, uₕ)
nc_w[:,i] = map(u -> u.w, w)
end
end
# write out our cubed sphere mesh
meshfile_cc = "mesh_cubedsphere.g"
write_exodus(meshfile_cc, Spaces.topology(Spaces.horizontal_space(cspace)))
# write out RLL mesh
nlat = 90
nlon = 180
meshfile_rll = "mesh_rll.g"
rll_mesh(meshfile_rll; nlat = nlat, nlon = nlon)
# construct overlap mesh
meshfile_overlap = "mesh_overlap.g"
overlap_mesh(meshfile_overlap, meshfile_cc, meshfile_rll)
# construct remap weight file
weightfile = "remap_weights.nc"
remap_weights(
weightfile,
meshfile_cc,
meshfile_rll,
meshfile_overlap;
in_type = "cgll",
in_np = Quadratures.degrees_of_freedom(Spaces.quadrature_style(cspace)),
)
# apply remap
datafile_rll = "data_rll.nc"
apply_remap(datafile_rll, datafile_cc, weightfile, ["rho", "theta", "u", "v", "w"])