Skip to content

Conversation

@hyeoksu-lee
Copy link
Contributor

@hyeoksu-lee hyeoksu-lee commented Nov 30, 2025

User description

User description

Description

This PR removes duplicated codes by

  • merging s_convert_species_to_mixture_variables_bubbles into s_convert_species_to_mixture_variables
  • merging s_convert_species_to_mixture_variables_bubbles_acc into s_convert_species_to_mixture_variables_acc
  • replacing many duplicated codes, which compute partial densities and volume fractions, with a new subroutine s_compute_species_fraction
  • removing unnecessarily duplicated codes, for example,
#ifdef MFC_SIMULATION
            @:ALLOCATE(bubrs_vc(1:nb))
#else
            @:ALLOCATE(bubrs_vc(1:nb))
#endif
  • simplifying mixture if-statements for the EE bubbles

Type of change

  • Something else

Scope

  • This PR comprises a set of related changes with a common goal

If you cannot check the above box, please split your PR into multiple PRs that each have a common goal.

How Has This Been Tested?

test suite passed on MacBook M4 Pro and Carpenter GNU

Checklist

  • I have added comments for the new code
  • I added Doxygen docstrings to the new code
  • I have made corresponding changes to the documentation (docs/)
  • I have added regression tests to the test suite so that people can verify in the future that the feature is behaving as expected
  • I have added example cases in examples/ that demonstrate my new feature performing as expected.
    They run to completion and demonstrate "interesting physics"
  • I ran ./mfc.sh format before committing my code
  • New and existing tests pass locally with my changes, including with GPU capability enabled (both NVIDIA hardware with NVHPC compilers and AMD hardware with CRAY compilers) and disabled
  • This PR does not introduce any repeated code (it follows the DRY principle)
  • I cannot think of a way to condense this code and reduce any introduced additional line count

If your code changes any code source files (anything in src/simulation)

To make sure the code is performing as expected on GPU devices, I have:

  • Checked that the code compiles using NVHPC compilers
  • Checked that the code compiles using CRAY compilers
  • Ran the code on either V100, A100, or H100 GPUs and ensured the new feature performed as expected (the GPU results match the CPU results)
  • Ran the code on MI200+ GPUs and ensure the new features performed as expected (the GPU results match the CPU results)
  • Enclosed the new feature via nvtx ranges so that they can be identified in profiles
  • Ran a Nsight Systems profile using ./mfc.sh run XXXX --gpu -t simulation --nsys, and have attached the output file (.nsys-rep) and plain text results to this PR
  • Ran a Rocprof Systems profile using ./mfc.sh run XXXX --gpu -t simulation --rsys --hip-trace, and have attached the output file and plain text results to this PR.
  • Ran my code using various numbers of different GPUs (1, 2, and 8, for example) in parallel and made sure that the results scale similarly to what happens if you run without the new code/feature

PR Type

Enhancement

Description

  • Removed duplicate subroutines for EE bubbles by merging s_convert_species_to_mixture_variables_bubbles and s_convert_species_to_mixture_variables_bubbles_acc into unified routines

  • Introduced new s_compute_species_fraction subroutine to consolidate partial density and volume fraction computation logic

  • Simplified mixture if-statements by eliminating special-case handling for bubbles_euler model

  • Removed redundant conditional compilation blocks with identical code in both branches

  • Updated checker to simplify bubble factor logic and remove redundant validation constraints

Diagram Walkthrough

flowchart LR
  A["Duplicate bubble<br/>conversion routines"] -->|merge| B["Unified conversion<br/>routines"]
  C["Scattered fraction<br/>computation logic"] -->|consolidate| D["s_compute_species_fraction"]
  E["Complex conditional<br/>logic"] -->|simplify| F["Streamlined<br/>if-statements"]
  B --> G["Cleaner codebase"]
  D --> G
  F --> G
Loading

File Walkthrough

Relevant files
Enhancement
m_checker_common.fpp
Simplify stiffened EOS checker logic                                         

src/common/m_checker_common.fpp

  • Simplified bubble factor assignment by removing condition check on
    num_fluids == 1
  • Changed loop to iterate over num_fluids + bub_fac instead of separate
    handling
  • Removed redundant validation constraints for gamma and pi_inf that
    duplicated earlier checks
+2/-10   
m_variables_conversion.fpp
Merge bubble-specific routines and extract fraction computation

src/common/m_variables_conversion.fpp

  • Removed public exports of
    s_convert_species_to_mixture_variables_bubbles and
    s_convert_species_to_mixture_variables_bubbles_acc
  • Added public export of new s_compute_species_fraction subroutine
  • Deleted entire s_convert_species_to_mixture_variables_bubbles
    subroutine (135 lines)
  • Deleted entire s_convert_species_to_mixture_variables_bubbles_acc
    subroutine (83 lines)
  • Refactored s_convert_species_to_mixture_variables to use unified logic
    for bubbles_euler case
  • Refactored s_convert_species_to_mixture_variables_acc to handle
    bubbles_euler within main routine
  • Created new s_compute_species_fraction subroutine to extract common
    fraction computation logic
  • Removed redundant #ifdef MFC_SIMULATION / #else blocks with identical
    allocations
  • Simplified Reynolds number computation by adding viscous check wrapper
  • Updated module initialization to remove duplicate conditional
    compilation blocks
+88/-311
m_bubbles_EE.fpp
Simplify bubble mixture property calculations                       

src/simulation/m_bubbles_EE.fpp

  • Simplified mixture property computation by consolidating conditional
    logic for single vs multiple fluids
  • Removed separate branches for mpp_lim with different fluid counts
  • Removed redundant assignment of myRho from q_prim_vf(1)%sf
  • Unified computation of myRho, n_tait, and B_tait into single if-else
    block
+9/-17   
m_bubbles_EL.fpp
Use unified fraction computation routine                                 

src/simulation/m_bubbles_EL.fpp

  • Replaced manual loop extracting alpha_rho and alpha with call to
    s_compute_species_fraction
  • Removed 5-line GPU loop in favor of unified subroutine call
+1/-5     
m_cbc.fpp
Remove bubbles_euler special case handling                             

src/simulation/m_cbc.fpp

  • Removed conditional branch checking bubbles_euler before mixture
    variable conversion
  • Unified to single call to s_convert_species_to_mixture_variables_acc
    for all cases
+1/-5     
m_hyperelastic.fpp
Use unified fraction computation routine                                 

src/simulation/m_hyperelastic.fpp

  • Replaced manual loop extracting alpha_rho_k and alpha_k with call to
    s_compute_species_fraction
  • Removed 5-line GPU loop in favor of unified subroutine call
+3/-5     
m_ibm.fpp
Remove bubbles_euler special case handling                             

src/simulation/m_ibm.fpp

  • Removed conditional branch checking bubbles_euler before mixture
    variable conversion
  • Unified to single call to s_convert_species_to_mixture_variables_acc
    for all cases
+0/-3     
m_sim_helpers.fpp
Consolidate fraction extraction and mixture conversion     

src/simulation/m_sim_helpers.fpp

  • Replaced manual conditional logic for extracting alpha and alpha_rho
    with call to s_compute_species_fraction
  • Removed 30-line conditional block handling igr cases
  • Removed conditional branch checking bubbles_euler before mixture
    variable conversion
  • Unified to single call to s_convert_species_to_mixture_variables_acc
    for all cases
+1/-23   

CodeAnt-AI Description

Correct mixture properties and species fractions for EE bubble simulations

What Changed

  • Corrected how density, compressibility, and stiffness are computed for Eulerian–Eulerian bubble cases, including a dedicated path for single‑fluid setups so bubble mixtures use the intended fluid properties
  • Centralized the computation and limiting of partial densities and volume fractions into a shared routine, ensuring non‑negative, normalized species fractions in the core solver, EE/EL bubble models, and hyperelastic module
  • Updated mixture conversions in boundary conditions and immersed boundary handling to use the same consistent species‑to‑mixture mapping, aligning mixture properties at inlets, outlets, and ghost cells with the interior solution

Impact

✅ More stable EE bubble simulations
✅ Correct mixture properties for single-fluid bubble setups
✅ Consistent mixture behavior at boundaries and immersed interfaces

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

Release Notes

  • Refactor
    • Consolidated internal computation paths for multi-phase flow simulations across different configurations.
    • Unified species fraction calculation logic, reducing code duplication and improving maintainability.
    • Simplified control flow by removing specialized code branches while preserving existing behavior.
    • Extended validation coverage for bubble dynamics scenarios with multiple fluid components.

✏️ Tip: You can customize this high-level summary in your review settings.

@codeant-ai
Copy link

codeant-ai bot commented Nov 30, 2025

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 30, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The changes consolidate bubble-specific variable conversion paths into a generic species-fraction computation routine. A new public subroutine s_compute_species_fraction replaces direct bubble-specific conversions across multiple simulation modules, while removing two specialized procedures from the public API. The validation logic for bubbles_euler cases has been broadened.

Changes

Cohort / File(s) Summary
Core variable conversion consolidation
src/common/m_variables_conversion.fpp
Added new public s_compute_species_fraction routine to compute partial densities and volume fractions generically; removed exported bubbles-specific procedures; refactored mixture variable conversion paths to use the new generic routine instead of inline bubble-specific logic.
Bubble model implementations
src/simulation/m_bubbles_EE.fpp, src/simulation/m_bubbles_EL.fpp
Updated to call or utilize s_compute_species_fraction for fraction extraction; simplified accumulation loops and consolidated single/multi-fluid initialization logic.
Conversion path simplifications
src/simulation/m_cbc.fpp, src/simulation/m_ibm.fpp
Removed conditional branches selecting between general and bubbles-specific conversion procedures; now unconditionally call general conversion routine regardless of bubbles_euler flag.
Integration refactoring
src/simulation/m_hyperelastic.fpp, src/simulation/m_sim_helpers.fpp
Replaced inline per-fluid loops extracting species fractions with centralized s_compute_species_fraction calls; consolidated GPU loop and branch logic in enthalpy assembly.
Validation scope expansion
toolchain/mfc/case_validator.py
Broadened bub_fac calculation to enable extra fluid slot validation for all bubbles_euler cases (not just single-component); expands stiffened EOS parameter validation to additional fluid slot.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • src/common/m_variables_conversion.fpp: Verify the new s_compute_species_fraction routine handles all upstream use cases correctly, including single/multi-fluid and with/without bubbles_euler edge cases.
  • Cross-file consistency: Ensure all five simulation module updates call the new routine with correct parameters and handle return values appropriately.
  • Behavioral equivalence: Confirm that removal of bubbles-specific procedures does not introduce regressions in bubble dynamics or accumulation logic.
  • Validation changes in case_validator.py: Verify the broadened scope correctly validates extra fluid slots without false positives.

Suggested labels

size:M, refactor, bubbles

Suggested reviewers

  • sbryngelson
  • wilfonba

Poem

🐰 Hops of joy for cleaner code,
Bubbles consolidated, lighter load!
One generic fraction, tried and true,
Replaces many paths—oh what a breakthrough!
Species dance more gracefully now,
Unified logic takes a bow!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective of consolidating duplicate code in bubble mixture rules for EE simulations.
Description check ✅ Passed The description is comprehensive with clear sections covering changes, testing, and most checklist items, though some GPU-related items remain unchecked.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b7ab1c and f882347.

