Conversation
…oving warning on Hbs since formula is correct
… in rdcon_netcdf.f
There was a problem hiding this comment.
Pull request overview
This PR updates the Mercier/MRE-related calculations and NetCDF outputs to correct several formula/normalization issues (inverse minor aspect ratio/trapped fraction impacts, Wc prefactor flux normalization) and to adjust what is emitted in rdcon_output_n*.nc.
Changes:
- Update MRE geometry-derived quantities (e.g.,
eps_loc, trapped fraction) and revise bootstrap-drive-related term handling. - Correct
Wc_prefacnormalization to account for toroidal→(normalized) poloidal flux conversion. - Extend/adjust NetCDF outputs: add globals (
volume,Zeff,bwall), add profile varh, renameHbs→Hbs_prefac, and stop writing the brokenavg_mu0Jbs_dot_Bterm.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
rdcon/rdcon_netcdf.f |
Adds new global attributes and profile/MRE variables to NetCDF output; renames Hbs output and removes avg_mu0Jbs_dot_B output. |
rdcon/mercier.f |
Updates surface geometry/trapped-fraction calculation, revises MRE prefactors, and annotates/retains (but flags) the suspected-broken bootstrap term. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rdcon/mercier.f
Outdated
| c initialise extremum surface locations. | ||
| c----------------------------------------------------------------------- | ||
| rmax_loc=0.0 | ||
| rmin_loc=HUGE(1.0_8) | ||
| zmax_loc=-HUGE(1.0_8) | ||
| zmin_loc=HUGE(1.0_8) |
There was a problem hiding this comment.
The extrema initialization (and the associated per-θ extrema tracking) runs unconditionally for every Mercier scan, but the resulting geometric quantities are only used under MRE_flag. Consider moving the extrema init/update under IF(MRE_flag) to avoid extra work in non-MRE runs.
| CALL check( nf90_def_var(ncid, | ||
| $ "Dnc", nf90_double, p_dim, dnc_id)) | ||
| CALL check( nf90_def_var(ncid, | ||
| $ "Wc", nf90_double, p_dim, wc_id)) |
There was a problem hiding this comment.
avg_mu0Jbs_dot_B is no longer defined/written, but jbs_id is still declared (and mreterms%fs(:,6) still exists). Consider removing jbs_id (and/or documenting the skipped index) so the netCDF writer and mreterms layout don’t silently diverge.
| $ "Wc", nf90_double, p_dim, wc_id)) | |
| $ "Wc", nf90_double, p_dim, wc_id)) | |
| c | |
| c NOTE: The MRE terms layout (e.g., mreterms%fs(:,6)) still reserves | |
| c an index for the deprecated quantity avg_mu0Jbs_dot_B. That term | |
| c is intentionally no longer written to this NetCDF file, so no | |
| c nf90_def_var call appears here for it. The sequence of variables | |
| c defined below therefore skips that index by design. | |
| c |
There was a problem hiding this comment.
This is overly verbose. We should just remove the index from being declared and add a one-line annotation wherever mreterms%fs(:,6) is actually calculated saying it comes from [citation] but gives suspect results and is thus not output for now
There was a problem hiding this comment.
This copilot comment is out of date and should be ignored -> mreterms%fs(:,6) now stores avg(|nabla psi|) which is correctly calculated, and printed on lines 284, 285, and 417
| CALL check( nf90_put_att(ncid,nf90_global,'volume', volume)) | ||
| CALL check( nf90_put_att(ncid,nf90_global,'Zeff', Zeff)) | ||
| CALL check( nf90_put_att(ncid,nf90_global,'bwall', bwall)) |
There was a problem hiding this comment.
Global NetCDF attributes in this file consistently use lowercase names (e.g., betan, bwall, volume), but this adds 'Zeff' with mixed case. Consider renaming the attribute to zeff (or otherwise matching the established casing) to avoid surprising downstream readers that treat attribute names as case-sensitive.
There was a problem hiding this comment.
The capitalization is ok here. It follows standard annotations in the field
rdcon/mercier.f
Outdated
| Jpara=psio*f1*avg(16)+p1*avg(18)*twopif/(twopi*psio) + | ||
| $ (twopif/twopi)**2*f1*avg(17)/psio !(mu0 included in p1)) | ||
| Jtor=p1*avg(12)/psio + (twopif/twopi)*f1*avg(13)/psio |
There was a problem hiding this comment.
Jtor is assigned but never used. If it’s not needed, remove the variable (and its declaration) to avoid dead code; otherwise, consider using it or documenting why it’s computed.
There was a problem hiding this comment.
This is ok. It may. come in handy later and is very cheap to compute
rdcon/mercier.f
Outdated
| mreterms%fs(ipsi,4)=ftr | ||
| mreterms%fs(ipsi,5)=mufrac | ||
| mreterms%fs(ipsi,6)=avg_Jboot_dot_B | ||
| mreterms%fs(ipsi,6)=avg_Jboot_dot_B !broken formula |
There was a problem hiding this comment.
mreterms%fs(ipsi,6) is being populated with a value marked as a “broken formula”. Since it’s also no longer written to netCDF, consider setting it to a sentinel (e.g., 0/NaN) or removing the field to prevent accidental downstream use of known-bad data.
| mreterms%fs(ipsi,6)=avg_Jboot_dot_B !broken formula | |
| mreterms%fs(ipsi,6)=0.0D0 ! intentionally set sentinel; avg_Jboot_dot_B formula is broken |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ts into adding_MRE_terms
|
@StuartBenjamin this is still marked as "draft" is is ready for review? |
Code ReviewThe physics fixes (eps_loc geometry, Wc_prefac flux conversion, trapped fraction formula) look well-motivated and the comments/references are a good improvement. Bugs
Jtor=p1*avg(12)/psio + (twopif/twopi)*f1*avg(13)/psio
Minor issues
Note on the broken J_bs_dot_B formulaThe PR description says the Callen 2010 eq. C18 formula "seems incorrect" but the reason is unknown. It would be worth opening a separate issue to track the investigation, especially since |
Code ReviewBugs1. Division by zero at the magnetic axis ( At deltatop_loc=(rmean_loc-zmax_loc(1))/amean_loc ! 0/0 at axis
deltabot_loc=(rmean_loc-zmin_loc(1))/amean_loc ! 0/0 at axisThis produces 2. Jtor=p1*avg(12)/psio + (twopif/twopi)*f1*avg(13)/psioThis variable is computed but not stored in 3. Line length violations in fixed-format Fortran ( The inline comments on the Lines 212-214 are similarly over-length. Move the inline comments to preceding Minor Issues4. Dead declaration:
5. Type literal conventions ( Per the codebase convention, use the
6.
Notes
|
|
Review of PR #242: Adding MRE terms corrections The physics fixes are well-described (eps_loc geometry, trapped fraction Sauter 2002 formula, Wc_prefac flux normalization). The added inline comments on the avg() array slots are a good improvement for readability. A few issues to address: Bugs / Compiler Warnings
jbs_id remains in the INTEGER :: declaration list but its corresponding nf90_def_var and nf90_put_var calls were removed. This will produce an "unused variable" compiler warning. Remove it from the declaration.
This is declared, computed, but never stored in mreterms or written anywhere. If it is a placeholder for future use, add a comment explaining that. Otherwise remove it. Convention Violations
Per the project type precision convention (CLAUDE.md), REAL(r8) literals should use the _r8 kind suffix. The lines: should use HUGE(1.0_r8) and -HUGE(1.0_r8). Kind 8 is conventionally double precision but is not guaranteed portable; r8 is the codebase named kind parameter. Similarly, rmax_loc=0.0 should be rmax_loc=0.0_r8. API Break Note
Slot 6 was avg_Jboot_dot_B and is now <|nabla psi|> (avg(22)). The NetCDF variable name change (avg_mu0Jbs_dot_B -> avg_nabla_psi) documents this in the output file, but any pypec scripts or downstream code reading mreterms arrays by index rather than by NetCDF variable name will silently get wrong data. Worth verifying no such direct array accesses exist on the Python side. |
|
Code Review The physics corrections (eps_loc, trapped fraction formula, Wc_prefac unit conversion) look well-motivated and the PR description explains the reasoning clearly. The added comments on mreterms%fs indices are a good improvement. A few issues worth addressing: Bugs / Correctness
The initialization is inconsistent with the others. It works for tokamaks (where R > 0 always), but should be -HUGE(1.0_r8) for correctness and clarity. If R were ever 0 or negative, the maximum-finding logic would silently fail.
Jtor=p1*avg(12)/psio + (twopif/twopi)f1avg(13)/psio This is dead code. Either save it to mreterms%fs or remove it. Convention Issues
Per the project conventions, use the _r8 suffix for REAL(r8) literals. All three occurrences (rmin_loc, zmax_loc, zmin_loc) should use HUGE(1.0_r8).
For example the line ending in the conversion comment extends to column ~88. The code portion is within limits so compilation is unaffected, but the comment will be silently truncated in strict fixed-format compilers and may confuse future editors. Interface / Downstream Compatibility
mreterms%fs(ipsi,6) used to hold avg_Jboot_dot_B; it now holds avg(22) = average of |nabla psi|. Any downstream Fortran or Python code reading column 6 and expecting avg_Jboot_dot_B will silently get the wrong quantity. If there is downstream code using this field, it should be updated in this PR or at least explicitly flagged. Similarly, mreterms%fs(ipsi,1) changed from a complete Hbs to a prefactor Hbs_prefac. The comment says to multiply by avg_Jboot_dot_B to get the full Hbs - confirm all downstream consumers are updated accordingly. Minor / Positive
|
Automatic reviews were triggering on any PR review submission, not just when @claude was explicitly requested. The on-demand claude.yml already covers the desired behavior. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Jtor (toroidal current density) was assigned but never used, generating compiler warnings. Remove from declaration and comment out the formula to preserve it for future reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- rmax_loc was initialized to 0.0, which happens to work since R > 0, but -HUGE(1.0_r8) is the correct sentinel for a running maximum - All HUGE() calls used _8 suffix; standardize to _r8 to match declared kind of the surrounding REAL(r8) variables Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The rmax/rmin/zmax/zmin arrays are only used inside the MRE_flag block. Wrap the pre-loop initialization and the per-theta-point tracking in IF(MRE_flag) to skip the work on non-MRE runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
At ipsi=0 the flux surface is a point, so amean_loc=0 and the triangularity calculations (deltatop/deltabot = 0/0) produce NaN that poisons ftr, mufrac, and Dnc. Guard the division: set delta quantities to HUGE (physically undefined/infinite at the axis) and eps_eff=0 directly (since eps_loc=0 makes it zero regardless of delta). The Sauter ftr formula then evaluates cleanly to 0 from eps_loc=0, eps_eff=0, consistent with no trapped particles at the axis. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jbs_id was declared for avg_mu0Jbs_dot_B but that output was removed; the variable was never assigned a NetCDF ID. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Addressed the review feedback with the following commits:
Items not addressed:
|
A few of the formulas in the MRE scripts were incorrect, namely the way I calculated inverse minor aspect ratio (eps_local), and its corresponding impact on the trapped fraction and bootstrap drive. The second erroneous formula that has since been fixed was Wc_prefac - I realized the original paper used toroidal flux not poloidal flux. I added the conversion factor to convert to normalized poloidal flux consistent with everything else. Finally the J_bs_dot_B formula, although correctly copied from Callen, 2010 UW-CPTC 09-6R equation C18, seems incorrect, so I've stopped printing it out in rdcon_netcdf.f. I haven't removed the equation because I don't understand why it's broken, and I think its useful to keep it there - happy to remove it if you think that's cleaner though.
Aside from that mentioned above, I've added some small changes that improve this section of code overall: more comments and revising variable name Hbs -> Hbs_prefac to match what is actually being computed and printed