Skip to content

Implement PyO3 bindings for Blake Threshold and Giersiepen Hemolysis#262

Open
ryancinsight wants to merge 2 commits intomainfrom
implement-pyo3-blake-giersiepen-13880426803342757695
Open

Implement PyO3 bindings for Blake Threshold and Giersiepen Hemolysis#262
ryancinsight wants to merge 2 commits intomainfrom
implement-pyo3-blake-giersiepen-13880426803342757695

Conversation

@ryancinsight
Copy link
Owner

@ryancinsight ryancinsight commented Mar 8, 2026

This PR implements the requested cfd_python bindings for Blake Threshold and Giersiepen Hemolysis. PyClass implementation handles data conversion correctly, and we remove TODO tags in the validation python script to assert that variables from both implementations match.


PR created automatically by Jules for task 13880426803342757695 started by @ryancinsight

Summary by CodeRabbit

  • New Features

    • Added cavitation analysis with Blake threshold and critical radius calculation.
    • Added Giersiepen hemolysis model for blood damage estimation.
  • Chores

    • Reorganized internal module structure for clearer code layout.
    • Improved validation script to perform concrete cross-language comparisons with per-case diffs and PASS/FAIL reporting.
    • Expanded benchmark workflow dependencies for more robust performance runs.

High-level PR Summary

This PR adds Python bindings for Blake Threshold cavitation calculations and Giersiepen hemolysis modeling to the cfd_python package. Two new PyO3 wrapper classes (PyBlakeThreshold and PyGiersiepenModel) expose the existing Rust physics implementations to Python. The validation script is updated to remove TODO comments and now actively cross-validates the Rust implementations against Python reference calculations, confirming that both implementations produce matching results. Additionally, several import paths are updated to reflect refactored module structures in the underlying Rust crates.

⏱️ Estimated Review Time: 15-30 minutes

💡 Review Order Suggestion
Order File Path
1 crates/cfd-python/src/lib.rs
2 crates/cfd-python/src/cavitation.rs
3 crates/cfd-python/src/hemolysis.rs
4 validation/cross_validate_rust_python.py
5 crates/cfd-python/src/bifurcation.rs
6 crates/cfd-python/src/womersley.rs
7 crates/cfd-python/src/solver_2d/serpentine.rs
8 crates/cfd-python/src/solver_2d/venturi.rs

Need help? Join our Discord

- Added `cavitation.rs` and `hemolysis.rs` into `crates/cfd-python/src/`
- Implemented `PyBlakeThreshold` and `PyGiersiepenModel` inside these modules
- Registered these new PyClasses inside `cfd_python` module initialization in `crates/cfd-python/src/lib.rs`
- Fixed module resolution inside `crates/cfd-python/src/` resolving import errors for python bindings
- Removed TODO flags in `validation/cross_validate_rust_python.py`
- Setup logic in `validation/cross_validate_rust_python.py` using `cfd_python` to fetch variables generated by rust implementations to verify equivalency with python variables

Co-authored-by: ryancinsight <55164720+ryancinsight@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: af6d8949-b285-4a40-8ce1-f79b9d122d14

📥 Commits

Reviewing files that changed from the base of the PR and between ab26b64 and 7298c22.

📒 Files selected for processing (1)
  • .github/workflows/performance-benchmarking.yml

📝 Walkthrough

Walkthrough

The PR updates several cfd_1d import paths to new domain/physics locations, adds PyO3 bindings for BlakeThreshold (cavitation) and GiersiepenModel (hemolysis), registers them in the Python module, and enhances the cross-validation script to compare Rust bindings against Python implementations.

Changes

