Skip to content

longitude shift is wrong when going from TripolarGrid -> ClimaCore cubed sphere #59

@juliasloan25

Description

@juliasloan25

I ran an example from test/usecases/climacore.jl and plotted the remapped fields to verify they look ok visually in addition to the conservation tests we have. I noticed that the longitude values are correctly shifted when we go from ClimaCore -> Oceananigans, but when we remap back they aren't shifted.

ClimaCore has longitude on [-180, 180], while Oceananigans Tripolar is [0, 360].

Note also that the test is missing one last step we should also be testing, which is to put the vector of remapped values onto the ClimaCore space using set_value_per_element!. I'll start a PR to add that.

To reproduce

Example
using ConservativeRegridding
using ConservativeRegridding: Trees
using Statistics
using Test
import GeometryOps as GO, GeoInterface as GI, LibGEOS

using ClimaCore:
    CommonSpaces, Fields, Spaces, RecursiveApply, Meshes, Quadratures, Topologies, Domains, ClimaComms
using Oceananigans

using CairoMakie
using ClimaCoreMakie

const ClimaCoreExt = Base.get_extension(ConservativeRegridding, :ConservativeRegriddingClimaCoreExt)

latlon_grid = LatitudeLongitudeGrid(size=(360, 180, 1), longitude=(0, 360), latitude=(-90, 90), z = (0, 1), radius = GO.Spherical().radius)

    cubedsphere_space = CommonSpaces.CubedSphereSpace(;
        radius = GO.Spherical().radius,
        n_quad_points = 2,
        h_elem = 64,
    )

    # Define a field on the first space, to use as our source field
    field = Fields.coordinate_field(cubedsphere_space).long

    fig = Figure();
    ax = Axis(fig[1, 1])
    hm = fieldheatmap!(ax, field)
    Colorbar(fig[1, 2], hm)
    save("field_src.png", fig)

    ones_field = Fields.ones(cubedsphere_space)
    cubed_sphere_vals = zeros(6*cubedsphere_space.grid.topology.mesh.ne^2)
    ClimaCoreExt.get_value_per_element!(cubed_sphere_vals, field, ones_field)

    latlon_field = Oceananigans.CenterField(latlon_grid)
    latlon_vals = vec(interior(latlon_field))
    set!(latlon_field, (x, y, z) -> 0)

    regridder = ConservativeRegridding.Regridder(latlon_grid, cubedsphere_space; threaded = false)

    ConservativeRegridding.regrid!(latlon_vals, regridder, cubed_sphere_vals)
    fig = Figure();
    ax = Axis(fig[1, 1])
    hm = heatmap!(ax, interior(latlon_field, :, :, 1))
    Colorbar(fig[1, 2], hm)
    save("field_oc.png", fig)

    # Test that the integral is conserved
    @test isapprox(
        sum(abs, latlon_vals .* ConservativeRegridding.areas(GO.Spherical(), Trees.treeify(latlon_grid))),
        sum(abs, cubed_sphere_vals .* ConservativeRegridding.areas(GO.Spherical(), Trees.treeify(cubedsphere_space))),
        rtol = 1e-13
    )

    # Test the other way
    set!(latlon_field, (x, y, z) -> x)

    ConservativeRegridding.regrid!(cubed_sphere_vals, transpose(regridder), latlon_vals)

    @test isapprox(
        sum(abs, cubed_sphere_vals .* ConservativeRegridding.areas(GO.Spherical(), Trees.treeify(cubedsphere_space))),
        sum(abs, latlon_vals .* ConservativeRegridding.areas(GO.Spherical(), Trees.treeify(latlon_grid))),
        rtol = 1e-13
    )

    # TODO lat/lon shift is incorrect in this direction
    # Convert the vector of remapped values to a ClimaCore Field with one value per element
    field_remapped = Fields.zeros(cubedsphere_space)
    ClimaCoreExt.set_value_per_element!(field_remapped, cubed_sphere_vals)
    fig = Figure();
    ax = Axis(fig[1, 1])
    hm = fieldheatmap!(ax, field_remapped)
    Colorbar(fig[1, 2], hm)
    save("field_remapped.png", fig)

Plots

Source field: ClimaCore CubedSphere

Image

Dest field: Oceananigans TripolarGrid

Image

Dest field: back to ClimaCore CubedSphere

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions