Skip to content

feat: #1140 - Implement mass_transfer_rate() and rate() with tests#1147

Merged
Gorkowski merged 3 commits intouncscode:mainfrom
Gorkowski:issue-1140-adw-2476d14e
Mar 4, 2026
Merged

feat: #1140 - Implement mass_transfer_rate() and rate() with tests#1147
Gorkowski merged 3 commits intouncscode:mainfrom
Gorkowski:issue-1140-adw-2476d14e

Conversation

@Gorkowski
Copy link
Copy Markdown
Collaborator

Target Branch: main

Fixes #1140 | Workflow: 2476d14e

Summary

Adds the non-isothermal condensation path to CondensationLatentHeat, reusing the isothermal flow through transport/pressure steps and branching to a latent-heat correction that uses surface vapor pressure and thermal conductivity. Implements rate() parity with the isothermal strategy and tightens handling of non-finite pressure deltas. Expands latent-heat tests to cover parity, reduction, shapes, scaling, skip-partitioning, and sanitization.

What Changed

New Components

  • _get_vapor_pressure_surface helper (in condensation_strategies.py) to extract surface equilibrium vapor pressure for the latent-heat correction without changing the public API.

Modified Components

  • particula/dynamics/condensation/condensation_strategies.py — implemented CondensationLatentHeat.mass_transfer_rate() with latent-heat branch using get_mass_transfer_rate_latent_heat + get_thermal_conductivity, reusing isothermal steps 1–3 and sanitizing pressure deltas; implemented rate() to scale by raw concentration and apply skip-partitioning; kept isothermal parity when no latent heat strategy is provided.
  • particula/dynamics/condensation/tests/condensation_strategies_test.py — added full latent-heat fixtures, parity/reduction/shape/skip-partitioning/scaling/sanitization tests, and updated the legacy stub test to only assert step() is still unimplemented.
  • Docs (adw-docs/dev-plans/*, docs/index.md, readme.md) — refreshed feature plan and index references for E5-F3 P2 completion.

Tests Added/Updated

  • particula/dynamics/condensation/tests/condensation_strategies_test.py — coverage for isothermal parity, latent-heat reduction, single- vs multi-species shapes, rate scaling and skip-partitioning, surface vapor-pressure helper, and non-finite pressure-delta sanitization.

How It Works

mass_transfer_rate()
    ├─ unwrap + validate (particle/gas, single box)
    ├─ fill/clip radii → first_order_mass_transport()
    ├─ pressure_delta = calculate_pressure_delta() → nan_to_num
    ├─ if no latent heat → get_mass_transfer_rate()
    └─ else
         ├─ latent_heat_strategy.latent_heat()
         ├─ get_thermal_conductivity()
         ├─ _get_vapor_pressure_surface()
         └─ get_mass_transfer_rate_latent_heat(
               diffusion_coefficient=self.diffusion_coefficient
             )

rate()
    ├─ mass_rate = mass_transfer_rate(...)
    ├─ scale by raw concentration (reshape for 2D)
    └─ apply _apply_skip_partitioning → return

Implementation Notes

  • Non-finite pressure_delta values are zeroed to avoid propagating NaNs/±inf into rates.
  • _get_vapor_pressure_surface mirrors the front half of calculate_pressure_delta(), squeezing (n, 1) activity output to 1D to maintain shape parity.
  • Latent-heat path uses diffusion_coefficient and thermal conductivity at the call temperature; fallback path remains bit-for-bit with CondensationIsothermal when no latent heat strategy is present.
  • rate() multiplies by raw concentration (legacy-compatible) and respects configured skip-partitioning indices.

Testing

  • pytest particula/dynamics/condensation/tests/condensation_strategies_test.py -k "LatentHeat"
  • pytest (workflow test step)

Add vapor-pressure surface helper to compute Kelvin-corrected partial
pressures for latent-heat condensation. Implement non-isothermal
mass_transfer_rate and rate to sanitize non-finite deltas, include latent
heat/thermal conductivity corrections, and preserve isothermal parity
when latent heat is absent. Expand CondensationLatentHeat tests with
parity, shape, skip-partitioning, concentration scaling, and
non-finite-sanitization coverage. Update E5-F3 planning docs to reflect
current status.

Closes uncscode#1140

ADW-ID: 2476d14e
Mark E5 and E5-F3-P2 status updates in dev plans and indices,
refresh docs/readme to reflect latent-heat mass-transfer and
rate coverage, and expand latent-heat strategy docstrings for
clarity.

Closes uncscode#1140

ADW-ID: 2476d14e
Copilot AI review requested due to automatic review settings March 4, 2026 04:44
@Gorkowski Gorkowski added agent Created or managed by ADW automation blocked Blocked - review required before ADW can process labels Mar 4, 2026
@Gorkowski
Copy link
Copy Markdown
Collaborator Author

ADW Code Review

PR: #1147 - feat: #1140 - Implement mass_transfer_rate() and rate() with tests
Review Date: 2026-03-03
Reviewers: Code Quality, Correctness, Performance (C++/Python), Security


Summary

Severity Count
Critical 0
Warning 10
Suggestion 1

Critical Issues (Must Fix)

None.


Warnings (Should Fix)

  • Strategy API inconsistency: CondensationLatentHeat.rate() adds dynamic_viscosity not in base interface.
  • Validation gap: latent-heat path lacks non-finite validation for latent_heat/thermal_conductivity/vapor_pressure_surface.
  • Validation gap: vapor_pressure_surface can be non-finite from Kelvin term; should validate/sanitize.
  • Input masking: pressure_delta nan_to_num may mask invalid inputs; consider logging/raise.
  • Tests: Missing error-path tests for mixed inputs and single-box checks.
  • Duplication: vapor-pressure computation duplicated between calculate_pressure_delta and _get_vapor_pressure_surface.
  • Performance: per-particle staggered loop recomputes strategy/partial pressure; hoist invariants.
  • Bounds: skip_partitioning_indices lacks bounds checking.
  • Docstring: class fallback behavior should mention positive latent_heat.
  • Docstring: latent_heat arg should mention negative/array warnings.

Suggestions (Overview)

  • Remove internal milestone reference from step() docstring.

Positive Observations

  • Good coverage of the new mass_transfer_rate()/rate() workflow with tests.
  • Clear separation between strategy calculation and execution flow.

Inline Comments

Detailed feedback has been posted as inline comments on the following locations:

  • rate() signature inconsistency
  • latent-heat non-finite validation
  • vapor_pressure_surface validation
  • pressure_delta nan_to_num masking

This review was generated by ADW Multi-Agent Code Review System.
Reviewers: Quality, Correctness, C++ Performance, Python Performance, Security

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: Strategy API inconsistency in rate()

CondensationLatentHeat.rate() adds a dynamic_viscosity parameter that is not present in the base strategy interface.

Suggested fix:

# Option A: add to base interface
class CondensationStrategy(ABC):
    def rate(self, ..., dynamic_viscosity: float | NDArray[np.float64]) -> ...:
        ...

# Option B: keep signature consistent and pass via state object

Keeping signatures aligned prevents LSP violations and avoids runtime errors when swapping strategies.

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: Missing non-finite validation in latent-heat path

latent_heat, thermal_conductivity, and vapor_pressure_surface are used without non-finite checks, which can propagate NaNs/inf.

Suggested fix:

validate_inputs({
    "latent_heat": "finite",
    "thermal_conductivity": "finite",
    "vapor_pressure_surface": "finite",
})

This keeps the latent-heat path consistent with other input validation and avoids silent NaN propagation.

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: vapor_pressure_surface can be non-finite from Kelvin term

The Kelvin term can yield non-finite values, which then flow into vapor_pressure_surface.

Suggested fix:

vapor_pressure_surface = np.asarray(vapor_pressure_surface)
if not np.all(np.isfinite(vapor_pressure_surface)):
    raise ValueError("vapor_pressure_surface must be finite")

Failing fast makes invalid inputs visible and prevents downstream NaNs.

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: nan_to_num masks invalid pressure_delta inputs

nan_to_num converts NaNs/Infs to finite values, which can hide invalid state and make debugging difficult.

Suggested fix:

if not np.all(np.isfinite(pressure_delta)):
    raise ValueError("pressure_delta contains non-finite values")

Failing loudly here will surface invalid upstream inputs instead of silently masking them.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements the non-isothermal (latent-heat-corrected) condensation rate path in CondensationLatentHeat, keeping isothermal parity when no latent heat strategy is configured, and adds targeted tests + doc updates to reflect the feature’s completion status.

Changes:

  • Added _get_vapor_pressure_surface() and implemented CondensationLatentHeat.mass_transfer_rate() with an optional latent-heat correction branch (and non-finite Δp sanitization).
  • Implemented CondensationLatentHeat.rate() to scale by raw particle concentration and apply skip-partitioning, mirroring isothermal behavior.
  • Expanded condensation strategy tests for parity, latent-heat reduction, shape handling, skip-partitioning, scaling, and sanitization; refreshed docs to reflect E5 progress.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
particula/dynamics/condensation/condensation_strategies.py Implements latent-heat corrected mass-transfer/rate flow and adds a helper to obtain surface vapor pressure.
particula/dynamics/condensation/tests/condensation_strategies_test.py Adds fixtures and tests covering parity, reduction, shapes, scaling, skip-partitioning, and sanitization.
readme.md Updates feature bullets to reflect that latent-heat mass_transfer_rate()/rate() are implemented.
docs/index.md Updates landing-page feature text to reflect latent-heat strategy completion status.
adw-docs/dev-plans/features/E5-F3-condensation-latent-heat-strategy.md Marks E5-F3-P2 complete and adjusts planning metadata.
adw-docs/dev-plans/epics/index.md Updates E5 epic status to “In Progress”.
adw-docs/dev-plans/epics/E5-non-isothermal-condensation.md Updates E5 epic metadata and phase checklist status.
adw-docs/dev-plans/README.md Updates E5 epic status and removes outdated P1 reference.

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

@@ -1840,24 +1946,50 @@ def rate(
pressure: float,
dynamic_viscosity: Optional[float] = None,
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

CondensationLatentHeat.rate() adds a dynamic_viscosity parameter, but CondensationStrategy.rate() (and the other condensation strategies) do not accept this argument. This breaks API parity with CondensationIsothermal.rate() and can cause override/type-checking issues. Consider removing dynamic_viscosity from rate() (keep it only on mass_transfer_rate()), or, if viscosity needs to be configurable at the rate() level, update the base ABC + all strategy implementations consistently.

Copilot uses AI. Check for mistakes.
@Gorkowski Gorkowski added request:fix Request AI to implement review suggestions adw:in-progress ADW workflow actively processing - remove to re-trigger and removed blocked Blocked - review required before ADW can process labels Mar 4, 2026
@Gorkowski
Copy link
Copy Markdown
Collaborator Author

Gorkowski commented Mar 4, 2026

🤖 Agent Developer Workflow

  • Description: Direct PR fix workflow triggered by request:fix label. Analyzes actionable review comments, generates fix plan, implements changes, validates, polishes, tests, formats, and ships fixes without creating intermediate GitHub issues.
  • ADW ID: 98ecae9c
  • Current Phase: Workflow completed successfully
  • Current Step: Analyze actionable PR review comments and generate implementation plan
  • Started: 2026-03-04T11:48:04.351961Z
  • Last Update: 2026-03-04T12:11:08.429657Z

Current Status

  • Workflow completed in 23m 2s

Workflow Plan

  • ✅ Analyze PR Comments (at 2026-03-04T11:48:47.781973Z)
  • ✅ Build Implementation (at 2026-03-04T11:57:23.495266Z)
  • ✅ Validate Implementation and Fix Gaps (at 2026-03-04T11:58:32.507921Z)
  • ✅ Polish Code (at 2026-03-04T11:59:31.979495Z)
  • ✅ Run Tests (at 2026-03-04T12:09:48.962501Z)
  • ✅ Format Code and Add Docstrings (at 2026-03-04T12:10:24.495190Z)
  • ✅ Ship Fix (at 2026-03-04T12:11:06.584457Z)
📋 Recent Activity
[2026-03-04T11:58:32.507935Z] Completed step 3/7: Validate Implementation and Fix Gaps
[2026-03-04T11:58:34.350547Z] Starting step 4/7: Polish Code
[2026-03-04T11:59:31.979521Z] Completed step 4/7: Polish Code
[2026-03-04T11:59:33.618550Z] Starting step 5/7: Run Tests
[2026-03-04T12:09:48.962520Z] Completed step 5/7: Run Tests
[2026-03-04T12:09:51.525203Z] Starting step 6/7: Format Code and Add Docstrings
[2026-03-04T12:10:24.495229Z] Completed step 6/7: Format Code and Add Docstrings
[2026-03-04T12:10:26.328100Z] Starting step 7/7: Ship Fix
[2026-03-04T12:11:06.584476Z] Completed step 7/7: Ship Fix
[2026-03-04T12:11:08.428111Z] Workflow fix finished: 7/7 steps completed
🔍 Archived Updates
[2026-03-04T11:48:04.417258Z] Workflow fix started with 7 steps
[2026-03-04T11:48:06.425929Z] Starting step 1/7: Analyze PR Comments
[2026-03-04T11:48:47.781993Z] Completed step 1/7: Analyze PR Comments
[2026-03-04T11:48:49.487452Z] Starting step 2/7: Build Implementation
[2026-03-04T11:57:23.495293Z] Completed step 2/7: Build Implementation
[2026-03-04T11:57:25.229112Z] Starting step 3/7: Validate Implementation and Fix Gaps

This comment is automatically updated as the workflow progresses

Harden latent-heat condensation by validating pressure deltas,
latent heat, thermal conductivity, and surface vapor pressure.
Extract Kelvin/partial-pressure helper to avoid duplication and
add bounds checks for skip-partitioning indices.

Update docs and expand tests for error paths and index validation.

Closes uncscode#1147

ADW-ID: 98ecae9c
@Gorkowski
Copy link
Copy Markdown
Collaborator Author

Fix Summary

Addressed PR review feedback on condensation strategy API parity, latent-heat validation, pressure-delta handling, skip-partitioning bounds, and documentation/testing gaps in the condensation latent-heat path.

Changes Made

  • Aligned condensation strategy rate() interface with base strategy expectations and updated docstrings/type hints.
  • Added explicit non-finite validation for latent-heat inputs (latent_heat, thermal_conductivity, vapor_pressure_surface) and Kelvin-term outputs; removed masking of pressure_delta in favor of clear error handling.
  • Added bounds checks for skip_partitioning_indices, reduced duplicated vapor-pressure computation via helper usage, and documented fallback behavior.
  • Expanded condensation strategy tests to cover error paths, parity/reduction, shape handling, skip-partitioning bounds, and non-finite pressure deltas.

Review Comments Addressed

  • CondensationLatentHeat.rate() signature parity with base strategy (reviewer: @Copilot).
  • Latent-heat input finiteness validation; Kelvin-term vapor-pressure validation; explicit non-finite pressure_delta errors (reviewer: @Gorkowski).
  • Skip-partitioning bounds checks and reduced vapor-pressure duplication; doc updates and error-path tests (reviewer: @Gorkowski).

Files Changed

  • docs/index.md
  • particula/dynamics/condensation/condensation_strategies.py
  • particula/dynamics/condensation/tests/condensation_strategies_test.py
  • readme.md

Automated fix by ADW workflow 98ecae9c

@Gorkowski Gorkowski merged commit dd721f9 into uncscode:main Mar 4, 2026
7 checks passed
@Gorkowski Gorkowski deleted the issue-1140-adw-2476d14e branch March 4, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adw:in-progress ADW workflow actively processing - remove to re-trigger agent Created or managed by ADW automation request:fix Request AI to implement review suggestions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[E5-F3-P2] Implement mass_transfer_rate() and rate() with tests

2 participants