Cohort / File(s) Summary
Module Path Updates
crates/cfd-python/src/bifurcation.rs, crates/cfd-python/src/solver_2d/serpentine.rs, crates/cfd-python/src/solver_2d/venturi.rs, crates/cfd-python/src/womersley.rs
Adjusted import paths to the restructured crate layout (e.g., cfd_1d::...cfd_1d::domain::... or cfd_1d::physics::...). No logic changes.
New Python Bindings for Physics Models
crates/cfd-python/src/cavitation.rs, crates/cfd-python/src/hemolysis.rs
Added PyO3-exposed classes: BlakeThreshold (new, critical_radius, threshold) and GiersiepenModel (new, calculate_damage) wrapping Rust physics/hemolysis models.
Module Registration
crates/cfd-python/src/lib.rs
Added cavitation and hemolysis modules, re-exported their symbols, and registered the new PyO3 classes in the Python module init.
Cross-Validation Script
validation/cross_validate_rust_python.py
Replaced placeholders with concrete cfd_python bindings (BlakeThreshold, CarreauYasudaBlood, GiersiepenModel), implemented side-by-side Rust↔Python comparisons with percent-diff reporting and PASS/MISMATCH outputs.
CI Packages
.github/workflows/performance-benchmarking.yml
Linux benchmark step installs additional packages (libfontconfig1-dev, pkg-config) alongside existing dependencies.

Sequence Diagram(s)

sequenceDiagram
    participant Validator as Python Validator Script
    participant PyBind as cfd_python (PyO3 bindings)
    participant RustModel as Rust physics/hemolysis models

    Validator->>PyBind: instantiate BlakeThreshold(ambient_pressure)
    PyBind->>RustModel: build CavitationRegimeClassifier / RayleighPlesset
    RustModel-->>PyBind: return classifier & threshold functions
    PyBind-->>Validator: provide critical_radius() and threshold()
    Validator->>Validator: compute reference Python values
    Validator->>PyBind: call threshold()/critical_radius()/calculate_damage()
    Validator->>Validator: compare Rust vs Python, print percent diffs and PASS/MISMATCH
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble paths and bindings bright,
Blake and Giersiepen hop into sight,
Python calls Rust, the numbers meet,
Cross-checked echoes, tidy and neat,
A tiny rabbit cheers this merge tonight 🌿

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implement PyO3 bindings for Blake Threshold and Giersiepen Hemolysis' directly and accurately summarizes the main changes in this PR, which adds PyO3 wrapper classes and Python bindings for two physics models.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch implement-pyo3-blake-giersiepen-13880426803342757695

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the cfd-python library by integrating Python bindings for two critical physics models: the Blake Threshold for cavitation and the Giersiepen model for hemolysis. These additions provide Python users with direct access to high-performance Rust implementations of these models. Furthermore, the accompanying validation script has been upgraded to rigorously cross-check the new Rust-based Python bindings against established Python implementations, confirming their accuracy and reliability. Minor internal refactoring of Rust module paths was also performed to improve code structure.

Highlights

  • New PyO3 Bindings for Cavitation: Implemented Python bindings for the Blake Threshold cavitation model, allowing calculation of critical radius and threshold pressure from Python.
  • New PyO3 Bindings for Hemolysis: Introduced Python bindings for the Giersiepen Hemolysis model, enabling damage index calculations from Python.
  • Enhanced Cross-Validation Script: Updated the cross_validate_rust_python.py script to perform explicit comparisons between the new Rust-backed Python implementations and existing Python calculations for Blake Threshold, Carreau-Yasuda Blood, and Giersiepen Hemolysis, ensuring numerical consistency.
  • Internal Rust Module Refactoring: Refactored internal import paths within the cfd-1d crate, moving junctions, channel, resistance, and womersley modules under domain or physics namespaces for better organization.
Changelog
  • crates/cfd-python/src/bifurcation.rs
    • Updated import paths for TwoWayBranchJunction, ThreeWayBranchJunction, Channel, and ChannelGeometry.
  • crates/cfd-python/src/cavitation.rs
    • Added new file for PyBlakeThreshold class.
  • crates/cfd-python/src/hemolysis.rs
    • Added new file for PyGiersiepenModel class.
  • crates/cfd-python/src/lib.rs
    • Added new modules cavitation and hemolysis.
    • Exposed PyBlakeThreshold and PyGiersiepenModel classes to the Python module.
  • crates/cfd-python/src/solver_2d/serpentine.rs
    • Updated import path for FlowConditions, ResistanceModel, SerpentineCrossSection, SerpentineModel.
  • crates/cfd-python/src/solver_2d/venturi.rs
    • Updated import path for FlowConditions, ResistanceModel, VenturiModel.
  • crates/cfd-python/src/womersley.rs
    • Updated import path for WomersleyFlow, WomersleyNumber, WomersleyProfile.
  • validation/cross_validate_rust_python.py
    • Updated the script to include explicit cross-validation tests for Blake Threshold, Carreau-Yasuda Blood, and Giersiepen Hemolysis models, removing TODO comments and asserting matches.
    • Updated file paths for Rust implementations.
Activity
  • PR created automatically by Jules for task 13880426803342757695 started by @ryancinsight.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully implements PyO3 bindings for the Blake Threshold and Giersiepen Hemolysis models, and adds the corresponding cross-validation tests against the Python implementations. The changes are well-structured and the validation script is now more comprehensive. I have one suggestion in cavitation.rs to improve maintainability by reducing code duplication.

Comment on lines +33 to +43
fn critical_radius(&self) -> f64 {
let model = RayleighPlesset {
initial_radius: 10e-6,
liquid_density: 997.0,
liquid_viscosity: 0.001,
surface_tension: 0.0728,
vapor_pressure: 2339.0,
polytropic_index: 1.4,
};
model.blake_critical_radius(self.ambient_pressure)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The RayleighPlesset model is re-created here with the same hardcoded values used in the new function. This code duplication can lead to maintenance issues. For instance, if the model parameters in new are updated, the same change would need to be manually applied here.

A better approach would be to store the RayleighPlesset instance on the PyBlakeThreshold struct itself and reuse it. Since RayleighPlesset implements Copy, this is an efficient change.

You could refactor this by:

  1. Adding a model: RayleighPlesset<f64> field to PyBlakeThreshold.
  2. In new(), create the model once and store it on the new PyBlakeThreshold instance. The CavitationRegimeClassifier can be created using this same model instance.
  3. This critical_radius function can then be simplified to just self.model.blake_critical_radius(self.ambient_pressure).

This would centralize the model creation and make the code more robust.

- Added `libfontconfig1-dev` and `pkg-config` dependencies to `.github/workflows/performance-benchmarking.yml` for Linux runners because `yeslogic-fontconfig-sys` relies on them to compile, addressing CI build failures.

Co-authored-by: ryancinsight <55164720+ryancinsight@users.noreply.github.com>
Copy link

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

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

Review by RecurseML

🔍 Review performed on 1d431b3..ab26b64

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (8)

crates/cfd-python/src/bifurcation.rs
crates/cfd-python/src/cavitation.rs
crates/cfd-python/src/hemolysis.rs
crates/cfd-python/src/lib.rs
crates/cfd-python/src/solver_2d/serpentine.rs
crates/cfd-python/src/solver_2d/venturi.rs
crates/cfd-python/src/womersley.rs
validation/cross_validate_rust_python.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
crates/cfd-python/src/cavitation.rs (1)

32-43: Eliminate duplicated RayleighPlesset initialization.

The same model parameters are hardcoded in both new() (lines 17-24) and critical_radius() (lines 34-41). Consider extracting to a helper function or accessing the model stored in the classifier.

♻️ Suggested refactor to reduce duplication
+fn default_rayleigh_plesset() -> RayleighPlesset<f64> {
+    RayleighPlesset {
+        initial_radius: 10e-6,
+        liquid_density: 997.0,
+        liquid_viscosity: 0.001,
+        surface_tension: 0.0728,
+        vapor_pressure: 2339.0,
+        polytropic_index: 1.4,
+    }
+}
+
 /// Calculator for Blake Threshold for cavitation
 #[pyclass(name = "BlakeThreshold")]
 pub struct PyBlakeThreshold {
     classifier: CavitationRegimeClassifier<f64>,
     ambient_pressure: f64,
+    model: RayleighPlesset<f64>,
 }

 #[pymethods]
 impl PyBlakeThreshold {
     #[new]
     fn new(ambient_pressure: f64) -> Self {
-        let model = RayleighPlesset {
-            initial_radius: 10e-6,
-            liquid_density: 997.0,
-            liquid_viscosity: 0.001,
-            surface_tension: 0.0728,
-            vapor_pressure: 2339.0,
-            polytropic_index: 1.4,
-        };
+        let model = default_rayleigh_plesset();

         PyBlakeThreshold {
-            classifier: CavitationRegimeClassifier::new(model, ambient_pressure, None, None),
+            classifier: CavitationRegimeClassifier::new(model.clone(), ambient_pressure, None, None),
             ambient_pressure,
+            model,
         }
     }

     fn critical_radius(&self) -> f64 {
-        let model = RayleighPlesset {
-            initial_radius: 10e-6,
-            liquid_density: 997.0,
-            liquid_viscosity: 0.001,
-            surface_tension: 0.0728,
-            vapor_pressure: 2339.0,
-            polytropic_index: 1.4,
-        };
-        model.blake_critical_radius(self.ambient_pressure)
+        self.model.blake_critical_radius(self.ambient_pressure)
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/cfd-python/src/cavitation.rs` around lines 32 - 43, critical_radius
currently reconstructs a RayleighPlesset with hardcoded parameters duplicated
from new(); remove the duplication by extracting the shared initialization into
a single helper and using it from both places—either add a field (e.g.,
rayleigh_model: RayleighPlesset) to the struct initialized in new() and call
that field in critical_radius(), or implement a private method like fn
rayleigh_plesset_model(&self) -> RayleighPlesset that returns the configured
model and call it from new() and critical_radius(); update critical_radius to
call the helper/field (instead of re-creating the model) and adjust new()/struct
definition accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@validation/cross_validate_rust_python.py`:
- Around line 172-192: Two print statements use f-strings without placeholders —
remove the unnecessary 'f' prefix to avoid misleading code and tiny overhead:
change the print(f"\nRust implementation (via cfd_python.GiersiepenModel):") and
print(f"\nComparison:") to plain print(...) calls; keep all other prints that
use formatting (like the formatted table and diff calculations using
giersiepen_python and hemolysis_model.calculate_damage) unchanged.
- Around line 57-75: Change the two print calls that use f-strings but have no
interpolations to plain strings: replace print(f"\nRust implementation (via
cfd_python.BlakeThreshold):") and replace print(f"\nComparison:") with
print("\nRust implementation (via cfd_python.BlakeThreshold):") and
print("\nComparison:") respectively; keep all other f-strings (e.g., the ones
printing R_c, P_Blake, rc_diff, pb_diff) unchanged.
- Around line 115-134: The two print statements using unnecessary f-strings
should be changed to plain string literals: remove the leading `f` from the
print that prints the Rust implementation header (the print currently before
creating `cy_blood = cfd_python.CarreauYasudaBlood()`) and from the print that
outputs the comparison header (the print before checking `all_match`); keep all
other prints (those that format variables like `gamma_dot`, `mu_rust`, and
`diff_pct`) as-is so `test_shear_rates`, `carreau_yasuda_python`, and
`cy_blood.viscosity` usage remains unchanged.

---

Nitpick comments:
In `@crates/cfd-python/src/cavitation.rs`:
- Around line 32-43: critical_radius currently reconstructs a RayleighPlesset
with hardcoded parameters duplicated from new(); remove the duplication by
extracting the shared initialization into a single helper and using it from both
places—either add a field (e.g., rayleigh_model: RayleighPlesset) to the struct
initialized in new() and call that field in critical_radius(), or implement a
private method like fn rayleigh_plesset_model(&self) -> RayleighPlesset that
returns the configured model and call it from new() and critical_radius();
update critical_radius to call the helper/field (instead of re-creating the
model) and adjust new()/struct definition accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ceacc20-c978-4cf1-a4a0-d9ae99777759

📥 Commits

Reviewing files that changed from the base of the PR and between 1d431b3 and ab26b64.

📒 Files selected for processing (8)
  • crates/cfd-python/src/bifurcation.rs
  • crates/cfd-python/src/cavitation.rs
  • crates/cfd-python/src/hemolysis.rs
  • crates/cfd-python/src/lib.rs
  • crates/cfd-python/src/solver_2d/serpentine.rs
  • crates/cfd-python/src/solver_2d/venturi.rs
  • crates/cfd-python/src/womersley.rs
  • validation/cross_validate_rust_python.py

Comment on lines +57 to +75
print(f"\nRust implementation (via cfd_python.BlakeThreshold):")
blake_calculator = cfd_python.BlakeThreshold(ambient_pressure=P_inf)
R_c_rust = blake_calculator.critical_radius()
P_Blake_rust = blake_calculator.threshold()

print(f" R_c = {R_c_rust*1e6:.4f} μm")
print(f" P_Blake = {P_Blake_rust:.2f} Pa = {P_Blake_rust/1000:.2f} kPa")

rc_diff = abs(R_c_rust - R_c_python) / R_c_python * 100
pb_diff = abs(P_Blake_rust - P_Blake_python) / P_Blake_python * 100

print(f"\nComparison:")
print(f" R_c diff: {rc_diff:.4e}%")
print(f" P_Blake diff: {pb_diff:.4e}%")

if rc_diff < 1e-4 and pb_diff < 1e-4:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unnecessary f-string prefixes.

Lines 57 and 68 use f-strings without placeholders. Use regular strings instead.

🧹 Proposed fix
-    print(f"\nRust implementation (via cfd_python.BlakeThreshold):")
+    print("\nRust implementation (via cfd_python.BlakeThreshold):")
     blake_calculator = cfd_python.BlakeThreshold(ambient_pressure=P_inf)
     R_c_rust = blake_calculator.critical_radius()
     P_Blake_rust = blake_calculator.threshold()

     print(f"  R_c = {R_c_rust*1e6:.4f} μm")
     print(f"  P_Blake = {P_Blake_rust:.2f} Pa = {P_Blake_rust/1000:.2f} kPa")

     rc_diff = abs(R_c_rust - R_c_python) / R_c_python * 100
     pb_diff = abs(P_Blake_rust - P_Blake_python) / P_Blake_python * 100

-    print(f"\nComparison:")
+    print("\nComparison:")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(f"\nRust implementation (via cfd_python.BlakeThreshold):")
blake_calculator = cfd_python.BlakeThreshold(ambient_pressure=P_inf)
R_c_rust = blake_calculator.critical_radius()
P_Blake_rust = blake_calculator.threshold()
print(f" R_c = {R_c_rust*1e6:.4f} μm")
print(f" P_Blake = {P_Blake_rust:.2f} Pa = {P_Blake_rust/1000:.2f} kPa")
rc_diff = abs(R_c_rust - R_c_python) / R_c_python * 100
pb_diff = abs(P_Blake_rust - P_Blake_python) / P_Blake_python * 100
print(f"\nComparison:")
print(f" R_c diff: {rc_diff:.4e}%")
print(f" P_Blake diff: {pb_diff:.4e}%")
if rc_diff < 1e-4 and pb_diff < 1e-4:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
print("\nRust implementation (via cfd_python.BlakeThreshold):")
blake_calculator = cfd_python.BlakeThreshold(ambient_pressure=P_inf)
R_c_rust = blake_calculator.critical_radius()
P_Blake_rust = blake_calculator.threshold()
print(f" R_c = {R_c_rust*1e6:.4f} μm")
print(f" P_Blake = {P_Blake_rust:.2f} Pa = {P_Blake_rust/1000:.2f} kPa")
rc_diff = abs(R_c_rust - R_c_python) / R_c_python * 100
pb_diff = abs(P_Blake_rust - P_Blake_python) / P_Blake_python * 100
print("\nComparison:")
print(f" R_c diff: {rc_diff:.4e}%")
print(f" P_Blake diff: {pb_diff:.4e}%")
if rc_diff < 1e-4 and pb_diff < 1e-4:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
🧰 Tools
🪛 Ruff (0.15.4)

[error] 57-57: f-string without any placeholders

Remove extraneous f prefix

(F541)


[error] 68-68: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@validation/cross_validate_rust_python.py` around lines 57 - 75, Change the
two print calls that use f-strings but have no interpolations to plain strings:
replace print(f"\nRust implementation (via cfd_python.BlakeThreshold):") and
replace print(f"\nComparison:") with print("\nRust implementation (via
cfd_python.BlakeThreshold):") and print("\nComparison:") respectively; keep all
other f-strings (e.g., the ones printing R_c, P_Blake, rc_diff, pb_diff)
unchanged.

Comment on lines +115 to +134
print(f"\nRust implementation (via cfd_python.CarreauYasudaBlood):")
cy_blood = cfd_python.CarreauYasudaBlood()

# Try to test if we can create a blood model
# Note: This depends on cfd_python API structure
print(f"\n TODO: Add cfd_python API test if blood model is exposed")
print(f"{'Shear Rate (s⁻¹)':>20} {'μ_rust (mPa·s)':>15} {'Diff %':>15}")
print("-" * 55)

all_match = True
for gamma_dot in test_shear_rates:
mu_python = carreau_yasuda_python(gamma_dot)
mu_rust = cy_blood.viscosity(gamma_dot)
diff_pct = abs(mu_rust - mu_python) / mu_python * 100
print(f"{gamma_dot:20.0f} {mu_rust * 1000:15.4f} {diff_pct:14.4e}%")
if diff_pct > 1e-4:
all_match = False

print(f"\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if the Rust CarreauYasudaBlood uses the same default parameters as the Python validation script

# Search for Carreau-Yasuda default parameters in cfd-core
rg -n "normal_blood|zero_shear|infinite_shear|lambda|relaxation" --type rust crates/cfd-core/src/physics/fluid/

# Check the blood.rs file specifically for default values
ast-grep --pattern 'fn normal_blood() -> Self {
  $$$
}'

Repository: ryancinsight/CFDrs

Length of output: 8534


🏁 Script executed:

# Get constant values
cat -n crates/cfd-core/src/physics/fluid/blood/constants.rs | head -50

# Check the validation file for f-string usage and parameters
cat -n validation/cross_validate_rust_python.py | sed -n '110,140p'

Repository: ryancinsight/CFDrs

Length of output: 3243


Remove unnecessary f-string prefixes.

Lines 115 and 130 use f-strings without placeholders. Remove the f prefix from both lines.

🧹 Proposed fix
-    print(f"\nRust implementation (via cfd_python.CarreauYasudaBlood):")
+    print("\nRust implementation (via cfd_python.CarreauYasudaBlood):")
     cy_blood = cfd_python.CarreauYasudaBlood()
     
     print(f"{'Shear Rate (s⁻¹)':>20} {'μ_rust (mPa·s)':>15} {'Diff %':>15}")
     print("-" * 55)

     all_match = True
     for gamma_dot in test_shear_rates:
         mu_python = carreau_yasuda_python(gamma_dot)
         mu_rust = cy_blood.viscosity(gamma_dot)
         diff_pct = abs(mu_rust - mu_python) / mu_python * 100
         print(f"{gamma_dot:20.0f} {mu_rust * 1000:15.4f} {diff_pct:14.4e}%")
         if diff_pct > 1e-4:
             all_match = False

-    print(f"\nComparison:")
+    print("\nComparison:")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(f"\nRust implementation (via cfd_python.CarreauYasudaBlood):")
cy_blood = cfd_python.CarreauYasudaBlood()
# Try to test if we can create a blood model
# Note: This depends on cfd_python API structure
print(f"\n TODO: Add cfd_python API test if blood model is exposed")
print(f"{'Shear Rate (s⁻¹)':>20} {'μ_rust (mPa·s)':>15} {'Diff %':>15}")
print("-" * 55)
all_match = True
for gamma_dot in test_shear_rates:
mu_python = carreau_yasuda_python(gamma_dot)
mu_rust = cy_blood.viscosity(gamma_dot)
diff_pct = abs(mu_rust - mu_python) / mu_python * 100
print(f"{gamma_dot:20.0f} {mu_rust * 1000:15.4f} {diff_pct:14.4e}%")
if diff_pct > 1e-4:
all_match = False
print(f"\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
print("\nRust implementation (via cfd_python.CarreauYasudaBlood):")
cy_blood = cfd_python.CarreauYasudaBlood()
print(f"{'Shear Rate (s⁻¹)':>20} {'μ_rust (mPa·s)':>15} {'Diff %':>15}")
print("-" * 55)
all_match = True
for gamma_dot in test_shear_rates:
mu_python = carreau_yasuda_python(gamma_dot)
mu_rust = cy_blood.viscosity(gamma_dot)
diff_pct = abs(mu_rust - mu_python) / mu_python * 100
print(f"{gamma_dot:20.0f} {mu_rust * 1000:15.4f} {diff_pct:14.4e}%")
if diff_pct > 1e-4:
all_match = False
print("\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
🧰 Tools
🪛 Ruff (0.15.4)

[error] 115-115: f-string without any placeholders

Remove extraneous f prefix

(F541)


[error] 130-130: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@validation/cross_validate_rust_python.py` around lines 115 - 134, The two
print statements using unnecessary f-strings should be changed to plain string
literals: remove the leading `f` from the print that prints the Rust
implementation header (the print currently before creating `cy_blood =
cfd_python.CarreauYasudaBlood()`) and from the print that outputs the comparison
header (the print before checking `all_match`); keep all other prints (those
that format variables like `gamma_dot`, `mu_rust`, and `diff_pct`) as-is so
`test_shear_rates`, `carreau_yasuda_python`, and `cy_blood.viscosity` usage
remains unchanged.

Comment on lines +172 to +192
print(f"\nRust implementation (via cfd_python.GiersiepenModel):")
hemolysis_model = cfd_python.GiersiepenModel()

print(f"{'Stress (Pa)':>12} {'Time (s)':>12} {'Damage_rust':>15} {'Diff %':>15}")
print("-" * 55)

all_match = True
for tau, t in test_cases:
damage_python = giersiepen_python(tau, t)
damage_rust = hemolysis_model.calculate_damage(tau, t)
diff_pct = abs(damage_rust - damage_python) / damage_python * 100
print(f"{tau:12.1f} {t:12.2f} {damage_rust:15.6f} {diff_pct:14.4e}%")

if diff_pct > 1e-4:
all_match = False

print(f"\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unnecessary f-string prefixes.

Lines 172 and 188 use f-strings without placeholders.

🧹 Proposed fix
-    print(f"\nRust implementation (via cfd_python.GiersiepenModel):")
+    print("\nRust implementation (via cfd_python.GiersiepenModel):")
     hemolysis_model = cfd_python.GiersiepenModel()

     print(f"{'Stress (Pa)':>12} {'Time (s)':>12} {'Damage_rust':>15} {'Diff %':>15}")
     print("-" * 55)

     all_match = True
     for tau, t in test_cases:
         damage_python = giersiepen_python(tau, t)
         damage_rust = hemolysis_model.calculate_damage(tau, t)
         diff_pct = abs(damage_rust - damage_python) / damage_python * 100
         print(f"{tau:12.1f} {t:12.2f} {damage_rust:15.6f} {diff_pct:14.4e}%")

         if diff_pct > 1e-4:
             all_match = False

-    print(f"\nComparison:")
+    print("\nComparison:")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(f"\nRust implementation (via cfd_python.GiersiepenModel):")
hemolysis_model = cfd_python.GiersiepenModel()
print(f"{'Stress (Pa)':>12} {'Time (s)':>12} {'Damage_rust':>15} {'Diff %':>15}")
print("-" * 55)
all_match = True
for tau, t in test_cases:
damage_python = giersiepen_python(tau, t)
damage_rust = hemolysis_model.calculate_damage(tau, t)
diff_pct = abs(damage_rust - damage_python) / damage_python * 100
print(f"{tau:12.1f} {t:12.2f} {damage_rust:15.6f} {diff_pct:14.4e}%")
if diff_pct > 1e-4:
all_match = False
print(f"\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
print("\nRust implementation (via cfd_python.GiersiepenModel):")
hemolysis_model = cfd_python.GiersiepenModel()
print(f"{'Stress (Pa)':>12} {'Time (s)':>12} {'Damage_rust':>15} {'Diff %':>15}")
print("-" * 55)
all_match = True
for tau, t in test_cases:
damage_python = giersiepen_python(tau, t)
damage_rust = hemolysis_model.calculate_damage(tau, t)
diff_pct = abs(damage_rust - damage_python) / damage_python * 100
print(f"{tau:12.1f} {t:12.2f} {damage_rust:15.6f} {diff_pct:14.4e}%")
if diff_pct > 1e-4:
all_match = False
print("\nComparison:")
if all_match:
print(" ✓ MATCH")
else:
print(" ✗ MISMATCH")
🧰 Tools
🪛 Ruff (0.15.4)

[error] 172-172: f-string without any placeholders

Remove extraneous f prefix

(F541)


[error] 188-188: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@validation/cross_validate_rust_python.py` around lines 172 - 192, Two print
statements use f-strings without placeholders — remove the unnecessary 'f'
prefix to avoid misleading code and tiny overhead: change the print(f"\nRust
implementation (via cfd_python.GiersiepenModel):") and print(f"\nComparison:")
to plain print(...) calls; keep all other prints that use formatting (like the
formatted table and diff calculations using giersiepen_python and
hemolysis_model.calculate_damage) unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant