Closed rabernat closed 2 years ago
Looking at f2py's documentation it seems there are a few ways of exposing the fortran routines in python. Do we want to: 1) Leave aerobulk alone entirely, make a new package "aerobulk-python" which keeps a copy of aerobulk's fortran routines in a subdirectory (via a git submodule), and create signature files using f2py which live in aerobulk-python. 2) Make PRs to aerobulk which add these F2PY directives directly into the aerobulk fortran routines as comments.
Approach (1) separates our packaging from the original routines most clearly, doesn't require the aerobulk developers to accept anything, and was what was done in xcape.
Approach (2) requires the smallest amount of additional code, and integrates the python interface more tightly with the aerobulk one, and gives us a reason to ask for commit access to aerobulk.
I would say 1
Yeah, I agree. It seems that is the fastest way to make progress. If we have success with this approach, we can always consider adding code upstream later on?
@rabernat I'm trying to compile the wrapper for the mod_blk_ncar.f90
file (I picked the NCAR one at random). First I tried compiling the wrapper for that file, but although I can create the signature file (mod_blk_ncar.pyf
), I can't compile it with f2py
immediately because it relies on a fortran module defined in mod_const.f90
, and asks for a mod_const.mod
file.
I don't understand how to get f2py's interface to build the .mod
file for me, but I can make the .mod
file by using gfortran directly on mod_const.f90
.
Now using f2py
on mod_blk_ncar.f90
asks for mod_phymbl.mod
, which is the other module USEd by mod_blk_ncar
. However if I try to compile mod_phymbl.mod
with gfortran -I.
then I get an error:
mod_phymbl.f90:1876:132:
1876 | WRITE(*,'(" *** ERROR (check_unit_consistency@mod_phymbl): shape of `mask` does not agree with array of field ",a," !")') TRIM(cfield)
| 1
Error: Line truncated at (1) [-Werror=line-truncation]
mod_phymbl.f90:1876:132:
1876 | WRITE(*,'(" *** ERROR (check_unit_consistency@mod_phymbl): shape of `mask` does not agree with array of field ",a," !")') TRIM(cfield)
| 1
Error: Syntax error in WRITE statement at (1)
mod_phymbl.f90:1949:132:
1949 | WRITE(*,'(" *** ERROR (check_unit_consistency@mod_phymbl): field `",a,"` does not seem to be in ",a," !")') TRIM(cfield), TRIM(cunit)
| 1
Error: Line truncated at (1) [-Werror=line-truncation]
mod_phymbl.f90:1949:132:
1949 | WRITE(*,'(" *** ERROR (check_unit_consistency@mod_phymbl): field `",a,"` does not seem to be in ",a," !")') TRIM(cfield), TRIM(cunit)
| 1
Error: Symbol ‘t’ at (1) has no IMPLICIT type
f951: some warnings being treated as errors
Am I doing this the right way? I feel like I'm doing something silly with respect to the linking of these files... Xcape has just .f90
and the .pyf
signature files in its repo - does that mean that the compilation happens when the user installs it from conda?
Have you tried to first compile the fortran as documented in the repo--indepndent of python? That will teach you how the code "expects" to be compiled and is probably a prerequisite for using f2py.
Have you tried to first compile the fortran as documented in the repo--indepndent of python? That will teach you how the code "expects" to be compiled and is probably a prerequisite for using f2py.
Yeah I mean I've successfully used make
with the makefile to get all the .o
and .mod
files. I'll try compiling and running the tests mentioned in the readme too.
I guess I'm just confused as to how to tell f2py to compile the code in the same way that the makefile specifies, or whether I can tell f2py just to use the object files I just compiled using make
. (The f2py documentation curtly dismisses make
in general so that isn't especially helpful).
Some notes summarizing the progress we have made so far. Here are the steps to try to compile f2py on aerobulk. I assume you have checked out https://github.com/brodeau/aerobulk and are in the root directory.
mamba create -n aerobulk python=3.9 numpy gfortran
conda activate aerobulk
cp arch/make.macro_GnuLinux make.macro
those of us on mac needed to edit make.macro
make this change
# These are needed for the C/C++ interface
- FF += -std=f2008 -lstdc++
+ FF += -std=f2008
EDIT:
Note that the line uncommented by default is actually using
-std=gnu
here. Both versions do however compile. Not sure about differences.
Then you should be able to run make
This will build:
src/*.o
mod/*.mod
lib/libaerobulk.a
bin/*x
I was able to run one of the binaries with bin/example_call_aerobulk.x
First we build the signature file
cd src
python -m numpy.f2py mod_aerobulk.f90 -m mod_aerobulk -h mod_aerobulk.pyf
At this point, we realized that, since the aerobulk code uses KIND specifiers to define fortran types, we need to follow these instructions - https://numpy.org/doc/stable/f2py/advanced.html#dealing-with-kind-specifiers
We created a file src/.f2py_f2cmap
with the contents
{'real': {'wp': 'double', 'dp': 'double', 'sp': 'float'}}
Then the magic command to build
python -m numpy.f2py --verbose -c --f90flags="-fdefault-real-8 -ffree-line-length-200 --std=gnu" \
-I../mod mod_aerobulk.pyf mod_*.f90
Unfortunately, this is still failing with the error
/var/folders/n8/63q49ms55wxcj_gfbtykwp5r0000gn/T/tmp1gwaq670/src.macosx-10.9-x86_64-3.9/mod_aerobulk-f2pywrappers2.f90:30:16:
30 | real(kind=wp) psst(f2py_psst_d0,f2py_psst_d1)
| 1
Error: Parameter ‘wp’ at (1) has not been declared or is a variable, which does not reduce to a constant expression
That's where we are at.
Ok, quick update, replacing kind=wp
with kind=8
in mod_aerobulk.pyf
allows the f2py to succeed. :tada:
Very productive session yesterday. I updated the top level issue with a checklist of next steps.
@jbusecke - since you are our packaging expert, I think it makes sense for you to create the repo and set up the package skeleton. Shall we do this in the xgcm org?
In the meanwhile, maybe @TomNicholas can keep tweaking f2py to address items 2 and 3?
Does this sounds like a good plan?
Ok, quick update, replacing kind=wp with kind=8 in mod_aerobulk.pyf allows the f2py to succeed.
I'm having problems replicating this step on my machine. After doing the substitution, I still get compilation errors of the form
x86_64-conda-linux-gnu-gfortran:f90: mod_blk_ncar-f2pywrappers2.f90
mod_blk_ncar-f2pywrappers2.f90:16:16:
16 | real(kind=wp) zt
| 1
Error: Parameter 'wp' at (1) has not been declared or is a variable, which does not reduce to a constant expression
These are similar to what we had before changing kind=wp
to kind=8
for mod_aerobulk, except now it's happening with a file that I shouldn't need a signature for mod_blk_ncar
.
After doing the substitution, I still get compilation errors
Did you remember to add the .f2py_f2cmap
file?
Did you remember to add the .f2py_f2cmap file?
Yes, and the compilation prints
Reading f2cmap from '.f2py_f2cmap' ...
Mapping "real(kind=wp)" to "double"
Mapping "real(kind=dp)" to "double"
Mapping "real(kind=sp)" to "float"
Successfully applied user defined f2cmap changes
So the question is, what process is generating the mod_blk_ncar-f2pywrappers2.f90
file? Presumably a manual search / replace within that file (and all others like it) would resolve the issue.
Closing now that we have all the intstructions in https://github.com/xgcm/aerobulk-python/pull/19
Today we discussed the choice between two options for computing bulk formulae:
For the latter, here are some helpful links:
My recommendation would be to make aerobulk a submodule of aerobulk-python.
Edited to add the following checklist
make
step and do all our compliation with f2py (perhaps optional; depending on how our build system works)aerobulk-python
but the package justaerobulk
)