Source code for komanawa.basgra_nz_py.get_fortran_module
"""
created matt_dumont
on: 26/04/24
"""
from copy import deepcopy
import warnings
import fmodpy
import sys
from pathlib import Path
import subprocess
[docs]
def get_fortran_basgra(supply_pet, recomplile=False, verbose=False, binname='gfortran-12'):
"""
get the callable fortran BASGRA function
:param supply_pet: bool if True use the PET version, if False use the peyman version
:param recomplile: bool if True force recompile the fortran code
:param verbose: bool if True print the fortran compilation output
:param version: str the version of gfortran to use, only tested on 11.4.0
:return:
"""
tested_fortran_versions = ['11.4.0', '12.3.0']
bad_tested_fortran_versions = ['13.2.0']
test_path = Path(__file__).parent.joinpath('tests', 'test_basgra_python.py')
if sys.platform.startswith('linux'):
which = subprocess.run(f'which {binname}', shell=True, check=False, stdout=subprocess.PIPE)
if which.returncode != 0:
warnings.warn(
'gfortran-12 not found, trying other gfortran instances alternatively please install gfortran: sudo apt install gfortran-12')
binname = 'gfortran'
try:
out = subprocess.run(f'{binname} --version', shell=True, check=True, stdout=subprocess.PIPE)
full_version = out.stdout.decode().split('\n')[0]
version = full_version.split(' ')[-1]
if version not in tested_fortran_versions:
warnings.warn(
f'gfortran version {full_version} has not been tested, only versions {tested_fortran_versions} have been tested. '
f'YMMV, You may wish to run `python -u {test_path}` to tests the outputs of this compilation yourself to ensure identical behaviour.'
f'note the following versions have caused issues {bad_tested_fortran_versions}')
except subprocess.CalledProcessError:
raise ChildProcessError('gfortran not found, please install gfortran: sudo apt install gfortran-12')
else:
warnings.warn(
'This function is only tested on linux, you will need to have Gfortran installed on your system, and no guarantees are made for other systems.')
f_compiler_args = ['-x', 'f95-cpp-input', '-O3', '-fdefault-real-8', '-cpp']
if supply_pet:
module_name = 'for_basgra_pet'
f_compiler_args.append('-Dweathergen')
else:
module_name = 'for_basgra_peyman'
fortran_dir = Path(__file__).parent.joinpath('fortran_BASGRA_NZ', 'uncompiled_fortran')
dependencies = [str(fortran_dir.joinpath(f)) for f in [
'parameters_plant.f95',
'parameters_site.f95',
'plant.f95',
'resources.f95',
'set_params.f95',
'soil.f95',
'h2o_storage.f95',
'environment.f95',
'brent.f95',
]]
basepath = fortran_dir.joinpath('basgraf.f95')
outputdir = fortran_dir.parent.joinpath(f'compiled_{module_name}')
if outputdir.joinpath('basgraf', '__init__.py').exists() and not recomplile:
pass
else:
for_basgra = fmodpy.fimport(
str(basepath),
output_dir=str(outputdir),
dependencies=dependencies,
f_compiler=binname,
f_compiler_args=f_compiler_args,
verbose=verbose,
end_is_named=False,
rebuild=True
)
if supply_pet:
from komanawa.basgra_nz_py.fortran_BASGRA_NZ.compiled_for_basgra_pet.basgraf import basgramodule
else:
from komanawa.basgra_nz_py.fortran_BASGRA_NZ.compiled_for_basgra_peyman.basgraf import basgramodule
return deepcopy(basgramodule)
if __name__ == '__main__':
get_fortran_basgra(False)
get_fortran_basgra(True)