From 40a06c5e2a4a95d5de6fcb32141fbc257e458dc1 Mon Sep 17 00:00:00 2001 From: Milan Date: Tue, 12 Sep 2023 16:09:16 -0400 Subject: [PATCH 1/3] pretty printing for structs --- src/SpeedyTransforms/aliasing.jl | 3 +++ src/SpeedyTransforms/show.jl | 14 ++++++++++---- src/dynamics/atmospheres.jl | 8 +++----- src/dynamics/constants.jl | 6 ++++++ src/dynamics/drag.jl | 8 +++----- src/dynamics/forcing.jl | 8 +++----- src/dynamics/horizontal_diffusion.jl | 13 ++++--------- src/dynamics/implicit.jl | 20 ++++++-------------- src/dynamics/initial_conditions.jl | 8 +++----- src/dynamics/models.jl | 18 +++++++++++++++++- src/dynamics/orography.jl | 25 ++++--------------------- src/dynamics/planets.jl | 8 +++----- src/dynamics/spectral_grid.jl | 22 +++++++++++++++------- src/dynamics/time_integration.jl | 8 +++----- src/dynamics/vertical_coordinates.jl | 8 ++++---- src/output/output.jl | 8 +++----- src/physics/pretty_printing.jl | 8 +++----- src/utility_functions.jl | 28 +++++++++++++++++++++++++++- 18 files changed, 120 insertions(+), 101 deletions(-) diff --git a/src/SpeedyTransforms/aliasing.jl b/src/SpeedyTransforms/aliasing.jl index c1a6fc3ae..1e97265a2 100644 --- a/src/SpeedyTransforms/aliasing.jl +++ b/src/SpeedyTransforms/aliasing.jl @@ -12,6 +12,9 @@ function RingGrids.get_nlat_half( trunc::Integer, return roundup_fft(ceil(Int,((1+dealiasing)*trunc+1)/4)) end +# inverse of get_nlat_half to reobtain dealiasing +get_dealiasing(trunc,nlat_half) = (4nlat_half)/(trunc+1) - 1 + """ $(TYPEDSIGNATURES) For the grid resolution parameter `nlat_half` (e.g. 24 for a 48-ring FullGaussianGrid) diff --git a/src/SpeedyTransforms/show.jl b/src/SpeedyTransforms/show.jl index dca08285b..64e618d27 100644 --- a/src/SpeedyTransforms/show.jl +++ b/src/SpeedyTransforms/show.jl @@ -19,8 +19,14 @@ function Base.show(io::IO,S::SpectralTransform{NF}) where NF s = S.recompute_legendre ? Base.summarysize(S.Λ) : Base.summarysize(S.Λs) s_str = prettymemory(s) - println(io,"$(typeof(S))(") - println(io," Spectral: T$mmax, $(lmax+1)x$(mmax+1) LowerTriangularMatrix{Complex{$NF}}") - println(io," Grid: $(RingGrids.get_nlat(Grid,nlat_half))-ring $Grid{$NF}") - print(io," Legendre: recompute polynomials $(S.recompute_legendre), $s_str)") + dealias = get_dealiasing(mmax,nlat_half) + truncations = ["cubic"] + truncation = truncations[clamp(floor(Int,dealias)+1,1,5)] + dealiasing = @sprintf("%.3g",dealias) + + println(io,"$(typeof(S)):") + println(io,"├ Spectral: T$mmax, $(lmax+1)x$(mmax+1) LowerTriangularMatrix{Complex{$NF}}") + println(io,"├ Grid: $(RingGrids.get_nlat(Grid,nlat_half))-ring $Grid{$NF}") + println(io,"├ Truncation: dealiasing = $dealiasing ($truncation)") + print(io,"└ Legendre: recompute polynomials $(S.recompute_legendre) ($s_str)") end diff --git a/src/dynamics/atmospheres.jl b/src/dynamics/atmospheres.jl index 7b62aa3d4..8f3424767 100644 --- a/src/dynamics/atmospheres.jl +++ b/src/dynamics/atmospheres.jl @@ -76,9 +76,7 @@ Base.@kwdef struct EarthAtmosphere <: AbstractAtmosphere end function Base.show(io::IO,atm::AbstractAtmosphere) - print(io,"$(typeof(atm)):") - for key in propertynames(atm) - val = getfield(atm,key) - print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(atm))") + keys = propertynames(atm) + print_fields(io,atm,keys) end \ No newline at end of file diff --git a/src/dynamics/constants.jl b/src/dynamics/constants.jl index b7eb98167..d63c42191 100644 --- a/src/dynamics/constants.jl +++ b/src/dynamics/constants.jl @@ -56,6 +56,12 @@ Base.@kwdef struct DynamicsConstants{NF<:AbstractFloat} <: AbstractDynamicsConst temp_ref_profile::Vector{NF} end +function Base.show(io::IO,C::DynamicsConstants) + println(io,"$(typeof(C)) <: AbstractDynamicsConstants") + keys = propertynames(C) + print_fields(io,C,keys) +end + """ $(TYPEDSIGNATURES) Generator function for a DynamicsConstants struct. diff --git a/src/dynamics/drag.jl b/src/dynamics/drag.jl index 49a168854..50589c68f 100644 --- a/src/dynamics/drag.jl +++ b/src/dynamics/drag.jl @@ -1,9 +1,7 @@ function Base.show(io::IO,F::AbstractDrag) - print(io,"$(typeof(F)) <: AbstractDrag:") - for key in propertynames(F) - val = getfield(F,key) - val isa AbstractArray || print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(F)) <: AbstractDrag") + keys = propertynames(F) + print_fields(io,F,keys) end ## NO DRAG diff --git a/src/dynamics/forcing.jl b/src/dynamics/forcing.jl index 7d357c4c7..81908b7e9 100644 --- a/src/dynamics/forcing.jl +++ b/src/dynamics/forcing.jl @@ -1,9 +1,7 @@ function Base.show(io::IO,F::AbstractForcing) - print(io,"$(typeof(F)) <: AbstractForcing:") - for key in propertynames(F) - val = getfield(F,key) - val isa AbstractArray || print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(F)) <: AbstractForcing") + keys = propertynames(F) + print_fields(io,F,keys) end ## NO FORCING diff --git a/src/dynamics/horizontal_diffusion.jl b/src/dynamics/horizontal_diffusion.jl index 55cc53d1d..bcf6584b7 100644 --- a/src/dynamics/horizontal_diffusion.jl +++ b/src/dynamics/horizontal_diffusion.jl @@ -61,15 +61,10 @@ function HyperDiffusion(spectral_grid::SpectralGrid;kwargs...) return HyperDiffusion{NF}(;trunc,nlev,kwargs...) end -function Base.show(io::IO,HD::HyperDiffusion) - print(io,"$(typeof(HD)):") - keys = (:trunc,:nlev,:power,:time_scale,:resolution_scaling,:power_stratosphere, - :tapering_σ,:adaptive,:vor_max,:adaptive_strength) - for key in keys - val = getfield(HD,key) - s = "\n $key::$(typeof(val)) = $val" - print(io,s) - end +function Base.show(io::IO,HD::HorizontalDiffusion) + println(io,"$(typeof(HD))") + keys = propertynames(HD) + print_fields(io,HD,keys,arrays=false) end """$(TYPEDSIGNATURES) diff --git a/src/dynamics/implicit.jl b/src/dynamics/implicit.jl index cb86e7359..83e7a5261 100644 --- a/src/dynamics/implicit.jl +++ b/src/dynamics/implicit.jl @@ -33,13 +33,9 @@ function ImplicitShallowWater(spectral_grid::SpectralGrid;kwargs...) end function Base.show(io::IO,I::ImplicitShallowWater) - print(io,"$(typeof(I)):") - keys = (:trunc,:α) - for key in keys - val = getfield(I,key) - s = "\n $key::$(typeof(val)) = $val" - print(io,s) - end + println(io,"$(typeof(I)) <: AbstractImplicit") + keys = propertynames(I) + print_fields(io,I,keys) end # function barrier to unpack the constants struct for shallow water @@ -192,13 +188,9 @@ function ImplicitPrimitiveEq(spectral_grid::SpectralGrid,kwargs...) end function Base.show(io::IO,I::ImplicitPrimitiveEq) - print(io,"$(typeof(I)):") - keys = (:trunc,:nlev,:α) - for key in keys - val = getfield(I,key) - s = "\n $key::$(typeof(val)) = $val" - print(io,s) - end + println(io,"$(typeof(I)) <: AbstractImplicit") + keys = propertynames(I) + print_fields(io,I,keys) end # function barrier to unpack the constants struct for primitive eq models diff --git a/src/dynamics/initial_conditions.jl b/src/dynamics/initial_conditions.jl index 9ff877090..2d03f243c 100644 --- a/src/dynamics/initial_conditions.jl +++ b/src/dynamics/initial_conditions.jl @@ -108,11 +108,9 @@ Base.@kwdef struct ZonalJet <: InitialConditions end function Base.show(io::IO,IC::InitialConditions) - print(io,"$(typeof(IC)) <: InitialConditions:") - for key in propertynames(IC) - val = getfield(IC,key) - print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(IC)) <: InitialConditions") + keys = propertynames(IC) + print_fields(io,IC,keys) end """ diff --git a/src/dynamics/models.jl b/src/dynamics/models.jl index d560dbeed..491cc713b 100644 --- a/src/dynamics/models.jl +++ b/src/dynamics/models.jl @@ -269,4 +269,20 @@ end Returns true if the model `M` has a prognostic variable `var_name`, false otherwise. The default fallback is that all variables are included. """ has(M::Type{<:ModelSetup}, var_name::Symbol) = var_name in (:vor, :div, :temp, :humid, :pres) -has(M::ModelSetup, var_name) = has(typeof(M), var_name) \ No newline at end of file +has(M::ModelSetup, var_name) = has(typeof(M), var_name) + +function Base.show(io::IO,M::ModelSetup) + println(io,"$(typeof(M))") + for key in propertynames(M)[1:end-1] + val = getfield(M,key) + println(io,"├ $key: $(typeof(val))") + end + println(io,"└ feedback: $(typeof(M.feedback))") +end + +function Base.show(io::IO,S::Simulation) + println(io,"$(typeof(S))") + println(io,"├ $(typeof(S.model))") + println(io,"├ $(typeof(S.prognostic_variables))") + print(io, "└ $(typeof(S.diagnostic_variables))") +end \ No newline at end of file diff --git a/src/dynamics/orography.jl b/src/dynamics/orography.jl index 8e0f18779..d747015fd 100644 --- a/src/dynamics/orography.jl +++ b/src/dynamics/orography.jl @@ -18,8 +18,10 @@ function NoOrography(spectral_grid::SpectralGrid) return NoOrography{NF,Grid{NF}}(orography,geopot_surf) end -function Base.show(io::IO,orog::NoOrography) - print(io,"$(typeof(orog))") +function Base.show(io::IO,orog::AbstractOrography) + println(io,"$(typeof(IC)) <: AbstractOrography") + keys = propertynames(IC) + print_fields(io,IC,keys) end # no further initialization needed @@ -44,15 +46,6 @@ Base.@kwdef struct ZonalRidge{NF<:AbstractFloat,Grid<:AbstractGrid{NF}} <: Abstr geopot_surf::LowerTriangularMatrix{Complex{NF}} end -function Base.show(io::IO,orog::ZonalRidge) - print(io,"$(typeof(orog)):") - keys = (:η₀,:u₀) - for key in keys - val = getfield(orog,key) - print(io,"\n $key::$(typeof(val)) = $val") - end -end - """ $(TYPEDSIGNATURES) Generator function pulling the resolution information from `spectral_grid`.""" @@ -146,16 +139,6 @@ function EarthOrography(spectral_grid::SpectralGrid;kwargs...) return EarthOrography{NF,Grid{NF}}(;orography,geopot_surf,kwargs...) end -function Base.show(io::IO,orog::EarthOrography) - print(io,"$(typeof(orog)):") - keys = (:path,:file,:scale,:smoothing,:smoothing_power, - :smoothing_strength,:smoothing_truncation) - for key in keys - val = getfield(orog,key) - print(io,"\n $key::$(typeof(val)) = $val") - end -end - """ $(TYPEDSIGNATURES) Initialize the arrays `orography`,`geopot_surf` in `orog` by reading the diff --git a/src/dynamics/planets.jl b/src/dynamics/planets.jl index 353a78800..a90559f67 100644 --- a/src/dynamics/planets.jl +++ b/src/dynamics/planets.jl @@ -33,9 +33,7 @@ Base.@kwdef struct Earth <: AbstractPlanet end function Base.show(io::IO,planet::AbstractPlanet) - print(io,"$(typeof(planet)):") - for key in propertynames(planet) - val = getfield(planet,key) - print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(planet)) <: AbstractPlanet") + keys = propertynames(planet) + print_fields(io,planet,keys) end \ No newline at end of file diff --git a/src/dynamics/spectral_grid.jl b/src/dynamics/spectral_grid.jl index 8631e69a6..37f8d8829 100644 --- a/src/dynamics/spectral_grid.jl +++ b/src/dynamics/spectral_grid.jl @@ -58,14 +58,22 @@ SpectralGrid(Grid::Type{<:AbstractGrid};kwargs...) = SpectralGrid(;Grid,kwargs.. SpectralGrid(NF::Type{<:AbstractFloat},Grid::Type{<:AbstractGrid};kwargs...) = SpectralGrid(;NF,Grid,kwargs...) function Base.show(io::IO,SG::SpectralGrid) - (;NF,trunc,Grid,dealiasing,radius,nlat_half,npoints,nlev,vertical_coordinates) = SG - truncation = if dealiasing < 2 "linear" elseif dealiasing < 3 "quadratic" else "cubic" end - res = sqrt(4π*radius^2/npoints)/1000 # in [km] + (;NF,trunc,Grid,radius,nlat_half,npoints,nlev,vertical_coordinates) = SG + # truncation = if dealiasing < 2 "linear" elseif dealiasing < 3 "quadratic" else "cubic" end + + # resolution information + res_ave = sqrt(4π*radius^2/npoints)/1000 # in [km] + res_eq_x = 2π*radius/RingGrids.get_nlon_max(Grid,nlat_half)/1000 + lat = get_lat(Grid,nlat_half) + res_eq_y = (lat[nlat_half] - lat[nlat_half+1])*radius/1000 + + s(x) = @sprintf("%.3g",x) + println(io,"$(typeof(SG)):") - println(io," Spectral: T$trunc LowerTriangularMatrix{Complex{$NF}}, radius = $radius m") - println(io," Grid: $npoints-element, $(get_nlat(Grid,nlat_half))-ring $Grid{$NF} ($truncation)") - println(io," Resolution: $(@sprintf("%.3g",res))km (average)") - print(io," Vertical: $nlev-level $(typeof(vertical_coordinates))") + println(io,"├ Spectral: T$trunc LowerTriangularMatrix{Complex{$NF}}, radius = $radius m") + println(io,"├ Grid: $(get_nlat(Grid,nlat_half))-ring $Grid{$NF}, $npoints grid points") + println(io,"├ Resolution: $(s(res_ave))km (average), $(s(res_eq_x))km × $(s(res_eq_y))km (Equator)") + print(io,"└ Vertical: $nlev-level $(typeof(vertical_coordinates))") end """ diff --git a/src/dynamics/time_integration.jl b/src/dynamics/time_integration.jl index a56234770..3d0fc4207 100644 --- a/src/dynamics/time_integration.jl +++ b/src/dynamics/time_integration.jl @@ -44,11 +44,9 @@ function Leapfrog(spectral_grid::SpectralGrid;kwargs...) end function Base.show(io::IO,L::Leapfrog) - print(io,"$(typeof(L)):") - for key = propertynames(L) - val = getfield(L,key) - print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(L)) <: TimeStepper") + keys = propertynames(L) + print_fields(io,L,keys) end """ diff --git a/src/dynamics/vertical_coordinates.jl b/src/dynamics/vertical_coordinates.jl index 7c3ce76ac..14558f41c 100644 --- a/src/dynamics/vertical_coordinates.jl +++ b/src/dynamics/vertical_coordinates.jl @@ -15,15 +15,15 @@ SigmaCoordinates(σ_half::AbstractVector) = SigmaCoordinates(nlev=length(σ_half SigmaCoordinates(σ_half::AbstractRange) = SigmaCoordinates(collect(σ_half)) function Base.show(io::IO,σ::SigmaCoordinates) - println("$(σ.nlev)-level SigmaCoordinates:") + println("$(σ.nlev)-level SigmaCoordinates") nchars = length(string(σ.nlev)) format = Printf.Format("%$(nchars)d") for k=1:σ.nlev - println(" k=",Printf.format(format,k-1),".5 -- ",@sprintf("%1.4f",σ.σ_half[k])) + println("├─ ", @sprintf("%1.4f",σ.σ_half[k])," k = ",Printf.format(format,k-1),".5") σk = (σ.σ_half[k] + σ.σ_half[k+1])/2 - println(" k=",Printf.format(format,k)," × ",@sprintf("%1.4f",σk)) + println("│× ",@sprintf("%1.4f",σk)," k = ",Printf.format(format,k)) end - print(" k=",Printf.format(format,σ.nlev),".5 -- ",@sprintf("%1.4f",σ.σ_half[end])) + print("└─ ",@sprintf("%1.4f",σ.σ_half[end])," k = ",Printf.format(format,σ.nlev),".5") end """Coefficients of the generalised logistic function to describe the vertical coordinate. diff --git a/src/output/output.jl b/src/output/output.jl index 37d9d2e97..b6fcbbbf1 100644 --- a/src/output/output.jl +++ b/src/output/output.jl @@ -15,11 +15,9 @@ Base.@kwdef struct Keepbits end function Base.show(io::IO,K::Keepbits) - print(io,"$(typeof(K)):") - for key in propertynames(K) - val = getfield(K,key) - print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(K))") + keys = propertynames(K) + print_fields(io,K,keys) end # default number format for output diff --git a/src/physics/pretty_printing.jl b/src/physics/pretty_printing.jl index 0f8f59005..3b26f32c2 100644 --- a/src/physics/pretty_printing.jl +++ b/src/physics/pretty_printing.jl @@ -1,8 +1,6 @@ # print all fields with type <: Number function Base.show(io::IO,P::AbstractParameterization) - print(io,"$(typeof(P)):") - for key in propertynames(P) - val = getfield(P,key) - val isa Number && print(io,"\n $key::$(typeof(val)) = $val") - end + println(io,"$(typeof(P)) <: $(supertype(typeof(P)))") + keys = propertynames(P) + print_fields(io,P,keys) end \ No newline at end of file diff --git a/src/utility_functions.jl b/src/utility_functions.jl index ad2e48fbc..8fa12de92 100644 --- a/src/utility_functions.jl +++ b/src/utility_functions.jl @@ -70,4 +70,30 @@ end A = nans(dims...) Allocate A::Array{Float64} with NaNs.""" -nans(dims...) = nans(Float64,dims...) \ No newline at end of file +nans(dims...) = nans(Float64,dims...) + +""" +$(TYPEDSIGNATURES) +Prints to `io` all fields of a struct `A` identified by their +`keys`.""" +function print_fields(io::IO,A,keys;arrays::Bool=false) + keys_filtered = arrays ? keys : filter(key -> ~(getfield(A,key) isa AbstractArray),keys) + n = length(keys_filtered) + filtered = n < length(keys) + for (i,key) in enumerate(keys_filtered) + last = (i == n) & ~filtered + key = keys[i] + val = getfield(A,key) + ~last ? println(io,"├ $key::$(typeof(val)) = $val") : + print(io, "└ $key::$(typeof(val)) = $val") + end + if filtered # add the names of arrays + s = "└── arrays: " + for key in keys + if ~(key in keys_filtered) + s *= "$key, " + end + end + print(io,s[1:end-2]) # remove last ", " + end +end \ No newline at end of file From 5fa817d22cf22b1415c4b3c5e2d84966e087c2fe Mon Sep 17 00:00:00 2001 From: Milan Date: Tue, 12 Sep 2023 17:07:11 -0400 Subject: [PATCH 2/3] orography show bug --- src/dynamics/orography.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dynamics/orography.jl b/src/dynamics/orography.jl index d747015fd..5dbf331ff 100644 --- a/src/dynamics/orography.jl +++ b/src/dynamics/orography.jl @@ -19,9 +19,9 @@ function NoOrography(spectral_grid::SpectralGrid) end function Base.show(io::IO,orog::AbstractOrography) - println(io,"$(typeof(IC)) <: AbstractOrography") - keys = propertynames(IC) - print_fields(io,IC,keys) + println(io,"$(typeof(orog)) <: AbstractOrography") + keys = propertynames(orog) + print_fields(io,orog,keys) end # no further initialization needed From 3ad6cdb7f6c3c6a678e7f34383aaac941d0df95c Mon Sep 17 00:00:00 2001 From: Milan Date: Wed, 13 Sep 2023 10:17:37 -0400 Subject: [PATCH 3/3] avoid invalid string index with prevind, findlast --- src/utility_functions.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utility_functions.jl b/src/utility_functions.jl index 8fa12de92..e65a0b9af 100644 --- a/src/utility_functions.jl +++ b/src/utility_functions.jl @@ -94,6 +94,9 @@ function print_fields(io::IO,A,keys;arrays::Bool=false) s *= "$key, " end end - print(io,s[1:end-2]) # remove last ", " + + # remove last ", " + s_without_comma = s[1:prevind(s,findlast(==(','), s))] + print(io,s_without_comma) end end \ No newline at end of file