Skip to content

Insoluble aerosol affecting condensation though kappa#493

Open
pdziekan wants to merge 15 commits into
igfuw:masterfrom
pdziekan:rd_insol_in_kappa
Open

Insoluble aerosol affecting condensation though kappa#493
pdziekan wants to merge 15 commits into
igfuw:masterfrom
pdziekan:rd_insol_in_kappa

Conversation

@pdziekan

@pdziekan pdziekan commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

no rd_insol in condensation, instead kappa is reduced if theres insoluble aerosol (Petters & Kreidenweis 2007)

Copilot AI review requested due to automatic review settings June 18, 2026 13:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Lagrangian microphysics initialization/diagnostics so that insoluble aerosol no longer directly affects condensation via a separate rd_insol term; instead, insoluble material reduces the effective hygroscopicity (kappa) while contributing to the dry radius.

Changes:

  • Remove rd3_insol from condensation/Köhler calculations and apply insoluble effects by reducing kappa based on insoluble volume fraction.
  • Introduce/rewire initialization steps to incorporate insoluble aerosol into dry size (add_insol_to_dry) and update kappa initialization accordingly.
  • Update ice nucleation to use insoluble particle surface area (rd2_insol) and adjust Python bindings + unit tests.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/python/unit/diag_incloud_time.py Simplifies dry distro keys (no explicit insoluble usage in this test).
tests/python/unit/api_lgrngn.py Updates dry-radius diagnostics and adds assertions for effective kappa with insoluble aerosol.
tests/python/unit/api_common.py Updates rw3_cr / S_cr calls to new signatures.
src/particles.tpp Includes new initialization helper for insoluble aerosol handling.
src/particles_diag.ipp Drops rd3_insol from diagnostic transforms calling Köhler helpers.
src/impl/sources_and_relaxation_of_SDs/particles_impl_src_dry_sizes.ipp Adjusts dry-size init to include insoluble radius and new init_kappa(kappa, rd_insol).
src/impl/sources_and_relaxation_of_SDs/particles_impl_src_dry_distros_simple.ipp Inserts insoluble contribution into dry size during source creation and updates kappa init signature.
src/impl/sources_and_relaxation_of_SDs/particles_impl_src_dry_distros_matching.ipp Adds a guard for unsupported rd_insol in matching sources and updates kappa init signature.
src/impl/sources_and_relaxation_of_SDs/particles_impl_rlx_dry_distros.ipp Modernizes iterator loops; clarifies assumptions about produced aerosol and rd_insol.
src/impl/particles_impl.ipp Renames/removes insoluble state from rd3_insol to rd2_insol (ice-only) and updates init method signatures.
src/impl/initialization/particles_impl_reserve_hskpng_npart.ipp Reserves rd2_insol only when ice is enabled; removes rd3_insol reserve.
src/impl/initialization/particles_impl_init_wet.ipp Removes rd3_insol from wet-radius equilibrium calculation path.
src/impl/initialization/particles_impl_init_T_freeze.ipp Updates freezing init to use rd2_insol (surface area proxy).
src/impl/initialization/particles_impl_init_SD_with_sizes.ipp Uses rd_sol + rd_insol in dry size init; updates kappa + insol init sequencing.
src/impl/initialization/particles_impl_init_SD_with_distros.ipp Adds insoluble contribution to dry size and updates kappa initialization sequencing.
src/impl/initialization/particles_impl_init_sanity_check.ipp Disallows insoluble aerosol initialization when chemistry is enabled.
src/impl/initialization/particles_impl_init_kappa.ipp Computes effective kappa after insoluble addition (volume-fraction reduction).
src/impl/initialization/particles_impl_init_insol_dry_sizes.ipp Stores insoluble size as rd2_insol (radius squared).
src/impl/initialization/particles_impl_init_dry_const_multi.ipp Whitespace-only tweak in signature line.
src/impl/initialization/particles_impl_add_insol_to_dry.ipp New helper for adding insoluble aerosol contribution into dry size.
src/impl/ice/particles_impl_ice_nucl_melt.ipp Switches ice nucleation inputs from rd3_insol to rd2_insol.
src/impl/ice/particles_impl_ice_dep.ipp Removes unused tuple inputs (rd3/kpa) from deposition helper zip iterator.
src/impl/housekeeping/particles_impl_hskpng_rc2.ipp Removes rd3_insol from rc2 approximation inputs.
src/impl/diagnose_SD_attributes/particles_impl_update_incloud_time.ipp Removes rd3_insol from incloud-time diagnostic transform inputs.
src/impl/diagnose_SD_attributes/particles_impl_fill_outbuf.ipp Renames exposed attribute from rd3_insol to rd2_insol and gates it behind ice_switch.
src/impl/condensation/perparticle/perparticle_nomixing_adaptive_sstp_cond.ipp Removes rd3_insol from condensation substepping tuple payloads.
src/impl/condensation/perparticle/perparticle_advance_rw2.ipp Removes rd3_insol from advance tuple payloads.
src/impl/condensation/percell/particles_impl_cond.ipp Removes rd3_insol from per-cell condensation tuple payloads.
src/impl/condensation/common/particles_impl_cond_common.ipp Removes rd3_insol from activity-of-water usage and tuple parsing/diagnostics.
include/libcloudph++/lgrngn/opts_init.hpp Switches rlx_dry_distros to a shared alias type.
include/libcloudph++/lgrngn/distro_t.hpp Adds rlx_dry_distros_t alias definition.
include/libcloudph++/common/kappa_koehler.hpp Removes insoluble term from Köhler helpers (activity/equilibrium/critical values).
include/libcloudph++/common/ice_nucleation.hpp Updates ice nucleation API to use insoluble surface area (rd2_insol).
bindings/python/common.hpp Updates Python binding signatures for rw3_cr and S_cr.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 25 to 30
thrust::transform(
thrust::make_zip_iterator(thrust::make_tuple(rd3_insol.begin() + n_part_old, u01.begin())),
thrust::make_zip_iterator(thrust::make_tuple(rd3_insol.begin() + n_part_old, u01.begin())) + n_part_to_init,
thrust::make_zip_iterator(thrust::make_tuple(rd2_insol.begin() + n_part_old, u01.begin() + n_part_old)),
thrust::make_zip_iterator(thrust::make_tuple(rd2_insol.end(), u01.end())),
T_freeze.begin() + n_part_old,
T_freeze_CDF_inv_functor<real_t>(opts_init.inp_type)
);
Comment on lines +20 to +30

