Skip to content

rft: improve parameter constructors#700

Merged
haakon-e merged 2 commits intomainfrom
he/rft-parameter-structs
Mar 19, 2026
Merged

rft: improve parameter constructors#700
haakon-e merged 2 commits intomainfrom
he/rft-parameter-structs

Conversation

@haakon-e
Copy link
Copy Markdown
Member

@haakon-e haakon-e commented Mar 11, 2026

Summary

This pull request refactors the type hierarchy and usage of parameterized types throughout the codebase to simplify type signatures and improve code clarity. The main change is the removal of the floating-point type parameter (FT) from many struct definitions and function signatures, in favor of storing the floating-point type only where necessary (typically as fields rather than in the type itself). This results in shorter, more readable type signatures and reduces the need for repeated type parameters in function definitions. Additionally, some keyword argument usage is improved for clarity.

The PR is organized with two commits:

  • The first introduces the struct improvements
  • The second contains the show.jl methods

Content

Type System Simplification and Refactoring:

  • The abstract ParametersType no longer has the FT field in type space. For backward compatibility, the eltype function remains, and recursively looks up the first argument of the concrete struct. Within microphysics parameterizations, FT should instead be fetched from the state.
  • Relatedly, structs that do not explicitly store elements of type FT, no longer carry this information in type space.

API and Usability Improvements:

  • Construction of SB2006 objects in plotting scripts now uses keyword arguments for clarity (is_limited = false), replacing positional boolean arguments. [1] [2] [3]

Struct printing

  • Added generic show methods (see show.jl) that structs can use to enable pretty-printing of their contents.
  • By default, all parameter structs (i.e. subtypes of ParametersType) with more than 7 elements will be verbosely printed, and otherwise tersely printed. Printing is recursive, as the example below illustrates.
  • Optionally, you can attach units to elements of the structure for more informative printing.
julia> import CloudMicrophysics.Parameters as CMP

julia> CMP.SB2006(Float32)
SB2006
├─ pdf_c: CloudParticlePDF_SB2006(νc = 1.0f0, μc = 1.0f0, xc_min = 4.2f-15, xc_max = 2.6f-10, ρw = 1000.0f0)
├─ pdf_r: RainParticlePDF_SB2006_limited
│  ├─ νr = -0.6666667
│  ├─ μr = 0.33333334
│  ├─ xr_min = 2.6e-10
│  ├─ xr_max = 5.0e-6
│  ├─ N0_min = 250000.0
│  ├─ N0_max = 2.0e7
│  ├─ λ_min = 1000.0
│  ├─ λ_max = 10000.0
│  ├─ ρw = 1000.0
│  └─ ρ0 = 1.225
├─ acnv: AcnvSB2006(kcc = 4.44f9, x_star = 2.6f-10, ρ0 = 1.225f0, A = 400.0f0, a = 0.7f0, b = 3.0f0)
├─ accr: AccrSB2006(kcr = 5.25f0, τ0 = 5.0f-5, ρ0 = 1.225f0, c = 4.0f0)
├─ self: SelfColSB2006(krr = 7.12f0, κrr = 60.7f0, d = -5.0f0)
├─ brek: BreakupSB2006(Deq = 0.0009f0, Dr_th = 0.00035f0, kbr = 1000.0f0, κbr = 2300.0f0)
├─ evap: EvaporationSB2006(av = 0.78f0, bv = 0.308f0, α = 159.0f0, β = 0.266f0, ρ0 = 1.225f0)
└─ numadj: NumberAdjustmentHorn2012(τ = 100.0f0)

julia> CMP.CloudLiquid(Float32)  # the fields for this struct has units defined
CloudLiquid(τ_relax = 10.0f0 [s], ρw = 1000.0f0 [kg/m³], r_eff = 1.4f-5 [m], N_0 = 5.0f8 [1/m³])

Other Minor Improvements:

  • Remove Base. prefix from @kwdef macro as it is directly available.

@haakon-e
Copy link
Copy Markdown
Member Author

haakon-e commented Mar 11, 2026

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 71.25000% with 92 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.28%. Comparing base (610618b) to head (c909c1a).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #700      +/-   ##
==========================================
- Coverage   94.98%   92.28%   -2.70%     
==========================================
  Files          53       54       +1     
  Lines        2371     2269     -102     
==========================================
- Hits         2252     2094     -158     
- Misses        119      175      +56     
Components Coverage Δ
src 93.28% <71.25%> (-2.77%) ⬇️
ext 69.47% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch from 6b4ed07 to 9215200 Compare March 11, 2026 22:47
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch 4 times, most recently from 1f4a917 to 7f380dc Compare March 12, 2026 17:40
Copy link
Copy Markdown
Member Author

@haakon-e haakon-e left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments to assist review

Comment on lines +435 to +439
# Developer docs

```@autodocs
Modules = [ShowMethods]
```
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional method signatures can be viewed in the doc preview

CMP.ParametersP3{Float64}
CMP.ParametersP3(::Float64)
CMP.ParametersP3(::Parameters.CP.ParamDict)
CMP.ParametersP3
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got some doc errors with this, so simplifying for now, will return improve this in a later PR