📒 Files selected for processing (1)
  • toolchain/mfc/case_validator.py (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Code Cleanliness Check
  • GitHub Check: Coverage Test on CodeCov
  • GitHub Check: Github (ubuntu, no-mpi, single, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, debug, false)
  • GitHub Check: Github (macos, mpi, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, no-debug, true)
  • GitHub Check: Github (ubuntu, mpi, debug, true)
  • GitHub Check: Github (macos, mpi, debug, false)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Build & Publish
🔇 Additional comments (2)
toolchain/mfc/case_validator.py (2)

375-397: Validation loop correctly includes the extra fluid slot.

The loop range range(1, num_fluids + 1 + bub_fac) properly extends validation to the num_fluids + 1 slot when bubbles_euler is active. The positivity checks and model-specific restrictions are applied uniformly to all slots, including the additional one. Since model_eqns = 1 is already prohibited with bubbles_euler (line 265), the restrictions on lines 392-397 are harmless for the extra slot and maintain code uniformity.


372-373: LGTM—simplified bubble factor logic.

The removal of the single-fluid restriction (broadening bub_fac to apply whenever bubbles_euler is true) aligns with the PR's introduction of s_compute_species_fraction, which now handles extended fluid sets uniformly. The conditional assignment is clear and correct.

Verify that the Fortran code properly initializes and uses fluid_pp(num_fluids + 1) parameters in multi-fluid + bubbles_euler scenarios (e.g., when num_fluids = 2 and bubbles_euler = T, does the code correctly populate and reference fluid_pp(3))?


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.

@qodo-merge-pro
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Issue

Loop now iterates to num_fluids + bub_fac when bubbles_euler is true, but gamma/pi_inf/cv are accessed as fluid_pp(i) for i > num_fluids; verify that fluid_pp is sized/initialized for the extra bubble entry to avoid out-of-bounds or use of uninitialized parameters.

if (bubbles_euler) bub_fac = 1

do i = 1, num_fluids + bub_fac
    call s_int_to_str(i, iStr)
    @:PROHIBIT(.not. f_is_default(fluid_pp(i)%gamma) .and. fluid_pp(i)%gamma <= 0._wp, &
        "fluid_pp("//trim(iStr)//")%gamma must be positive")

    @:PROHIBIT(model_eqns == 1 .and. (.not. f_is_default(fluid_pp(i)%gamma)), &
        "model_eqns = 1 does not support fluid_pp("//trim(iStr)//")%gamma")

    @:PROHIBIT(.not. f_is_default(fluid_pp(i)%pi_inf) .and. fluid_pp(i)%pi_inf < 0._wp, &
        "fluid_pp("//trim(iStr)//")%pi_inf must be non-negative")

    @:PROHIBIT(model_eqns == 1 .and. (.not. f_is_default(fluid_pp(i)%pi_inf)), &
        "model_eqns = 1 does not support fluid_pp("//trim(iStr)//")%pi_inf")

    @:PROHIBIT(fluid_pp(i)%cv < 0._wp, &
        "fluid_pp("//trim(iStr)//")%cv must be positive")
end do
Logic Change

In s_compute_species_fraction, alpha_K(1) is set to q_vf(advxb)%sf for the single-fluid bubbles_euler case after normalization; confirm this does not conflict with earlier mpp_lim normalization and that downstream code expects alpha_K possibly not equal to 1 in this special case.

if (mpp_lim) then
    do i = 1, num_fluids
        alpha_rho_K(i) = max(0._wp, alpha_rho_K(i))
        alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
    end do
    alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
end if

if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
Physical Consistency

B_tait is now accumulated using pi_infs(ii)/pi_fac for multi-fluid but also set to pi_infs(1)/pi_fac for single-fluid; ensure consistent use of pi_fac in both branches and that previous behavior didn’t require weighting by raw pi_infs without division.

if (num_fluids == 1) then
    myRho = myalpha_rho(1)
    n_tait = gammas(1)
    B_tait = pi_infs(1)/pi_fac
else
    myRho = 0._wp
    n_tait = 0._wp
    B_tait = 0._wp

    $:GPU_LOOP(parallelism='[seq]')
    do ii = 1, num_fluids
        myRho = myRho + myalpha_rho(ii)
        n_tait = n_tait + myalpha(ii)*gammas(ii)
        B_tait = B_tait + myalpha(ii)*pi_infs(ii)/pi_fac
    end do
end if

n_tait = 1._wp/n_tait + 1._wp !make this the usual little 'gamma'
B_tait = B_tait*(n_tait - 1)/n_tait ! make this the usual pi_inf

@codeant-ai codeant-ai bot added the size:L This PR changes 100-499 lines, ignoring generated files label Nov 30, 2025
Copy link
Contributor

Choose a reason for hiding this comment

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

High-level Suggestion

The new s_compute_species_fraction subroutine has a confusing structure with a conditional override at the end. Refactor it to have clear, separate logic paths for each physical model to improve readability. [High-level, importance: 7]

Solution Walkthrough:

Before:

subroutine s_compute_species_fraction(...)
    if (num_fluids == 1) then
        alpha_rho_K(1) = ...
        if (igr .or. bubbles_euler) then
            alpha_K(1) = 1._wp
        else
            alpha_K(1) = ...
        end if
    else
        ! ... logic for num_fluids > 1
    end if

    if (mpp_lim) then
        ! ... apply limits and normalize alpha_K
    end if

    ! Override for a specific case
    if (num_fluids == 1 .and. bubbles_euler) then
        alpha_K(1) = q_vf(advxb)%sf(k, l, r)
    end if
end subroutine

After:

subroutine s_compute_species_fraction(...)
    if (num_fluids == 1 .and. bubbles_euler) then
        alpha_rho_K(1) = q_vf(contxb)%sf(k, l, r)
        alpha_K(1) = q_vf(advxb)%sf(k, l, r)
    else if (num_fluids == 1) then
        alpha_rho_K(1) = ...
        if (igr) then
            alpha_K(1) = 1._wp
        else
            alpha_K(1) = ...
        end if
    else
        ! ... logic for num_fluids > 1
    end if

    if (mpp_lim) then
        ! ... apply limits and normalize alpha_K
    end if
end subroutine

alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
end if

if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: In s_compute_species_fraction, prevent an unconditional overwrite of alpha_K(1) when bubbles_euler is true. Add a check for .not. igr to the condition to respect the logic for ideal gas relaxation. [possible issue, importance: 8]

Suggested change
if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
if (num_fluids == 1 .and. bubbles_euler .and. .not. igr) alpha_K(1) = q_vf(advxb)%sf(k, l, r)

Comment on lines 262 to 263
n_tait = 1._wp/n_tait + 1._wp !make this the usual little 'gamma'
B_tait = B_tait*(n_tait - 1)/n_tait ! make this the usual pi_inf
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Prevent a potential division-by-zero error in the calculation of n_tait and B_tait. Use max(n_tait, sgm_eps) in the denominator to ensure it is non-zero. [possible issue, importance: 8]

Suggested change
n_tait = 1._wp/n_tait + 1._wp !make this the usual little 'gamma'
B_tait = B_tait*(n_tait - 1)/n_tait ! make this the usual pi_inf
n_tait = 1._wp/max(n_tait, sgm_eps) + 1._wp !make this the usual little 'gamma'
B_tait = B_tait*(n_tait - 1)/max(n_tait, sgm_eps) ! make this the usual pi_inf

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
src/common/m_variables_conversion.fpp (2)

1343-1351: Use consistent tolerance constant; clarify bubbles_euler alpha override.

Two observations:

  1. Inconsistent tolerance: Line 1348 uses hardcoded 1.e-16_wp, while the rest of the codebase uses sgm_eps for similar purposes (see lines 347, 379, 739).

  2. Confusing logic flow: For single-fluid bubbles_euler, alpha_K(1) is set to 1._wp at line 1323, then potentially processed by mpp_lim, and finally overwritten at line 1351. Consider restructuring to make the intent clearer.

Apply this diff for consistency:

         if (mpp_lim) then
             do i = 1, num_fluids
                 alpha_rho_K(i) = max(0._wp, alpha_rho_K(i))
                 alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
             end do
-            alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
+            alpha_K = alpha_K/max(sum(alpha_K), sgm_eps)
         end if
 
-        if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
+        ! For single-fluid bubbles_euler, alpha_K represents void fraction from advection variable
+        if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)

1312-1318: Add Doxygen-style documentation for the new public subroutine.

As a public subroutine called from multiple modules (per the AI summary: m_hyperelastic.fpp, m_ibm.fpp, m_cbc.fpp, etc.), this should have documentation describing its purpose and parameters.

Add documentation header:

    !>  Computes partial densities (alpha_rho_K) and volume fractions (alpha_K)
    !!  for species at a given cell location, handling igr and bubbles_euler modes.
    !!  @param q_vf Conservative or primitive variables
    !!  @param k First-coordinate cell index
    !!  @param l Second-coordinate cell index
    !!  @param r Third-coordinate cell index
    !!  @param alpha_rho_K Partial densities for each fluid (output)
    !!  @param alpha_K Volume fractions for each fluid (output)
    subroutine s_compute_species_fraction(q_vf, k, l, r, alpha_rho_K, alpha_K)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2ce07d and 1568228.

📒 Files selected for processing (8)
  • src/common/m_checker_common.fpp (1 hunks)
  • src/common/m_variables_conversion.fpp (7 hunks)
  • src/simulation/m_bubbles_EE.fpp (1 hunks)
  • src/simulation/m_bubbles_EL.fpp (1 hunks)
  • src/simulation/m_cbc.fpp (1 hunks)
  • src/simulation/m_hyperelastic.fpp (1 hunks)
  • src/simulation/m_ibm.fpp (0 hunks)
  • src/simulation/m_sim_helpers.fpp (1 hunks)
💤 Files with no reviewable changes (1)
  • src/simulation/m_ibm.fpp
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{fpp,f90}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{fpp,f90}: Use 2-space indentation; continuation lines align beneath &
Use lower-case keywords and intrinsics (do, end subroutine, etc.)
Name modules with m_ pattern (e.g., m_transport)
Name public subroutines with s_ pattern (e.g., s_compute_flux)
Name public functions with f
_ pattern
Keep subroutine size ≤ 500 lines, helper subroutines ≤ 150 lines, functions ≤ 100 lines, files ≤ 1000 lines
Limit routine arguments to ≤ 6; use derived-type params struct if more are needed
Forbid goto statements (except in legacy code), COMMON blocks, and save globals
Every argument must have explicit intent; use dimension/allocatable/pointer as appropriate
Call s_mpi_abort() for errors, never use stop or error stop

**/*.{fpp,f90}: Indent 2 spaces; continuation lines align under &
Use lower-case keywords and intrinsics (do, end subroutine, etc.)
Name modules with m_<feature> prefix (e.g., m_transport)
Name public subroutines as s_<verb>_<noun> (e.g., s_compute_flux) and functions as f_<verb>_<noun>
Keep private helpers in the module; avoid nested procedures
Enforce size limits: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100, module/file ≤ 1000
Limit subroutines to ≤ 6 arguments; otherwise pass a derived-type 'params' struct
Avoid goto statements (except unavoidable legacy); avoid global state (COMMON, save)
Every variable must have intent(in|out|inout) specification and appropriate dimension / allocatable / pointer
Use s_mpi_abort(<msg>) for error termination instead of stop
Use !> style documentation for header comments; follow Doxygen Fortran format with !! @param and !! @return tags
Use implicit none statement in all modules
Use private declaration followed by explicit public exports in modules
Use derived types with pointers for encapsulation (e.g., pointer, dimension(:,:,:) => null())
Use pure and elemental attributes for side-effect-free functions; combine them for array ...

Files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
  • src/common/m_checker_common.fpp
src/simulation/**/*.{fpp,f90}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/simulation/**/*.{fpp,f90}: Wrap tight GPU loops with !$acc parallel loop gang vector default(present) reduction(...); add collapse(n) when safe; declare loop-local variables with private(...)
Allocate large GPU arrays with managed memory or move them into persistent !$acc enter data regions at start-up
Avoid stop/error stop inside GPU device code
Ensure GPU code compiles with Cray ftn, NVIDIA nvfortran, GNU gfortran, and Intel ifx/ifort compilers

src/simulation/**/*.{fpp,f90}: Mark GPU-callable helpers with $:GPU_ROUTINE(function_name='...', parallelism='[seq]') immediately after declaration
Do not use OpenACC or OpenMP directives directly; use Fypp macros from src/common/include/parallel_macros.fpp instead
Wrap tight loops with $:GPU_PARALLEL_FOR(private='[...]', copy='[...]') macro; add collapse=n for safe nested loop merging
Declare loop-local variables with private='[...]' in GPU parallel loop macros
Allocate large arrays with managed or move them into a persistent $:GPU_ENTER_DATA(...) region at start-up
Do not place stop or error stop inside device code

Files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_bubbles_EE.fpp
src/**/*.fpp

📄 CodeRabbit inference engine (.cursor/rules/mfc-agent-rules.mdc)

src/**/*.fpp: Use .fpp file extension for Fypp preprocessed files; CMake transpiles them to .f90
Start module files with Fypp include for macros: #:include 'macros.fpp'
Use the fypp ASSERT macro for validating conditions: @:ASSERT(predicate, message)
Use fypp macro @:ALLOCATE(var1, var2) for device-aware allocation instead of standard Fortran allocate
Use fypp macro @:DEALLOCATE(var1, var2) for device-aware deallocation instead of standard Fortran deallocate

Files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
  • src/common/m_checker_common.fpp
🧠 Learnings (15)
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Wrap tight GPU loops with !$acc parallel loop gang vector default(present) reduction(...); add collapse(n) when safe; declare loop-local variables with private(...)

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Wrap tight loops with `$:GPU_PARALLEL_FOR(private='[...]', copy='[...]')` macro; add `collapse=n` for safe nested loop merging

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Mark GPU-callable helpers with `$:GPU_ROUTINE(function_name='...', parallelism='[seq]')` immediately after declaration

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Ensure GPU code compiles with Cray ftn, NVIDIA nvfortran, GNU gfortran, and Intel ifx/ifort compilers

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Declare loop-local variables with `private='[...]'` in GPU parallel loop macros

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EE.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Do not use OpenACC or OpenMP directives directly; use Fypp macros from `src/common/include/parallel_macros.fpp` instead

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/simulation/m_cbc.fpp
  • src/simulation/m_bubbles_EE.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Avoid stop/error stop inside GPU device code

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/simulation/m_sim_helpers.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Allocate large GPU arrays with managed memory or move them into persistent !$acc enter data regions at start-up

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Allocate large arrays with `managed` or move them into a persistent `$:GPU_ENTER_DATA(...)` region at start-up

Applied to files:

  • src/simulation/m_hyperelastic.fpp
  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to **/*.{fpp,f90} : Use `private` declaration followed by explicit `public` exports in modules

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to **/*.{fpp,f90} : Name public subroutines with s_<verb>_<noun> pattern (e.g., s_compute_flux)

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to **/*.{fpp,f90} : Name public subroutines as `s_<verb>_<noun>` (e.g., `s_compute_flux`) and functions as `f_<verb>_<noun>`

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/**/*.fpp : Use fypp macro `@:ALLOCATE(var1, var2)` for device-aware allocation instead of standard Fortran `allocate`

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to **/*.{fpp,f90} : Limit routine arguments to ≤ 6; use derived-type params struct if more are needed

Applied to files:

  • src/common/m_checker_common.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to **/*.{fpp,f90} : Limit subroutines to ≤ 6 arguments; otherwise pass a derived-type 'params' struct

Applied to files:

  • src/common/m_checker_common.fpp
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Code Cleanliness Check
  • GitHub Check: Github (ubuntu, no-mpi, single, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, debug, false)
  • GitHub Check: Github (ubuntu, mpi, no-debug, true)
  • GitHub Check: Github (ubuntu, mpi, no-debug, false)
  • GitHub Check: Self Hosted (gpu, acc, frontier)
  • GitHub Check: Self Hosted (gpu, omp, gt)
  • GitHub Check: Github (ubuntu, mpi, debug, true)
  • GitHub Check: Github (macos, mpi, no-debug, false)
  • GitHub Check: Self Hosted (gpu, omp, frontier)
  • GitHub Check: Self Hosted (gpu, acc, gt)
  • GitHub Check: Self Hosted (cpu, none, gt)
  • GitHub Check: Self Hosted (cpu, none, frontier)
  • GitHub Check: Github (macos, mpi, debug, false)
  • GitHub Check: Coverage Test on CodeCov
  • GitHub Check: Build & Publish
🔇 Additional comments (12)
src/common/m_checker_common.fpp (1)

314-333: LGTM - Loop bound expansion for EE bubbles validation.

The change to set bub_fac = 1 whenever bubbles_euler is true (regardless of num_fluids) correctly extends the validation loop to check the bubble gas fluid properties (fluid_pp(num_fluids + 1)). This aligns with the broader refactor to unify species fraction handling for EE bubbles.

src/simulation/m_cbc.fpp (1)

816-816: LGTM - Unified conversion path for CBC.

The removal of the bubbles_euler conditional branch in favor of unconditionally calling s_convert_species_to_mixture_variables_acc correctly adopts the unified species-to-mixture conversion approach. This aligns with the PR's goal of consolidating duplicated code paths.

src/simulation/m_bubbles_EL.fpp (1)

645-648: LGTM - Centralized species fraction computation.

The refactoring correctly delegates species fraction extraction to s_compute_species_fraction, which populates myalpha_rho and myalpha for the given cell coordinates. The subsequent call to s_convert_species_to_mixture_variables_acc consumes these outputs appropriately. The variables are properly declared as private in the GPU parallel loop directive at line 620.

src/simulation/m_bubbles_EE.fpp (1)

245-260: LGTM - Simplified single/multi-fluid handling.

The refactored conditional correctly handles both cases:

  • Single-fluid (num_fluids == 1): Direct assignment from fluid properties.
  • Multi-fluid: Volume-fraction-weighted accumulation for myRho, n_tait, and B_tait.

The logic is clear and eliminates the previously duplicated code paths while maintaining correct behavior for both scenarios.

src/simulation/m_hyperelastic.fpp (1)

113-118: LGTM - Delegated species fraction computation to centralized routine.

The replacement of the per-fluid loop with s_compute_species_fraction(q_cons_vf, j, k, l, alpha_rho_k, alpha_k) correctly delegates species fraction extraction to the shared utility. The subsequent call to s_convert_species_to_mixture_variables_acc properly consumes the outputs, including the optional G_local and Gs_hyper arguments for hyperelasticity.

src/simulation/m_sim_helpers.fpp (1)

112-119: LGTM - Unified species fraction extraction in enthalpy computation.

The consolidation to a single s_compute_species_fraction call removes the previously branched logic for IGR vs non-IGR and bubbles-specific handling. The subsequent conversion path correctly uses the general s_convert_species_to_mixture_variables_acc routine for both elasticity and standard cases. This aligns with the PR's objective of centralizing species fraction computation.

src/common/m_variables_conversion.fpp (6)

42-42: LGTM!

The new subroutine s_compute_species_fraction is correctly exported and follows the s_<verb>_<noun> naming convention per coding guidelines.


95-98: LGTM!

Good simplification—the volume fraction model dispatch now delegates all special cases (including bubbles_euler) to the unified s_convert_species_to_mixture_variables subroutine.


262-280: LGTM!

The refactoring cleanly separates species fraction computation from mixture variable derivation. The special case for single-fluid bubbles_euler and the general multi-fluid accumulation logic are correctly preserved.


336-356: Potential inconsistency in mpp_lim handling for single-fluid bubbles_euler case.

In s_compute_species_fraction (lines 1343-1349), mpp_lim constraints are applied unconditionally after computing species fractions. However, in this _acc variant, the mpp_lim logic (lines 342-348) is only applied in the multi-fluid branch, skipping it for the single-fluid bubbles_euler case.

This could cause divergent behavior between the non-accelerated and accelerated code paths when mpp_lim = .true. and num_fluids == 1 with bubbles_euler.

Please verify if mpp_lim should also be applied in the single-fluid bubbles_euler branch for consistency:

         if (num_fluids == 1 .and. bubbles_euler) then
             rho_K = alpha_rho_K(1)
             gamma_K = gammas(1)
             pi_inf_K = pi_infs(1)
             qv_K = qvs(1)
+            if (mpp_lim) then
+                alpha_rho_K(1) = max(0._wp, alpha_rho_K(1))
+                alpha_K(1) = min(max(0._wp, alpha_K(1)), 1._wp)
+            end if
         else

617-617: LGTM!

The call to s_compute_species_fraction is correctly placed within the GPU parallel loop, and the subroutine has the appropriate GPU_ROUTINE declaration for sequential execution within the parallel region.


1218-1218: No substantive change.

This appears to be a formatting adjustment only.

@codeant-ai
Copy link

codeant-ai bot commented Nov 30, 2025

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Possible Bug
    The condition for enabling the extra EOS slot for bubbles has been relaxed from requiring num_fluids == 1 to any case with bubbles_euler. This relies on fluid_pp being allocated with at least num_fluids + 1 entries for all bubbles_euler configurations; otherwise, the subsequent loop bounds can lead to out-of-bounds access. Verify that the allocation and intended usage of fluid_pp are consistent with this new logic for all models and numbers of fluids.

  • Possible Bug
    The effective Reynolds number mixing for bubbles_euler cases has been unified to use alpha_K(Re_idx(i,j)) as the weight. Previously, the bubble-specific routines used 1 - alpha_K(...) for the single-fluid-with-bubbles configuration. This change may invert the intended weighting between carrier fluid and bubbles (especially when num_fluids == 1 and bubbles_euler is true), potentially leading to incorrect viscous scales. The new logic in both s_convert_species_to_mixture_variables and s_convert_species_to_mixture_variables_acc should be carefully verified against the prior bubble model behavior.

  • Possible Bug
    In s_compute_species_fraction, when num_fluids == 1 and bubbles_euler is true, alpha_K(1) is assigned from q_vf(advxb) after the mpp_lim bounds and renormalization are applied. This can reintroduce out-of-bounds or unnormalized volume fractions, which are then used downstream (e.g., in mixture property and Reynolds number calculations). The ordering of the bubbles_euler special case and the mpp_lim enforcement should be revisited.

  • Behavioral Change
    The new call to s_compute_species_fraction replaces the inlined loop that filled alpha_rho_k and alpha_k from q_cons_vf. It should be checked that this subroutine reproduces exactly the previous behavior (correct use of advxb offsets and num_fluids range) and that it is safe to call inside the surrounding GPU_PARALLEL_LOOP (i.e., it is GPU-compatible and does not introduce unintended host-side work), otherwise the computed mixture properties used for the hyperelastic update may change.

@codeant-ai
Copy link

codeant-ai bot commented Nov 30, 2025

CodeAnt AI finished reviewing your PR.

@hyeoksu-lee hyeoksu-lee changed the title removing duplicated codes for EE bubbles removing duplicated codes in mixture rules for EE bubbles Nov 30, 2025
Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
src/common/m_variables_conversion.fpp (1)

1321-1352: Critical: Confusing conditional override creates ambiguous logic flow.

The structure of this subroutine has a problematic conditional override pattern that was flagged in previous reviews:

  1. Lines 1323-1324: When igr .or. bubbles_euler is true, sets alpha_K(1) = 1._wp
  2. Line 1352: Unconditionally overrides alpha_K(1) when num_fluids == 1 .and. bubbles_euler

This creates ambiguous logic where the same condition (bubbles_euler) leads to different assignments. The override at line 1352 negates the assignment at line 1324 for the bubbles_euler case.

Issue 1: The override doesn't check .not. igr, which means it could potentially conflict with the igr case (though in practice igr and bubbles_euler may not coexist).

Issue 2: The structure makes the code difficult to understand and maintain.

As suggested in previous reviews, refactor to have clear, separate logic paths:

-    if (num_fluids == 1) then
-        alpha_rho_K(1) = q_vf(contxb)%sf(k, l, r)
-        if (igr .or. bubbles_euler) then
-            alpha_K(1) = 1._wp
-        else
-            alpha_K(1) = q_vf(advxb)%sf(k, l, r)
-        end if
+    if (num_fluids == 1 .and. bubbles_euler) then
+        alpha_rho_K(1) = q_vf(contxb)%sf(k, l, r)
+        alpha_K(1) = q_vf(advxb)%sf(k, l, r)
+    else if (num_fluids == 1) then
+        alpha_rho_K(1) = q_vf(contxb)%sf(k, l, r)
+        if (igr) then
+            alpha_K(1) = 1._wp
+        else
+            alpha_K(1) = q_vf(advxb)%sf(k, l, r)
+        end if
     else
         if (igr) then
             do i = 1, num_fluids - 1
                 alpha_rho_K(i) = q_vf(i)%sf(k, l, r)
                 alpha_K(i) = q_vf(advxb + i - 1)%sf(k, l, r)
             end do
             alpha_rho_K(num_fluids) = q_vf(num_fluids)%sf(k, l, r)
             alpha_K(num_fluids) = 1._wp - sum(alpha_K(1:num_fluids - 1))
         else
             do i = 1, num_fluids
                 alpha_rho_K(i) = q_vf(i)%sf(k, l, r)
                 alpha_K(i) = q_vf(advxb + i - 1)%sf(k, l, r)
             end do
         end if
     end if
     
     if (mpp_lim) then
         do i = 1, num_fluids
             alpha_rho_K(i) = max(0._wp, alpha_rho_K(i))
             alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
         end do
         alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
     end if
-
-    if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)

Alternatively, if there's a specific reason for the override (e.g., the mpp_lim normalization), add a comment explaining why this is intentional.

🧹 Nitpick comments (1)
src/common/m_variables_conversion.fpp (1)

1344-1350: Consider using sgm_eps for consistency.

Line 1349 uses 1.e-16_wp as the epsilon value for normalization, while line 293 in the same file uses sgm_eps. Consider using sgm_eps consistently throughout the module for maintainability.

Apply this diff to use the consistent epsilon value:

-        alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
+        alpha_K = alpha_K/max(sum(alpha_K), sgm_eps)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1568228 and 4b7ab1c.

📒 Files selected for processing (1)
  • src/common/m_variables_conversion.fpp (7 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{fpp,f90}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{fpp,f90}: Use 2-space indentation; continuation lines align beneath &
Use lower-case keywords and intrinsics (do, end subroutine, etc.)
Name modules with m_ pattern (e.g., m_transport)
Name public subroutines with s_ pattern (e.g., s_compute_flux)
Name public functions with f
_ pattern
Keep subroutine size ≤ 500 lines, helper subroutines ≤ 150 lines, functions ≤ 100 lines, files ≤ 1000 lines
Limit routine arguments to ≤ 6; use derived-type params struct if more are needed
Forbid goto statements (except in legacy code), COMMON blocks, and save globals
Every argument must have explicit intent; use dimension/allocatable/pointer as appropriate
Call s_mpi_abort() for errors, never use stop or error stop

**/*.{fpp,f90}: Indent 2 spaces; continuation lines align under &
Use lower-case keywords and intrinsics (do, end subroutine, etc.)
Name modules with m_<feature> prefix (e.g., m_transport)
Name public subroutines as s_<verb>_<noun> (e.g., s_compute_flux) and functions as f_<verb>_<noun>
Keep private helpers in the module; avoid nested procedures
Enforce size limits: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100, module/file ≤ 1000
Limit subroutines to ≤ 6 arguments; otherwise pass a derived-type 'params' struct
Avoid goto statements (except unavoidable legacy); avoid global state (COMMON, save)
Every variable must have intent(in|out|inout) specification and appropriate dimension / allocatable / pointer
Use s_mpi_abort(<msg>) for error termination instead of stop
Use !> style documentation for header comments; follow Doxygen Fortran format with !! @param and !! @return tags
Use implicit none statement in all modules
Use private declaration followed by explicit public exports in modules
Use derived types with pointers for encapsulation (e.g., pointer, dimension(:,:,:) => null())
Use pure and elemental attributes for side-effect-free functions; combine them for array ...

Files:

  • src/common/m_variables_conversion.fpp
src/**/*.fpp

📄 CodeRabbit inference engine (.cursor/rules/mfc-agent-rules.mdc)

src/**/*.fpp: Use .fpp file extension for Fypp preprocessed files; CMake transpiles them to .f90
Start module files with Fypp include for macros: #:include 'macros.fpp'
Use the fypp ASSERT macro for validating conditions: @:ASSERT(predicate, message)
Use fypp macro @:ALLOCATE(var1, var2) for device-aware allocation instead of standard Fortran allocate
Use fypp macro @:DEALLOCATE(var1, var2) for device-aware deallocation instead of standard Fortran deallocate

Files:

  • src/common/m_variables_conversion.fpp
🧠 Learnings (12)
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to **/*.{fpp,f90} : Name public subroutines with s_<verb>_<noun> pattern (e.g., s_compute_flux)

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to **/*.{fpp,f90} : Each variable should have one clear purpose; do not use the same variable for multiple purposes

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to **/*.{fpp,f90} : Name public subroutines as `s_<verb>_<noun>` (e.g., `s_compute_flux`) and functions as `f_<verb>_<noun>`

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Allocate large GPU arrays with managed memory or move them into persistent !$acc enter data regions at start-up

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Allocate large arrays with `managed` or move them into a persistent `$:GPU_ENTER_DATA(...)` region at start-up

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Mark GPU-callable helpers with `$:GPU_ROUTINE(function_name='...', parallelism='[seq]')` immediately after declaration

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Wrap tight loops with `$:GPU_PARALLEL_FOR(private='[...]', copy='[...]')` macro; add `collapse=n` for safe nested loop merging

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Wrap tight GPU loops with !$acc parallel loop gang vector default(present) reduction(...); add collapse(n) when safe; declare loop-local variables with private(...)

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Ensure GPU code compiles with Cray ftn, NVIDIA nvfortran, GNU gfortran, and Intel ifx/ifort compilers

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:16.684Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T21:50:16.684Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Avoid stop/error stop inside GPU device code

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/simulation/**/*.{fpp,f90} : Declare loop-local variables with `private='[...]'` in GPU parallel loop macros

Applied to files:

  • src/common/m_variables_conversion.fpp
📚 Learning: 2025-11-24T21:50:46.879Z
Learnt from: CR
Repo: MFlowCode/MFC PR: 0
File: .cursor/rules/mfc-agent-rules.mdc:0-0
Timestamp: 2025-11-24T21:50:46.879Z
Learning: Applies to src/**/*.fpp : Use fypp macro `@:ALLOCATE(var1, var2)` for device-aware allocation instead of standard Fortran `allocate`

Applied to files:

  • src/common/m_variables_conversion.fpp
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Github (macos, mpi, debug, false)
  • GitHub Check: Github (macos, mpi, no-debug, false)
  • GitHub Check: Github (ubuntu, no-mpi, single, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, debug, false)
  • GitHub Check: Github (ubuntu, mpi, no-debug, true)
  • GitHub Check: Github (ubuntu, mpi, no-debug, false)
  • GitHub Check: Github (ubuntu, mpi, debug, true)
  • GitHub Check: Coverage Test on CodeCov
  • GitHub Check: Code Cleanliness Check
  • GitHub Check: Build & Publish
🔇 Additional comments (7)
src/common/m_variables_conversion.fpp (7)

42-42: LGTM: Public interface addition follows naming conventions.

The new subroutine export follows the s_<verb>_<noun> pattern as required by coding guidelines.


95-98: LGTM: Simplified conditional improves readability.

The consolidation of volume fraction model handling (with and without bubbles) into a single path is cleaner and delegates the bubbles_euler-specific logic to the called subroutine.


284-295: LGTM: Defensive check for viscous calculations.

The addition of the if (viscous) conditional prevents unnecessary Reynolds number calculations when viscosity is disabled, which is a good practice.


617-617: LGTM: Consistent use of centralized fraction computation.

The call to s_compute_species_fraction centralizes the logic and is consistent with the refactoring objectives.


1312-1318: LGTM: Proper GPU directive and intent declarations.

The subroutine signature correctly uses intent(out) for the computed fractions, and the GPU directive with sequential parallelism and inlining is appropriate for this helper function.


336-356: I apologize for the technical issue. The repository cloning failed, which prevents me from directly verifying the call sites and initialization patterns in the codebase.

Given this constraint, let me attempt to understand the concern using what information is available in the review comment itself:

The review comment raises a valid concern about intent(inout) parameters in Fortran. When a subroutine has intent(inout) parameters, they must be initialized before the call. However, without access to:

  1. The subroutine signature showing the actual intent declarations
  2. All call sites of s_convert_species_to_mixture_variables_acc
  3. The initialization patterns in calling code

I cannot definitively verify whether this concern is substantiated or if it's a false alarm.

Verify the initialization of alpha_rho_K and alpha_K at all call sites of s_convert_species_to_mixture_variables_acc in src/common/m_variables_conversion.fpp and related files.

Without repository access, I cannot complete the verification. Please retry the script execution or provide direct access to:

  • The subroutine signature (showing intent declarations for alpha_rho_K and alpha_K)
  • A list of all call sites to this subroutine
  • The initialization code surrounding those calls

262-280: Repository access unavailable for verification.

The refactored code calls s_compute_species_fraction and then handles the single-fluid bubbles_euler case specially. The verification request asks to ensure that the alpha_K values computed by s_compute_species_fraction at line 1352 are compatible with the conditional logic at line 267.

However, I cannot access the repository to examine the s_compute_species_fraction implementation and verify:

  • How alpha_K is set for the num_fluids == 1 .and. bubbles_euler case
  • Whether the computed values are consistent with their usage in the subsequent accumulation logic
  • Whether the single-fluid branch correctly bypasses the mixture calculation

Manual verification needed: Confirm that when num_fluids == 1 and bubbles_euler == true, the alpha_K array values returned by s_compute_species_fraction are consistent with the direct property assignment in lines 268-271, and that the multi-fluid branch at lines 273-280 correctly accumulates properties weighted by alpha_K.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 8 files

Prompt for AI agents (all 1 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/common/m_variables_conversion.fpp">

<violation number="1" location="src/common/m_variables_conversion.fpp:1352">
P2: Single-fluid Eulerian bubble volume fraction bypasses the limiter, so `alpha_K(1)` can leave the physical [0,1] range and corrupt Reynolds/mixture calculations.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
end if

if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 30, 2025

Choose a reason for hiding this comment

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

P2: Single-fluid Eulerian bubble volume fraction bypasses the limiter, so alpha_K(1) can leave the physical [0,1] range and corrupt Reynolds/mixture calculations.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/common/m_variables_conversion.fpp, line 1352:

<comment>Single-fluid Eulerian bubble volume fraction bypasses the limiter, so `alpha_K(1)` can leave the physical [0,1] range and corrupt Reynolds/mixture calculations.</comment>

<file context>
@@ -1575,6 +1309,50 @@ contains
+            alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
+        end if
+
+        if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
+
+    end subroutine s_compute_species_fraction
</file context>
Suggested change
if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = min(max(q_vf(advxb)%sf(k, l, r), 0._wp), 1._wp)

✅ Addressed in 262e980

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 8 files

Prompt for AI agents (all 3 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/common/m_variables_conversion.fpp">

<violation number="1" location="src/common/m_variables_conversion.fpp:276">
P1: `s_convert_species_to_mixture_variables` now includes the bubble species when computing `gamma`, `pi_inf`, and `qv`, so bubbles_euler cases with multiple fluids use void-fraction-weighted properties instead of the carrier-liquid values required by the pressure equation.</violation>

<violation number="2" location="src/common/m_variables_conversion.fpp:352">
P1: `s_convert_species_to_mixture_variables_acc` also mixes the bubble species into `gamma_K`, `pi_inf_K`, and `qv_K`, breaking the carrier-liquid property assumption for bubbles_euler flows on the accelerated path.</violation>

<violation number="3" location="src/common/m_variables_conversion.fpp:1351">
P2: This late assignment bypasses the limiter/normalization performed above, so any negative or &gt;1 bubble volume fraction from `q_vf(advxb)` is written back into `alpha_K` and propagates to mixture property calculations; clamp the value or move the assignment before the limiter.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
alpha_K_sum = alpha_K_sum + alpha_K(i)
rho_K = rho_K + alpha_rho_K(i)
gamma_K = gamma_K + alpha_K(i)*gammas(i)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 30, 2025

Choose a reason for hiding this comment

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

P1: s_convert_species_to_mixture_variables_acc also mixes the bubble species into gamma_K, pi_inf_K, and qv_K, breaking the carrier-liquid property assumption for bubbles_euler flows on the accelerated path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/common/m_variables_conversion.fpp, line 352:

<comment>`s_convert_species_to_mixture_variables_acc` also mixes the bubble species into `gamma_K`, `pi_inf_K`, and `qv_K`, breaking the carrier-liquid property assumption for bubbles_euler flows on the accelerated path.</comment>

<file context>
@@ -473,47 +321,40 @@ contains
-                alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
-                alpha_K_sum = alpha_K_sum + alpha_K(i)
+                rho_K = rho_K + alpha_rho_K(i)
+                gamma_K = gamma_K + alpha_K(i)*gammas(i)
+                pi_inf_K = pi_inf_K + alpha_K(i)*pi_infs(i)
+                qv_K = qv_K + alpha_rho_K(i)*qvs(i)
</file context>

✅ Addressed in 262e980

alpha_rho_K(i) = max(0._wp, alpha_rho_K(i))
alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
rho = rho + alpha_rho_K(i)
gamma = gamma + alpha_K(i)*gammas(i)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 30, 2025

Choose a reason for hiding this comment

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

P1: s_convert_species_to_mixture_variables now includes the bubble species when computing gamma, pi_inf, and qv, so bubbles_euler cases with multiple fluids use void-fraction-weighted properties instead of the carrier-liquid values required by the pressure equation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/common/m_variables_conversion.fpp, line 276:

<comment>`s_convert_species_to_mixture_variables` now includes the bubble species when computing `gamma`, `pi_inf`, and `qv`, so bubbles_euler cases with multiple fluids use void-fraction-weighted properties instead of the carrier-liquid values required by the pressure equation.</comment>

<file context>
@@ -379,72 +251,48 @@ contains
-                alpha_rho_K(i) = max(0._wp, alpha_rho_K(i))
-                alpha_K(i) = min(max(0._wp, alpha_K(i)), 1._wp)
+                rho = rho + alpha_rho_K(i)
+                gamma = gamma + alpha_K(i)*gammas(i)
+                pi_inf = pi_inf + alpha_K(i)*pi_infs(i)
+                qv = qv + alpha_rho_K(i)*qvs(i)
</file context>

✅ Addressed in 262e980

alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
end if

if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 30, 2025

Choose a reason for hiding this comment

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

P2: This late assignment bypasses the limiter/normalization performed above, so any negative or >1 bubble volume fraction from q_vf(advxb) is written back into alpha_K and propagates to mixture property calculations; clamp the value or move the assignment before the limiter.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/common/m_variables_conversion.fpp, line 1351:

<comment>This late assignment bypasses the limiter/normalization performed above, so any negative or &gt;1 bubble volume fraction from `q_vf(advxb)` is written back into `alpha_K` and propagates to mixture property calculations; clamp the value or move the assignment before the limiter.</comment>

<file context>
@@ -1575,6 +1309,49 @@ contains
+            alpha_K = alpha_K/max(sum(alpha_K), 1.e-16_wp)
+        end if
+
+        if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
+
+    end subroutine s_compute_species_fraction
</file context>
Suggested change
if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = q_vf(advxb)%sf(k, l, r)
if (num_fluids == 1 .and. bubbles_euler) alpha_K(1) = min(max(q_vf(advxb)%sf(k, l, r), 0._wp), 1._wp)

✅ Addressed in 262e980

@codecov
Copy link

codecov bot commented Nov 30, 2025

Codecov Report

❌ Patch coverage is 40.90909% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.16%. Comparing base (ba8a820) to head (f882347).

Files with missing lines Patch % Lines
src/common/m_variables_conversion.fpp 41.66% 15 Missing and 6 partials ⚠️
src/simulation/m_bubbles_EE.fpp 20.00% 3 Missing and 1 partial ⚠️
src/simulation/m_hyperelastic.fpp 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1071      +/-   ##
==========================================
+ Coverage   44.08%   44.16%   +0.08%     
==========================================
  Files          71       71              
  Lines       20284    20197      -87     
  Branches     1974     1970       -4     
==========================================
- Hits         8943     8921      -22     
+ Misses      10209    10148      -61     
+ Partials     1132     1128       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codeant-ai
Copy link

codeant-ai bot commented Nov 30, 2025

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Nov 30, 2025
@codeant-ai
Copy link

codeant-ai bot commented Nov 30, 2025

CodeAnt AI Incremental review completed.

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

Labels

Review effort 3/5 size:L This PR changes 100-499 lines, ignoring generated files

Development

Successfully merging this pull request may close these issues.

2 participants