// add the insoluble aerosol
const real_t rd3_insol = rd_insol * rd_insol * rd_insol;
thrust::transform(
rd3.begin()+n_part_old,
rd3.end(),
thrust::make_constant_iterator<real_t>(rd3_insol),
rd3.begin()+n_part_old,
// arg::_1 + arg::_2
thrust::plus<real_t>()
);
Comment on lines +29 to +31

debug::print(kpa);

Comment on lines 53 to 55
auto p_sdd = sdd.cbegin();
assert(p_sdd->first.rd_insol == 0); // rd insol in matching source not implemented yet

Comment thread tests/python/unit/api_lgrngn.py Outdated
assert (n == 20 ).all()
assert isclose(k, n * kappa2, rtol=1e-20)
for rd_sol, kappa, n_stp in [(1e-6, kappa1, 30), (15.e-6, kappa1, 10), (1.2e-6, kappa2, 20), (12.e-6, kappa2, 15)]:
print("testig rd_sol: ", rd_sol, " kappa: ", kappa, " n_stp: ", n_stp)
rd3.begin() + n_part_old, rd3.end(),
kpa.begin() + n_part_old,
(arg::_1 - rd3_insol) / arg::_1 * kappa
// assuming that soluble and insoluble densities are the same (hence using volume fraction mixing, not mass fraction as should (?) be done)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's ok following Petters and Kreidenweis:
"ε is defined as the volume fraction of a model salt in a dry particle consisting of the model salt (κ_m) and an insoluble
core. Two-component system of a model salt and an insoluble species (κ=0) gives κ=ε × κ_m ."

thrust::make_zip_iterator(thrust::make_tuple(rd2_insol.end(), u01.end())),
T_freeze.begin() + n_part_old,
T_freeze_CDF_inv_functor<real_t>(opts_init.inp_type)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

that problem with u01 for T_freeze was fixed in my PR, so we need to keep changes from my PR here

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 57 out of 58 changed files in this pull request and generated 7 comments.

Comment on lines 51 to 54
{
assert(kappa > 0);
if ((rw3 - rd3 - rd3_insol) / si::cubic_meters <= std::nextafter(real_t(0),real_t(1)))
return real_t(0.);
return (rw3 - rd3 - rd3_insol) / (rw3 - rd3 * (real_t(1) - kappa) - rd3_insol);
return (rw3 - rd3) / (rw3 - rd3 * (real_t(1) - kappa));
}
Comment on lines +23 to +27
BOOST_GPU_ENABLED
real_t operator()(real_t rd3_val) const
{
return pow(insol_fraction * rd3_val, real_t(2) / real_t(3));
}
Comment on lines 22 to 24
const real_t &kappa(dsi->first.kappa);
const real_t &rd_insol(dsi->first.rd_insol);
const real_t &soluble_fraction(dsi->first.soluble_fraction);
const auto &size_number_map(dsi->second);
Comment on lines +61 to 65
// init other properties of SDs
init_kappa(
p_sdd->first.kappa
p_sdd->first.kappa,
p_sdd->first.soluble_fraction
);
// if any SDs with dry radius similar to the one to be added are present,
// we increase their multiplicity instead of adding new SDs
// TODO: make it work for sdd.size()>1
// -------- TODO: match not only sizes of old particles, but also kappas, rd_insol, chemical composition... --------
Comment on lines 101 to 104
// analyze distribution to get rd_min and max needed for bin sizes
// TODO: this could be done once at the beginning of the simulation
// TODO: take rd_insol into account here?
init_dist_analysis_sd_conc(
assert (n == 20 ).all()
assert isclose(k, n * kappa2, rtol=1e-20)
for rd, kappa, n_stp in [(1e-6, kappa1, 30), (15.e-6, kappa1, 10), (1.2e-6, kappa2, 20), (12.e-6, kappa2, 15)]:
print("testig rd: ", rd, " kappa: ", kappa, " n_stp: ", n_stp)
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.

3 participants