| 
1 | 1 | import Oceananigans as OC  | 
2 | 2 | import ClimaOcean as CO  | 
 | 3 | +import ClimaAtmos as CA  | 
3 | 4 | import ClimaCoupler: Checkpointer, FieldExchanger, FluxCalculator, Interfacer, Utilities  | 
4 | 5 | import ClimaComms  | 
5 | 6 | import ClimaCore as CC  | 
@@ -46,6 +47,9 @@ function OceananigansSimulation(  | 
46 | 47 |     output_dir,  | 
47 | 48 |     comms_ctx = ClimaComms.context(),  | 
48 | 49 | )  | 
 | 50 | +    # using Dates  | 
 | 51 | +    # start_date = Dates.DateTime(2008)  | 
 | 52 | +    # stop_date = Dates.DateTime(2008, 1, 2)  | 
49 | 53 |     arch = comms_ctx.device isa ClimaComms.CUDADevice ? OC.GPU() : OC.CPU()  | 
50 | 54 | 
 
  | 
51 | 55 |     # Retrieve EN4 data (monthly)  | 
@@ -102,13 +106,84 @@ function OceananigansSimulation(  | 
102 | 106 |     OC.set!(ocean.model, T = en4_temperature[1], S = en4_salinity[1])  | 
103 | 107 | 
 
  | 
104 | 108 |     # Construct a remapper from the exchange grid to `Center, Center` fields  | 
105 |  | -    long_cc = OC.λnodes(grid, OC.Center(), OC.Center(), OC.Center())  | 
106 |  | -    lat_cc = OC.φnodes(grid, OC.Center(), OC.Center(), OC.Center())  | 
 | 109 | + | 
 | 110 | +    # Tripolar to cubed sphere (fails currently)  | 
 | 111 | +    # long_oc = OC.λnodes(grid, OC.Center(), OC.Center(), OC.Center())  | 
 | 112 | +    # lat_oc = OC.φnodes(grid, OC.Center(), OC.Center(), OC.Center())  | 
 | 113 | + | 
 | 114 | +    T = OC.CenterField(grid) # field on tripolar grid  | 
 | 115 | +    OC.set!(T, en4_temperature[1])  | 
 | 116 | +    coords_tripolar, _ = XESMF.extract_xesmf_coordinates_structure(T, T)  | 
107 | 117 | 
 
  | 
108 | 118 |     # Create a 2D matrix containing each lat/long combination as a LatLongPoint  | 
109 | 119 |     # Note this must be done on CPU since the CC.Remapper module is not GPU-compatible  | 
110 |  | -    target_points_cc = Array(CC.Geometry.LatLongPoint.(lat_cc, long_cc))  | 
 | 120 | +    # target_points_oc = Array(CC.Geometry.LatLongPoint.(lat_oc, long_oc))  | 
 | 121 | + | 
 | 122 | +    # TODO double check these coords are on centers, get lat/lon bounds for each element  | 
 | 123 | +    # boundary_space = axes(area_fraction)  | 
 | 124 | +    boundary_space = CC.CommonSpaces.CubedSphereSpace(  | 
 | 125 | +        Float32;  | 
 | 126 | +        radius = 1.0,  | 
 | 127 | +        n_quad_points = 2,  | 
 | 128 | +        h_elem = 10,  | 
 | 129 | +    )  | 
 | 130 | +    boundary_coords = CC.Fields.coordinate_field(boundary_space)  | 
 | 131 | +    boundary_lat_arr = CC.Fields.field2array(boundary_coords.lat)  | 
 | 132 | +    boundary_long_arr = CC.Fields.field2array(boundary_coords.long)  | 
 | 133 | +    coords_cubedsphere = Dict("lat" => boundary_lat_arr, "lon" => boundary_long_arr)  | 
 | 134 | + | 
 | 135 | +    regridder_tripolar_to_cubedsphere =  | 
 | 136 | +        XESMF.Regridder(coords_cubedsphere, coords_tripolar; method = "conservative")  | 
 | 137 | +    regridder_cubedsphere_to_tripolar =  | 
 | 138 | +        XESMF.Regridder(coords_tripolar, coords_cubedsphere; method = "conservative")  | 
 | 139 | + | 
 | 140 | +    # Tripolar to LatLon  | 
 | 141 | +    T = OC.CenterField(grid) # field on tripolar grid  | 
 | 142 | +    OC.set!(T, en4_temperature[1])  | 
 | 143 | + | 
 | 144 | +    grid_latlon = OC.LatitudeLongitudeGrid(  | 
 | 145 | +        arch;  | 
 | 146 | +        size = (Nx, Ny, Nz),  | 
 | 147 | +        longitude = (0, 360),  | 
 | 148 | +        latitude = (-81, 90),  | 
 | 149 | +        z,  | 
 | 150 | +    )  | 
 | 151 | +    field_latlon = OC.CenterField(grid_latlon)  | 
 | 152 | +    remapper_tripolar_to_latlon = XESMF.Regridder(T, field_latlon; method = "conservative")  | 
 | 153 | +    remapper_tripolar_to_latlon(  | 
 | 154 | +        vec(OC.interior(field_latlon, :, :, Nz)),  | 
 | 155 | +        vec(OC.interior(T, :, :, Nz)),  | 
 | 156 | +    )  | 
 | 157 | +    OC.fill_halo_regions!(field_latlon)  | 
 | 158 | +    # heatmap(field_latlon) # using GeoMakie, using CairoMakie  | 
 | 159 | + | 
 | 160 | +    # LatLon to cubed sphere  | 
 | 161 | +    boundary_space = CC.CommonSpaces.CubedSphereSpace(  | 
 | 162 | +        Float32;  | 
 | 163 | +        radius = 1.0,  | 
 | 164 | +        n_quad_points = 2,  | 
 | 165 | +        h_elem = 10,  | 
 | 166 | +    )  | 
 | 167 | +    field_cubedsphere = Interfacer.remap(field_latlon, boundary_space)  | 
 | 168 | +    # fieldheatmap(field_cubedsphere) # using ClimaCoreMakie  | 
 | 169 | + | 
 | 170 | +    # Cubed sphere to LatLon  | 
 | 171 | +    long_oc = OC.λnodes(grid_latlon, OC.Center(), OC.Center(), OC.Center())  | 
 | 172 | +    lat_oc = OC.φnodes(grid_latlon, OC.Center(), OC.Center(), OC.Center())  | 
 | 173 | +    long_oc = reshape(long_oc, length(long_oc), 1)  | 
 | 174 | +    lat_oc = reshape(lat_oc, 1, length(lat_oc))  | 
 | 175 | +    target_points_oc = @. CC.Geometry.LatLongPoint(lat_oc, long_oc)  | 
 | 176 | + | 
 | 177 | +    remapper_cubedsphere_to_latlon = CC.Remapping.Remapper(boundary_space, target_points_oc)  | 
 | 178 | +    field_cubedsphere = CC.Fields.zeros(boundary_space)  | 
 | 179 | +    CC.Remapping.interpolate!(  | 
 | 180 | +        field_cubedsphere,  | 
 | 181 | +        remapper_cubedsphere_to_latlon,  | 
 | 182 | +        field_latlon,  | 
 | 183 | +    )  | 
 | 184 | + | 
111 | 185 | 
 
  | 
 | 186 | +    # Previous remapper for LatLon  | 
112 | 187 |     if pkgversion(CC) >= v"0.14.34"  | 
113 | 188 |         remapper_cc = CC.Remapping.Remapper(axes(area_fraction), target_points_cc)  | 
114 | 189 |     else  | 
@@ -194,14 +269,14 @@ Interfacer.step!(sim::OceananigansSimulation, t) =  | 
194 | 269 | 
 
  | 
195 | 270 | # We always want the surface, so we always set zero(pt.lat) for z  | 
196 | 271 | """  | 
197 |  | -    to_node(pt::CA.ClimaCore.Geometry.LatLongPoint)  | 
 | 272 | +    to_node(pt::CCGeometry.LatLongPoint)  | 
198 | 273 | 
  | 
199 | 274 | Transform `LatLongPoint` into a tuple (long, lat, 0), where the 0 is needed because we only  | 
200 | 275 | care about the surface.  | 
201 | 276 | """  | 
202 |  | -@inline to_node(pt::CA.ClimaCore.Geometry.LatLongPoint) = pt.long, pt.lat, zero(pt.lat)  | 
 | 277 | +@inline to_node(pt::CC.Geometry.LatLongPoint) = pt.long, pt.lat, zero(pt.lat)  | 
203 | 278 | # This next one is needed if we have "LevelGrid"  | 
204 |  | -@inline to_node(pt::CA.ClimaCore.Geometry.LatLongZPoint) = pt.long, pt.lat, zero(pt.lat)  | 
 | 279 | +@inline to_node(pt::CC.Geometry.LatLongZPoint) = pt.long, pt.lat, zero(pt.lat)  | 
205 | 280 | 
 
  | 
206 | 281 | """  | 
207 | 282 |     map_interpolate(points, oc_field::OC.Field)  | 
 | 
0 commit comments