Add Fortran 101 notes#27
Conversation
There was a problem hiding this comment.
@edoyango thanks very much for adding these notes! For this reader, they are nicely incrementally pedagogical, relevant and gentle for those unfamiliar with Fortran -- well done! I particularly appreciated the Python analogues.
Having said that, I think there's a lot of material here for <ten minutes and so I'm inclined to suggest we split it over two weeks. I'm thinking that we do as you've suggested, start with the "built" example and go slowly through it. The following week, if you're open to it, I'd ask you to come back and show a real MOM6 example from the dynamical core, e.g. the barotropic solver. Applying the same ideas that you've mentioned this week but to real MOM6 code. We could alternatively ask @JorgeG94 to walk through one of the miniapp routines if we think that is less complicated but in this case I think it would help to have the same voice, as you can mention the same ideas but now applied to a real example.
I've made some suggestions, see review notes. Also, note Jorge's notes have now been merged. So can you please re-base this to main when you get a chance.
@adele-morrison, if Ed or Jorge are open to it, you okay to extend Fortran 101 to two weeks?
|
Thanks for the review Chris! I'll address your comments today.
Ordinarily, I would be happy to, but I'll be in the US next week.
If he's available, I'm sure @JorgeG94 could walk through a relevant module in my stead. |
|
One more thought.. Pushing the Python analogy... I wonder at the start, is it worth showing a python version of the end goal? I think this way the reader has a clear idea of where we are heading and when you introduce each concept (modules, sub-routines etc) it's clear what they are for? I played around with copilot and it came up with this conversion (that I have not tested) import numpy as np
# ============================================================
# grid_type (Fortran derived type → Python class)
# ============================================================
class grid_type:
def __init__(self, is_, js, ie, je, nz):
self.is_ = is_
self.js = js
self.ie = ie
self.je = je
self.nz = nz
# ============================================================
# control_structure_type
# ============================================================
class control_structure_type:
def __init__(self):
self.initialized = False
self.which_op = 1
# ============================================================
# Internal routines (Fortran "private" subroutines)
# ============================================================
def _sum_along_column(g, arr1, arr2):
"""
Python equivalent of the Fortran sum_along_column subroutine.
Explicit loops are used to match Fortran behavior exactly.
"""
for j in range(g.js, g.je + 1):
# Initialize column sum
arr2[:, j - g.js] = arr1[:, j - g.js, 0]
for k in range(1, g.nz):
for i in range(g.is_, g.ie + 1):
arr2[i - g.is_, j - g.js] += arr1[i - g.is_, j - g.js, k]
def _max_along_column(g, arr1, arr2):
"""
Python equivalent of the Fortran max_along_column subroutine.
"""
for j in range(g.js, g.je + 1):
arr2[:, j - g.js] = arr1[:, j - g.js, 0]
for k in range(1, g.nz):
for i in range(g.is_, g.ie + 1):
arr2[i - g.is_, j - g.js] = max(
arr2[i - g.is_, j - g.js],
arr1[i - g.is_, j - g.js, k]
)
# ============================================================
# Public routine (Fortran: do_something_along_column)
# ============================================================
def do_something_along_column(cs, g, arr1, arr2):
if not cs.initialized:
raise RuntimeError("Control structure not initialized!")
if cs.which_op == 1:
_sum_along_column(g, arr1, arr2)
elif cs.which_op == 2:
_max_along_column(g, arr1, arr2)
else:
raise RuntimeError("Invalid operation provided! Must be 1 or 2.")
# ============================================================
# Main program (Fortran: program my_program)
# ============================================================
def main():
# Construct derived types
g = grid_type(is_=1, js=2, ie=3, je=4, nz=5)
cs = control_structure_type()
cs.initialized = True
cs.which_op = 1 # 1 = sum, 2 = max
# Convert Fortran index ranges to Python sizes
nx = g.ie - g.is_ + 1
ny = g.je - g.js + 1
nz = g.nz
# Allocate arrays
input_array = np.ones((nx, ny, nz))
output_array = np.zeros((nx, ny))
# Perform the operation
do_something_along_column(cs, g, input_array, output_array)
# Print the sum of the output array
print(np.sum(output_array))
if __name__ == "__main__":
main() |
@JorgeG94, since Ed is travelling the following week, would you be able to do a little run-through of actual MOM6 code the following week? This would be 21/05/2026 at 11.30 (same setup as last time). More about my suggestion here. |
Hi Chris, for sure no worries |
Awesome, thanks @JorgeG94. @aekiss, we'd like to extend Fortran 101 to two weeks, can we put your navier stokes intro back a week please? More about my suggestion #27 (review). |
Added introductory notes on Fortran programming for MOM6, including modules, subroutines, variable declarations, array handling, loops, and derived types.
Added control structure type and updated subroutines for operations along columns.
Co-authored-by: Christopher Bull <5499680+chrisb13@users.noreply.github.com> Co-authored-by: Edward Yang <94523015+edoyango@users.noreply.github.com>
|
hi @chrisb13 I've rebase the PR and addressed your comments. Can you have another look? |
There was a problem hiding this comment.
Thanks @edoyango looking really good. I've made some small further suggestions.
My last thing is can we tweak the title given that it will run over two weeks.
How about something like:
- Fortran 101 part 1: Fortran concepts for understanding MOM6 (or a toy example using modules and sub-routines?);
- Fortran 101 part 2: Fortran in the MOM6 ROUTINE_NAME
@JorgeG94, feel free to chime in here. Any idea which routine you'd like to focus on?
Also, did you test the python code? Works as expected?
Co-authored-by: Christopher Bull <5499680+chrisb13@users.noreply.github.com>
@edoyango opinions on the routine being the dynamics split rk2? It's pretty high level and showcases probs one of the most important bits! |
Hi @chrisb13
This is my notes for next week's decoding MOM session.
It's long, as I build the example over a few steps. In the session I plan to quickly go over language features used in the final product. It's hopefully enough to make MOM6 code somewhat comprehensible to a beginner.
Let me know if you have any comments.