Frage

I am using python as an interface to several fortran files in my model. I want to duplicate a fortran file several times but at each copy, I will change the parameters that describe my model.

For example: I have the fortran file below

!file.f
! This is a fortran code

!Parameters
alpha = 0.5
beta = 100
...

I want to copy file.f several times such that I will have file1.f, file2.f, file3.f, etc. However, at each file duplicated I want to change the parameters alpha and beta automatically. Thanks

EDIT: Let me explain a little further. I am using python to implement data assimilation (kalman filtering) to models that have already been developed in fortran. Basically, how it works is at each specified time step the fortran models stop running, then I integrate real world data to model data and I do this in python. Then after the integration (assimilation), I rerun the same models however this time using new parameters that I obtained from fusing data from model and observations and the new initial conditions. I use python to do everything except run the model which is being done by fortran.

War es hilfreich?

Lösung

I think the most consistent way to go would be to use a templating engine. Python has a lot of then, usually deployed within web applications.

But the purpose of templating engines is exactly to allow one to have the bulk of the code, that needs nos change as static text, and through some special markup interpolate that with variables generated within the Python code.

Depending on the complexity of your parameters you could even don't need any separte templating engine at all, and just go on with Python string formating capabilities, as in the example bellow.

Template engines could provide you with a bit extra capacity, as the ability to unroll loops and conditionals inside the template.

Example - write your fortram template something like:

!file.f
! This is a fortran code

!Parameters
alpha = %(alpha)s
beta = %(beta)s

And in the Python code, write something like:

template = open("fortram_template.for", "rt").read()
data = {"alpha": 0.5, "beta": 100}

with open("fortram_1.for", "wt") as output:
    output.write (template % data)

Andere Tipps

Here's an example of what you could do. I've placed the various (alpha, beta) pairs in the alpha_beta list. With alpha_beta I'm choosing to use the index of the pair position to be the value that increments the file name but there are a variety of ways that you could do this. This code is fragile in that it assumes a lot about your .f file but since this is for your own personal use in generating these files I think you'll be alright (e.g. I assume based on the information you've provided that there is only one instance of the word alpha at the start of a line in your file - if that's not true you might be better of using a regex).

alpha_beta = [(0.1, 16), (0.9, 50), (0.4, 76)]
file_name = 'file'
file_ext = '.txt'

for index, vars in enumerate(alpha_beta, start=1):
    with open(file_name + file_ext) as f:
        alpha, beta = vars
        new_file = open(file_name + str(index) + file_ext, 'w')
        for line in f:
            if line.startswith('alpha'):
                new_file.write('alpha = %s \n' % str(alpha))
            elif line.startswith('beta'):
                new_file.write('beta = %s \n' % str(beta))
            else:
                new_file.write(line)
        new_file.close()

A Fortran solution could be to write the parameter lines in a separate text file, and then include that file in the Fortran source with a line like this:

include 'parameters.inc'

This way you can simply regenerate the parameter file, without having to touch the file containing the main Fortran code.

First of all, I think this solution is overkill as stated in several comments. I would go for either one of the following two options, preferably the second if you will not be doing lots of fortran coding.

  1. Read the parameters to be used from a temporary input file, something like:

    !file.f
    !This is a fortran code
    
    !Parameters
    open (unit=input, file='tmp_inp.txt', action='read', iostat=ierr)
    read (input, '(...)') alpha, beta
    

    Then change the values in the temporary input file from Python or with sed.

  2. Pass the parameters as arguments to the fortran subroutine from within python, by interfacing the fortran code with python using f2py. The fortran code looks like:

    !file.f
    !This is a fortran code
    subroutine my_sub(alpha, beta)
    ...
    

    Then compile with f2py:

    f2py -c -m my_fortran_code file.f
    

    And finally call from within python as:

    #python code
    from my_fortran_code import my_sub
    my_sub(alpha, beta)
    

Both solutions do not require you to recompile any fortran code just for changing a few input parameters.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top