# Temporary fallback until we stop checking eltype from the parameters
Base.eltype(p::ParametersType) = fieldcount(typeof(p)) > 0 ? eltype(getfield(p, 1)) : Any
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will remove this method in a future breaking PR

Comment on lines -35 to -37
H2SO4SolutionParameters(::Type{FT}) where {FT <: AbstractFloat} =
H2SO4SolutionParameters(CP.create_toml_dict(FT))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitions such as this is moved to src/parameters/Parameters.jl, which defines this for all subtypes of ParametersType

Comment on lines -52 to +49
FT = CP.float_type(td)
return H2SO4SolutionParameters{FT}(; parameters...)
return H2SO4SolutionParameters(; parameters...)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed these type flags where I could find them as they're unnecessary since all fields returned from CP.get_parameter_values have uniform FT type already.

# Fields
$(DocStringExtensions.FIELDS)
"""
Base.@kwdef struct H2SO4SolutionParameters{FT} <: ParametersType{FT}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kwdef is always available, no need for Base. prefix. Did a search and replace to remove them.

### Create methods that enables the creation of parameter types with a given float type
### for all subtypes of `ParametersType`
### e.g. `Microphysics1MParams(Float32)`
import InteractiveUtils
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InteractiveUtils is already shipped with the julia standard library, so this is not in reality a new dependency. We do need to add it to the Project.toml file though.

return concrete_types
end
for T in get_concrete_subtypes(ParametersType)
@eval (::Type{$T})(::Type{FT}; kw...) where {FT} = $T(CP.create_toml_dict(FT); kw...)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference: The reason I needed to define these in a loop over concrete subtypes of ParametersType as opposed to simply defining the method

(::Type{T}(::Type{FT}; kw...) where {T <: ParametersType, FT} = 
    T(CP.create_toml_dict(FT); kw...)

is that this results in Aqua/Test complaining about ambiguous method definitions for structs with one field. For example,

@kwdef struct NumberAdjustmentHorn2012{FT} <: ParametersType
    "Number concentration adjustment timescale [s]"
    τ::FT
end

defines the method

(::Type{NumberAdjustmentHorn2012})(τ::Any)

Here, the struct is more concrete, while the argument is less concrete. With the method above, the struct is less concrete while the argument (::Type{FT}) is more concrete. In practice, it appears that julia is able to resolve this apparent ambiguity, so it may be a bug in Test/Aqua.

The @eval loop instead defines

(::Type{NumberAdjustmentHorn2012})(::Type{FT}) where {FT} = ...

for every subtype of ParametersType, circumventing this potential method ambiguity problem.

@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch 2 times, most recently from e0cb5b6 to 35f69b6 Compare March 12, 2026 20:00
@haakon-e haakon-e requested a review from trontrytel March 12, 2026 20:13
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch from 35f69b6 to 62241f0 Compare March 12, 2026 21:03
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch 2 times, most recently from 0459d67 to 3bc6212 Compare March 12, 2026 22:53
@trontrytel trontrytel added the Needs review Please review my pull request label Mar 13, 2026
@trontrytel
Copy link
Copy Markdown
Member

Amazing! Thank you so much for carrying out for the whole repo.

@trontrytel trontrytel self-requested a review March 13, 2026 22:28
Copy link
Copy Markdown
Member

@trontrytel trontrytel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

I was wondering if we can replace some of the parameter printing here: https://clima.github.io/CloudMicrophysics.jl/dev/guides/literated/Parameters/

with the new show. But I can also do it in a separate PR

@trontrytel trontrytel removed the Needs review Please review my pull request label Mar 13, 2026
@trontrytel
Copy link
Copy Markdown
Member

Is this a breaking release from ClimaAtmos point of view in any way?

@trontrytel
Copy link
Copy Markdown
Member

Closes #573

@haakon-e haakon-e changed the base branch from main to he/ci-update-tests-juliaformatter March 18, 2026 20:35
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch from be4ca3d to 6fa6924 Compare March 18, 2026 20:35
Base automatically changed from he/ci-update-tests-juliaformatter to aj/julia_v12 March 18, 2026 20:52
Base automatically changed from aj/julia_v12 to main March 18, 2026 20:53
- add constructor using float type (e.g. Float32)
    for all param structs
- remove explicit type declarations where not needed
- clean up some constructors
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch from 6fa6924 to 1080882 Compare March 18, 2026 20:57
@haakon-e haakon-e force-pushed the he/rft-parameter-structs branch from 1080882 to c909c1a Compare March 18, 2026 21:19
@haakon-e
Copy link
Copy Markdown
Member Author

Thank you!

I was wondering if we can replace some of the parameter printing here: https://clima.github.io/CloudMicrophysics.jl/dev/guides/literated/Parameters/

with the new show. But I can also do it in a separate PR

Let's do it separately, since the Rain struct does contain quite a bit more information than is currently printed. It's not obvious to me if printing the entire struct is always useful?

Is this a breaking release from ClimaAtmos point of view in any way?

I don't think so, but I won't make a release here until the P3 PR is merged anyways, and I have a corresponding PR in Atmos

@haakon-e haakon-e merged commit 3aa2461 into main Mar 19, 2026
16 of 26 checks passed
@haakon-e haakon-e deleted the he/rft-parameter-structs branch March 19, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants