@@ -112,22 +112,7 @@ function debug(cs_fields::CC.Fields.Field, dir, cs_fields_ref = nothing)
112112 if field_index <= length (field_names)
113113 field_name = field_names[field_index]
114114 field = getproperty (cs_fields, field_name)
115-
116- # Copy field onto cpu space if necessary
117- cpu_field = CC. to_cpu (field)
118-
119- # ClimaCoreMakie doesn't support NaNs/Infs, so we substitute them with 100max
120- FT = CC. Spaces. undertype (axes (cpu_field))
121- isinvalid = (x) -> isnan (x) || isinf (x)
122-
123- field_valid_min, field_valid_max = extrema (map (x -> isinvalid (x) ? FT (0 ) : x, parent (cpu_field)))
124- map! (x -> isinvalid (x) ? 100 field_valid_max : x, parent (cpu_field), parent (cpu_field))
125- colorrange =
126- isapprox (field_valid_min, field_valid_max) ? (field_valid_min - 1 , field_valid_max + 1 ) :
127- (field_valid_min, field_valid_max)
128- ax = Makie. Axis (fig[i, j * 2 - 1 ], title = string (field_name) * print_extrema (field))
129- hm = ClimaCoreMakie. fieldheatmap! (ax, cpu_field, colorrange = colorrange)
130- Makie. Colorbar (fig[i, j * 2 ], hm)
115+ _heatmap_cc_field! (fig, field, i, j, field_name)
131116 end
132117 end
133118 Makie. save (joinpath (dir, " debug_coupler.png" ), fig)
@@ -139,27 +124,7 @@ function debug(cs_fields::CC.Fields.Field, dir, cs_fields_ref = nothing)
139124 if field_index <= length (field_names)
140125 field_name = field_names[field_index]
141126 field = getproperty (cs_fields, field_name)
142- # Copy field onto cpu space if necessary
143-
144- cpu_field = CC. to_cpu (field)
145-
146- # ClimaCoreMakie doesn't support NaNs/Infs, so we substitute them with 100max
147- FT = CC. Spaces. undertype (axes (cpu_field))
148- isinvalid = (x) -> isnan (x) || isinf (x)
149-
150- field_valid_min, field_valid_max = extrema (map (x -> isinvalid (x) ? FT (0 ) : x, parent (cpu_field)))
151- map! (x -> isinvalid (x) ? 100 field_valid_max : x, parent (cpu_field), parent (cpu_field))
152- colorrange =
153- isapprox (field_valid_min, field_valid_max) ? (field_valid_min - 1 , field_valid_max + 1 ) :
154- (field_valid_min, field_valid_max)
155-
156- ax = Makie. Axis (fig[i, j * 2 - 1 ], title = string (field_name) * print_extrema (field))
157- hm = ClimaCoreMakie. fieldheatmap! (
158- ax,
159- cpu_field .- getproperty (cs_fields_ref, field_name),
160- colorrange = colorrange,
161- )
162- Makie. Colorbar (fig[i, j * 2 ], hm)
127+ _heatmap_cc_field! (fig, field, i, j, field_name)
163128 end
164129 end
165130 Makie. save (joinpath (dir, " debug_coupler_anomalies.png" ), fig)
@@ -190,24 +155,7 @@ function debug(sim::Interfacer.ComponentModelSimulation, dir)
190155 hm = CairoMakie. heatmap! (ax, view (field, :, :, grid. Nz))
191156 Makie. Colorbar (fig[i, j * 2 ], hm)
192157 elseif field isa CC. Fields. Field
193- # Copy field onto cpu space if necessary
194- cpu_field = CC. to_cpu (field)
195- if cpu_field isa CC. Fields. ExtrudedCubedSphereSpectralElementField3D
196- cpu_field = CC. Fields. level (cpu_field, 1 )
197- end
198- FT = CC. Spaces. undertype (axes (cpu_field))
199- vals = CC. Fields. field_values (cpu_field)
200- isinvalid = (x) -> isnan (x) || isinf (x)
201- # ClimaCoreMakie doesn't support NaNs or Infs, so we make them
202- # stand out by replacing them with 100max
203-
204- field_valid_min, field_valid_max = extrema (map (x -> isinvalid (x) ? FT (0 ) : x, parent (cpu_field)))
205- map! (x -> isinvalid (x) ? 100 field_max : x, parent (cpu_field), parent (cpu_field))
206- colorrange =
207- isapprox (field_valid_min, field_valid_max) ? (field_valid_min - 1 , field_valid_max + 1 ) :
208- (field_valid_min, field_valid_max)
209- hm = ClimaCoreMakie. fieldheatmap! (ax, cpu_field, colorrange = colorrange)
210- Makie. Colorbar (fig[i, j * 2 ], hm)
158+ _heatmap_cc_field! (fig, field, i, j, field_name)
211159 elseif field isa AbstractArray
212160 lin = Makie. lines! (ax, Array (field))
213161 end
@@ -216,6 +164,40 @@ function debug(sim::Interfacer.ComponentModelSimulation, dir)
216164 Makie. save (joinpath (dir, " debug_$(nameof (sim)) .png" ), fig)
217165end
218166
167+ """
168+ _heatmap_cc_field!(fig, field::CC.Fields.Field, i, j, field_name)
169+
170+ Helper function to plot a heatmap of a ClimaCore field in the given figure at position (i, j).
171+ If the field is constant, skip plotting it to avoid heatmap errors.
172+ """
173+ function _heatmap_cc_field! (fig, field:: CC.Fields.Field , i, j, field_name)
174+ # Copy field onto cpu space if necessary
175+ cpu_field = CC. to_cpu (field)
176+ if cpu_field isa CC. Fields. ExtrudedCubedSphereSpectralElementField3D
177+ cpu_field = CC. Fields. level (cpu_field, 1 )
178+ end
179+
180+ # ClimaCoreMakie doesn't support NaNs/Infs, so we substitute them with 100max
181+ FT = CC. Spaces. undertype (axes (cpu_field))
182+ isinvalid = (x) -> isnan (x) || isinf (x)
183+ field_valid_min, field_valid_max = extrema (map (x -> isinvalid (x) ? FT (0 ) : x, parent (cpu_field)))
184+ map! (x -> isinvalid (x) ? 100 field_valid_max : x, parent (cpu_field), parent (cpu_field))
185+
186+ # If the values are too small, `isapprox` can't be computed accurately because of floating point precision issues.
187+ is_toosmall = (x) -> log10 (abs (x)) < log10 (floatmin (Float64)) / 2
188+
189+ # If the field is constant, skip plotting it to avoid heatmap errors.
190+ if isapprox (field_valid_min, field_valid_max) || (is_toosmall (field_valid_min) && is_toosmall (field_valid_max))
191+ ax = Makie. Axis (fig[i, j * 2 - 1 ], title = string (field_name) * print_extrema (cpu_field))
192+ else
193+ colorrange = (field_valid_min, field_valid_max)
194+ ax = Makie. Axis (fig[i, j * 2 - 1 ], title = string (field_name) * print_extrema (cpu_field))
195+ hm = ClimaCoreMakie. fieldheatmap! (ax, cpu_field, colorrange = colorrange)
196+ Makie. Colorbar (fig[i, j * 2 ], hm)
197+ end
198+ return nothing
199+ end
200+
219201"""
220202 print_extrema(field::CC.Fields.Field)
221203
0 commit comments