如何复制一个文件但更改其中的一些参数?

发布于 2024-12-26 18:16:29 字数 537 浏览 2 评论 0原文

我使用 python 作为模型中多个 fortran 文件的接口。我想多次复制一个 Fortran 文件,但在每次复制时,我都会更改描述我的模型的参数。

例如:我有下面的 fortran 文件,

!file.f
! This is a fortran code

!Parameters
alpha = 0.5
beta = 100
...

我想复制 file.f 几次,这样我就会有 file1.f、file2.f、file3.f 等。但是,在复制的每个文件中,我想更改参数 alpha并自动进行测试。谢谢

编辑:让我进一步解释一下。我正在使用 python 对已经在 fortran 中开发的模型实现数据同化(卡尔曼滤波)。基本上,它的工作原理是在每个指定的时间步,fortran 模型停止运行,然后我将现实世界数据集成到模型数据中,并在 python 中执行此操作。然后在集成(同化)之后,我重新运行相同的模型,但是这次使用通过融合模型和观测数据以及新的初始条件获得的新参数。除了运行由 fortran 完成的模型之外,我使用 python 做所有事情。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如此安好 2025-01-02 18:16:30

首先,我认为这个解决方案是矫枉过正的,正如一些评论中所述。我会选择以下两个选项之一,如果您不进行大量的 Fortran 编码,最好选择第二个。

  1. 从临时输入文件中读取要使用的参数,例如:

    <前><代码>!file.f
    !这是一段 Fortran 代码

    !参数
    打开(单元=输入,文件='tmp_inp.txt',操作='读取',iostat=ierr)
    读取(输入,'(...)')alpha,beta

    然后从 Python 或使用 sed 更改临时输入文件中的值。

  2. 通过使用 f2py 将 fortran 代码与 python 连接,将参数作为参数从 python 内传递给 fortran 子例程。 Fortran 代码如下所示:

    <前><代码>!file.f
    !这是一段 Fortran 代码
    子程序 my_sub(alpha, beta)
    ...

    然后用f2py编译:

    f2py -c -m my_fortran_code file.f
    

    最后从 python 中调用:

    #python代码
    从 my_fortran_code 导入 my_sub
    my_sub(阿尔法,贝塔)
    

两种解决方案都不需要您仅为了更改一些输入参数而重新编译任何 Fortran 代码。

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.

浅黛梨妆こ 2025-01-02 18:16:29

我认为最一致的方法是使用模板引擎。 Python 有很多,通常部署在 Web 应用程序中。

但模板引擎的目的正是允许人们拥有大量代码,无需将其作为静态文本进行更改,并通过一些特殊的标记将其与 Python 代码中生成的变量进行插值。

根据参数的复杂性,您甚至可能根本不需要任何单独的模板引擎,而只需继续使用 Python 字符串格式化功能,如下例所示。

模板引擎可以为您提供一些额外的能力,例如在模板内展开循环和条件的能力。

示例 - 编写您的 fortram 模板,如下所示:

!file.f
! This is a fortran code

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

在 Python 代码中,编写如下所示的内容:

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)

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)
童话 2025-01-02 18:16:29

这是您可以执行的操作的示例。我已将各种(alpha、beta)对放入 alpha_beta 列表中。对于 alpha_beta ,我选择使用对位置的索引作为增加文件名的值,但有多种方法可以做到这一点。该代码很脆弱,因为它假设了很多关于您的 .f 文件的信息,但由于这是供您个人使用来生成这些文件的,我认为您会没事的(例如,我假设根据您提供的信息,有文件中一行开头处只有一个单词 alpha 的实例 - 如果不是这样,您可能最好使用正则表达式)。

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()

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()
眸中客 2025-01-02 18:16:29

Fortran 解决方案可能是将参数行写入单独的文本文件中,然后在 Fortran 源代码中包含该文件,并使用如下行:

include 'parameters.inc'

这样您就可以简单地重新生成参数文件,而无需触摸包含主要 Fortran 代码的文件。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文