Skip to content

feat: #1139 - [E5-F3-P1] Create CondensationLatentHeat class skeleton with tests#1146

Merged
Gorkowski merged 2 commits intouncscode:mainfrom
Gorkowski:issue-1139-adw-72bc5e5e
Mar 4, 2026
Merged

feat: #1139 - [E5-F3-P1] Create CondensationLatentHeat class skeleton with tests#1146
Gorkowski merged 2 commits intouncscode:mainfrom
Gorkowski:issue-1139-adw-72bc5e5e

Conversation

@Gorkowski
Copy link
Copy Markdown
Collaborator

Target Branch: main

Fixes #1139 | Workflow: 72bc5e5e

Summary

Adds the CondensationLatentHeat strategy skeleton with latent-heat resolution
logic and diagnostics, enabling strategy/constant/isothermal fallbacks while
deferring non-isothermal mass-transfer implementation. Exposes the new strategy
through the condensation and dynamics namespaces, and extends tests to cover
instantiation, warnings, and stub behavior.

What Changed

New Components

  • particula/dynamics/condensation/condensation_strategies.py - Added
    CondensationLatentHeat with latent-heat strategy resolution, diagnostics,
    and stubbed abstract methods for later phases.

Modified Components

  • particula/dynamics/condensation/__init__.py - Exported
    CondensationLatentHeat via the condensation package.
  • particula/dynamics/__init__.py - Re-exported CondensationLatentHeat in the
    top-level dynamics namespace.
  • particula/dynamics/condensation/tests/condensation_strategies_test.py -
    Added TestCondensationLatentHeat coverage for resolution priority,
    warnings, and stubbed method behavior.
  • particula/dynamics/tests/condensation_exports_test.py - Verified exports
    across particula.dynamics and particula.dynamics.condensation.
  • adw-docs/dev-plans/**, docs/index.md, readme.md - Refreshed plan and
    documentation indices.

How It Works

CondensationLatentHeat mirrors the isothermal initialization path, then
resolves latent heat in priority order:

  • Use an explicit LatentHeatStrategy when provided.
  • Otherwise, wrap a positive scalar latent heat in ConstantLatentHeat.
  • For zero/negative or array-like inputs, log a warning and fall back to
    isothermal behavior (None).

The core mass-transfer methods are stubbed with NotImplementedError to keep
instantiation and diagnostics testable ahead of P2–P3 implementation.

Implementation Notes

  • Why this approach: Keeps constructor behavior aligned with existing
    condensation strategies while introducing a clear, testable latent-heat
    resolution policy.
  • Warnings: Array-like or negative latent heat values emit logger warnings
    to avoid CI -Werror failures.

Testing

  • pytest (workflow Run Tests phase)
  • pytest particula/dynamics/condensation/tests/condensation_strategies_test.py -v
  • pytest particula/dynamics/tests/condensation_exports_test.py -v

Add CondensationLatentHeat with resolver logic and stubs to support
future latent-heat condensation behavior. Extend condensation tests
and exports to cover the new strategy and its resolution warnings.

Closes uncscode#1139

ADW-ID: 72bc5e5e
Mark E5-F3 P1 in progress across dev plan docs and update
public docs/readme to mention the CondensationLatentHeat
scaffold and strategy resolution behavior. Expand the
CondensationLatentHeat docstrings to describe inputs and
stubbed method expectations.

Closes uncscode#1139

ADW-ID: 72bc5e5e
Copilot AI review requested due to automatic review settings March 4, 2026 03:26
@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: #1146 - feat: #1139 - [E5-F3-P1] Create CondensationLatentHeat class skeleton with tests
Review Date: 2026-03-03
Reviewers: Code Quality, Correctness, Performance (C++/Python), Security


Summary

Severity Count
Critical 0
Warning 3
Suggestion 2

Critical Issues (Must Fix)

None.


Warnings (Should Fix)

  • particula/dynamics/condensation/condensation_strategies.py:1790-1805 - latent_heat validation silently falls back on non-finite values and ignores array-like inputs.
  • particula/dynamics/condensation/condensation_strategies.py:1835-1872 - rate/step signatures diverge from CondensationStrategy (dynamic_viscosity param + return annotation mismatch).
  • particula/dynamics/condensation/condensation_strategies.py:1712-1749 - class docstring missing attribute types/units and latent_heat constraints.

Suggestions (Overview)

  • Consider a small micro-optimization by avoiding repeated np.isscalar checks if a scalar-only API is chosen.
  • If exposing an unimplemented strategy is intentional, consider a brief architectural note or explicit TODO to clarify the roadmap.

Positive Observations

  • Clear scaffolding for the new strategy class with tests in place.
  • Consistent use of strategy pattern fits existing condensation module structure.

Inline Comments

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

  • particula/dynamics/condensation/condensation_strategies.py:1790-1805 - latent_heat validation behavior
  • particula/dynamics/condensation/condensation_strategies.py:1835-1872 - signature alignment with base strategy
  • particula/dynamics/condensation/condensation_strategies.py:1712-1749 - docstring types/units/constraints

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: latent_heat validation should reject non-finite / decide array support

latent_heat currently treats NaN/inf as a silent isothermal fallback and ignores array-like inputs.

Suggested fix:

if not np.isfinite(latent_heat):
    raise ValueError("latent_heat must be finite")

Decide whether array-like values are supported; if not, validate and raise to avoid silent behavior.

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: Align rate/step signatures with CondensationStrategy

The rate() / step() signatures include dynamic_viscosity, and the return annotation differs from the base class.

Suggested fix:

def rate(self, aerosol, gas, temperature, pressure, time_step):
    ...

Keeping signatures identical preserves strategy interchangeability and typing.

@Gorkowski
Copy link
Copy Markdown
Collaborator Author

WARNING: Docstring needs types/units + latent_heat constraints

The class docstring lists attributes without types/units and __init__ doesn’t document latent_heat constraints.

Suggested fix:

latent_heat: float  # J/kg, finite, non-negative

Clarify scalar/array expectations and fallback behavior in the docstrings.

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

Adds an initial CondensationLatentHeat condensation strategy scaffold to support latent-heat strategy/constant resolution and diagnostics, while deferring the non-isothermal mass-transfer implementation to later phases. The PR also wires the new symbol into the public dynamics/condensation namespaces and updates docs/dev-plan indices accordingly.

Changes:

  • Add CondensationLatentHeat skeleton with latent-heat strategy resolution and last_latent_heat_energy diagnostic.
  • Export CondensationLatentHeat via particula.dynamics and particula.dynamics.condensation, with smoke tests for exports.
  • Add unit tests covering instantiation paths, warning logs, and NotImplemented stubs; refresh docs/dev-plan references.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
particula/dynamics/condensation/condensation_strategies.py Adds CondensationLatentHeat class skeleton with latent-heat strategy resolution + stubs.
particula/dynamics/condensation/__init__.py Re-exports CondensationLatentHeat from the condensation subpackage.
particula/dynamics/__init__.py Re-exports CondensationLatentHeat from the top-level dynamics namespace.
particula/dynamics/condensation/tests/condensation_strategies_test.py Adds TestCondensationLatentHeat for resolution priority, logging, diagnostics, and stubs.
particula/dynamics/tests/condensation_exports_test.py Extends export smoke tests to include CondensationLatentHeat.
readme.md Documents the new condensation strategy scaffold in the feature list.
docs/index.md Updates homepage bullet to mention CondensationLatentHeat scaffold.
adw-docs/dev-plans/features/index.md Marks E5-F3 status as “In Progress”.
adw-docs/dev-plans/features/E5-F3-condensation-latent-heat-strategy.md Updates status, dates, and phase checklist details for #1139.
adw-docs/dev-plans/epics/E5-non-isothermal-condensation.md Notes #1139 in the epic’s phase listing and updates “Last Updated”.
adw-docs/dev-plans/README.md Updates dev-plan README to reflect E5-F3 in progress (P1, #1139).

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

Comment on lines +1835 to +1872
def rate(
self,
particle: ParticleRepresentation | ParticleData,
gas_species: GasSpecies | GasData,
temperature: float,
pressure: float,
dynamic_viscosity: Optional[float] = None,
) -> NDArray[np.float64]:
"""Return the condensation rate (stub).

Args:
particle: Particle representation providing radius and activity
information.
gas_species: Gas species supplying vapor properties and
concentrations.
temperature: System temperature in Kelvin.
pressure: System pressure in Pascals.
dynamic_viscosity: Optional dynamic viscosity override.

Returns:
Condensation rate per particle and per species in kg/s.

Raises:
NotImplementedError: Implemented in E5-F3-P2/P3.
"""
raise NotImplementedError("Implemented in E5-F3-P2/P3")

def step(
self,
particle: ParticleRepresentation | ParticleData,
gas_species: GasSpecies | GasData,
temperature: float,
pressure: float,
time_step: float,
dynamic_viscosity: Optional[float] = None,
) -> (
Tuple[ParticleRepresentation, GasSpecies] | Tuple[ParticleData, GasData]
):
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.

rate() and step() add a dynamic_viscosity parameter that is not part of the CondensationStrategy interface (and is not present on CondensationIsothermal / CondensationIsothermalStaggered). For API consistency across condensation strategies, either remove dynamic_viscosity from these method signatures or update the base ABC + other implementations in the same change set.

Copilot uses AI. Check for mistakes.
if latent_heat_array.shape == ():
latent_heat_value = float(latent_heat_array)
if latent_heat_value > 0:
return ConstantLatentHeat(latent_heat_value)
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.

Use a keyword argument when constructing ConstantLatentHeat (e.g., latent_heat_ref=...) to match how this codebase instantiates it elsewhere and to make the units/meaning of the positional value unambiguous.

Suggested change
return ConstantLatentHeat(latent_heat_value)
return ConstantLatentHeat(latent_heat_ref=latent_heat_value)

Copilot uses AI. Check for mistakes.
cond = CondensationLatentHeat(molar_mass=0.018, latent_heat=2.26e6)

self.assertIsInstance(cond._latent_heat_strategy, ConstantLatentHeat)
assert cond._latent_heat_strategy is not 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.

Avoid mixing bare assert with unittest.TestCase assertions. Using self.assertIsNotNone(...) keeps failure reporting consistent and avoids python -O potentially skipping the check.

Suggested change
assert cond._latent_heat_strategy is not None
self.assertIsNotNone(cond._latent_heat_strategy)

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: 197d81b2
  • Current Phase: Workflow completed successfully
  • Current Step: Analyze actionable PR review comments and generate implementation plan
  • Started: 2026-03-04T03:34:59.326561Z
  • Last Update: 2026-03-04T03:51:51.435656Z

Current Status

  • Workflow completed in 16m 50s

Workflow Plan

  • ✅ Analyze PR Comments (at 2026-03-04T03:35:40.672447Z)
  • ✅ Build Implementation (at 2026-03-04T03:38:25.021535Z)
  • ✅ Validate Implementation and Fix Gaps (at 2026-03-04T03:39:21.914827Z)
  • ✅ Polish Code (at 2026-03-04T03:40:23.586880Z)
  • ✅ Run Tests (at 2026-03-04T03:50:29.934885Z)
  • ✅ Format Code and Add Docstrings (at 2026-03-04T03:51:08.743048Z)
  • ✅ Ship Fix (at 2026-03-04T03:51:49.602990Z)
📋 Recent Activity
[2026-03-04T03:39:21.914847Z] Completed step 3/7: Validate Implementation and Fix Gaps
[2026-03-04T03:39:23.558212Z] Starting step 4/7: Polish Code
[2026-03-04T03:40:23.586895Z] Completed step 4/7: Polish Code
[2026-03-04T03:40:25.351970Z] Starting step 5/7: Run Tests
[2026-03-04T03:50:29.934915Z] Completed step 5/7: Run Tests
[2026-03-04T03:50:31.978498Z] Starting step 6/7: Format Code and Add Docstrings
[2026-03-04T03:51:08.743063Z] Completed step 6/7: Format Code and Add Docstrings
[2026-03-04T03:51:10.587587Z] Starting step 7/7: Ship Fix
[2026-03-04T03:51:49.603007Z] Completed step 7/7: Ship Fix
[2026-03-04T03:51:51.433811Z] Workflow fix finished: 7/7 steps completed
🔍 Archived Updates
[2026-03-04T03:34:59.392382Z] Workflow fix started with 7 steps
[2026-03-04T03:35:01.534064Z] Starting step 1/7: Analyze PR Comments
[2026-03-04T03:35:40.672463Z] Completed step 1/7: Analyze PR Comments
[2026-03-04T03:35:42.458170Z] Starting step 2/7: Build Implementation
[2026-03-04T03:38:25.021557Z] Completed step 2/7: Build Implementation
[2026-03-04T03:38:26.840594Z] Starting step 3/7: Validate Implementation and Fix Gaps

This comment is automatically updated as the workflow progresses

Gorkowski added a commit to Gorkowski/particula that referenced this pull request Mar 4, 2026
Reject array-like or non-finite latent heat inputs and use
keyworded constant latent heat construction to clarify units.
Align CondensationLatentHeat rate/step signatures with the base
strategy and update tests to assert ValueError handling.

Update E5-F3 planning docs to reflect validation expectations.

Closes uncscode#1146

ADW-ID: 197d81b2
@Gorkowski
Copy link
Copy Markdown
Collaborator Author

Fix Summary

Implemented the fixes outlined in the workflow plan for PR #1146, including aligning CondensationLatentHeat API signatures with the base strategy, validating and documenting latent_heat constraints, and updating tests for style consistency.

Changes Made

  • Aligned rate()/step() signatures and return annotations with CondensationStrategy.
  • Enforced finite latent_heat inputs, clarified scalar/array support, and expanded docstrings with types/units/constraints.
  • Used keyword argument for ConstantLatentHeat(latent_heat_ref=...) instantiation.
  • Updated unittest assertion style to self.assertIsNotNone(...).

Review Comments Addressed

  • Copilot: Align rate()/step() signatures with base strategy.
  • Copilot: Use keyword argument for ConstantLatentHeat.
  • Copilot: Replace bare assert with unittest-style assertion.
  • @Gorkowski: Reject non-finite latent_heat; clarify scalar/array support.
  • @Gorkowski: Ensure API signatures/return annotations match base class.
  • @Gorkowski: Add types/units/constraints to class and __init__ docs.
  • @Gorkowski: Add a brief architectural note/TODO for the deferred roadmap.

(Review comment IDs not recorded in workflow state.)

Files Changed

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

Automated fix by ADW workflow 197d81b2

@Gorkowski Gorkowski merged commit 5d2cdb5 into uncscode:main Mar 4, 2026
11 checks passed
@Gorkowski Gorkowski deleted the issue-1139-adw-72bc5e5e branch March 4, 2026 04:09
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-P1] Create CondensationLatentHeat class skeleton with tests

2 participants