【问题标题】:Run a code in fortran multiple times with different input parameters使用不同的输入参数在 fortran 中多次运行代码
【发布时间】:2017-10-09 16:00:59
【问题描述】:

我想使用不同的输入参数集多次运行一个 fortran 77 程序;我已经确保输出文件名会随着我使用的不同输入参数而改变,但我不确定如何运行具有不同输入参数集的程序,而不必每次都去代码更改参数。

为了说明我的问题,这里有一个简单的代码。

   PROGRAM CODE
   IMPLICIT DOUBLE PRECISION (A-H, J-Z)
   COMMON / param  / radius

   radius = 2
   write(*,*) 'radius = ', radius
   write(*,*) 'the area is = ', 3.14*radius*radius

   END 

假设我想以不同的半径运行这段代码,而不是必须进入代码并手动更改值,我想要一个具有不同参数选择的文件并让它运行多次。

当然,通过创建一组不同的参数选择和循环来解决这个问题。但是,我不想这样做,因为我实际上有多个参数要为每次运行更改。

针对下面的其中一个 cmets,如果我有一个文件,每次运行都有不同的输入选择,我如何让程序为每次运行的不同参数选择抓取不同的行?

【问题讨论】:

  • 好吧,有些人会用他们最喜欢的脚本语言编写一个小脚本,为程序的每次执行提供一些输入参数。对于任何像真正的答案,问一个问题。 (不,您发布的内容不是问题。)
  • 你可能想查找Get_command_argument
  • 另一种选择是读取包含每次运行所需的输入参数的数据文件。
  • 你的操作系统是什么? Windows 还是 Linux?您可以使用哪些脚本语言?
  • @agentp:这家伙(我猜)想在 FORTRAN77 中编程——不要让他接触到任何先进的 21 世纪技术。

标签: fortran gfortran fortran77


【解决方案1】:

有一种“行人”式的方法,我用过很多次。

为避免重新编译,一种解决方案是硬编码参数文件的名称并从该文件中读取数据。每次运行代码都必须有自己的参数副本和自己的目录。

我在下面给出了单个参数的示例,但如果需要,您可以对其进行概括。它依赖于 bash 中的驱动程序脚本。

Fortran 程序:

      PROGRAM CODE
      IMPLICIT DOUBLE PRECISION (A-H, J-Z)
      COMMON / param  / radius

      open(11, file='parameters.txt')
      read(11,*) radius
      close(11)
      write(*,*) 'radius = ', radius
      write(*,*) 'the area is = ', 3.14*radius*radius

      END 

bash 程序:

for radius in 01 02 05 10
do
RUNDIR=run_${radius}
mkdir ${RUNDIR}
echo "${radius}" > ${RUNDIR}/parameters.txt
(cd ${RUNDIR} ; ../code)
done

编译 Fortran 代码:

gfortran -std=legacy -o code code.f

并执行参数化运行:

bash parametricrun.sh
  1. Fortran 代码的作用:打开名为 parameters.txt 的文件并读取第一个条目以获取半径值。

  2. bash 脚本的作用:对于参数的多个值,创建一个新目录,在该目录中创建一个名为 parameters.txt 的文件,然后执行 Fortran 程序 code in em> 那个目录。

评论:

  1. 使用 bash 程序中的第二个循环,可以将其扩展到多个变量,每行一个或 parameters.txt 中的每行多个。

  2. 如果您可以使用更现代的 Fortran 版本,请提及。那里有更多选择。

  3. 其他语言(Python,如 arclight 所建议的那样,或其他)可用于编写脚本。许多计算集群使用 bash 来运行作业,因此它可能用于参数化运行(半径的值可以通过作业排队系统传递)。

  4. 我任意使用了 11 作为文件单元号。您的实际情况确实需要为您的程序使用可用的单元号。

【讨论】:

  • 这是我会使用的方法,但是懒得写了。也可以在 Windows 中使用,只是脚本略有不同。不需要特殊的编程语言。老实说,我不认为提出基本问题的用户能够仅根据一些描述编写 Python 脚本而无需任何代码。
  • 文件方法的优点是可以归档输入文件。如果有多个参数,我通常会使用它。
  • 感谢您的帮助。我坚持使用 fortran 77 的原因是,我正在使用我的同事已经在 fortran 77 中编写的代码。我不是一个程序员,但是有没有办法简单地将 fortran 77 代码更改为更现代的版本?
  • 有指南。 Fortran 90 for the Fortran 77 Programmer 与“90 年代的旧现代 Fortran”有关,但这是最大的变化。更新页面位于fortranwiki。另一个很好的资源是fortran90.org关注这些语言的最新版本(尽管有标题)。
【解决方案2】:

如果改成代码,需要重新编译。

我不知道您的程序有多复杂,通常最好以从用户界面或文件读取值的方式编写程序。

查看CHECK_COMMAND_ARGUMENTNamelists 了解如何操作。

但是如果你想每次都去重新编译它,你可以使用预处理器来设置代码的某些部分。

查看此示例代码:

      PROGRAM area
      IMPLICIT NONE
      PRINT *, "area of circle with radius ", RADIUS, " is ",
     &         3.15159 * RADIUS**2
      END PROGRAM area

要使用预处理器,您必须明确告诉编译器这样做(例如gfortran -cppifort -fpp),或者您可以将扩展名更改为大写 .F(或现代 Fortran 的 .F90 ) 默认情况下启用预处理器。

$ gfortran -D RADIUS=2 area.F -o area
$ ./area
 area of circle with radius            2  is    12.6063604
$ gfortran -D RADIUS=20 area.F -o area
$ ./area
 area of circle with radius           20  is    1260.63599

【讨论】:

  • 虽然我现在正在重新考虑是否要告诉没有太多编程经验的人关于预处理器......它们可能会产生奇怪的效果......
  • 教人们为程序的每次不同执行重新编译,这是一种奇怪的效果 ...
【解决方案3】:

在我不得不对希望对一组参数进行操作的代码进行参数分析的情况下,我使用 Jinja2 模板库在 Python 中编写了一个小脚本来生成大量输入文件.我选择了一个命名约定,让我可以轻松地确定哪个输入文件对应于哪个输入排列,以帮助对结果进行后处理。 Python 和 Jinja2 的具体使用不如在输入生成脚本之外拥有文本模板重要,因此您可以在不编辑输入生成器的情况下对生成的文件进行调整。有很多成熟、简单的 Web 模板系统可以高效地生成输入文本文件。

输入参数和文件名之间的交叉引用可能就像对数据结构数组(即哈希或字典)的索引一样简单。我尝试使用更有意义的东西并将描述性 cmets 添加到生成的输入中(假设输入格式允许 cmets...)

在我的情况下,我可能使用的代码如果不经过长达一个月的 QA 周期就无法重新编译,因此将参数变体代码编写为单独的脚本比将其集成到我的 Fortran 中要便宜得多代码。

我倾向于用 Python 编写参数分析代码的另一个原因是它比用 Fortran 编写复杂的输入处理要容易得多。能够使用 numpy 生成线性、对数或其他变化模式(例如 Chebyshev 节点)比在 Fortran 中尝试要容易得多。

标准免责声明:我的操作环境和用例可能与您的非常不同,因此这种技术可能不合适。我只是指出,这是一个具有多个优点的选项,具体取决于您的环境。

【讨论】:

    【解决方案4】:

    命令行参数方法

      implicit none
      real r
      character*30 arg
      integer ios
      if(command_argument_count().eq.0)then
    ! default for no argument
        r=1. 
      else
         call get_command_argument(1,arg)
         read(arg,*,iostat=ios)r
         if(ios.ne.0)then
            write(*,*)'error expected number arg got ',arg
            stop
         endif
      endif
      write(*,*)r
      end
    

    请注意,对于古代编译器,您应该改用 iargcgetarg。纯粹主义者会注意到这些是非标准的 f77,但它们在许多编译器中都很常见。

    循环参数列表的典型 Python 脚本:

    import os
    for r in (1.2,6.6): os.system('fortran_program %g'%r)
    

    当然,您应该使用您熟悉的任何脚本语言。我喜欢“高级”语言,因为我似乎不可避免地最终会在脚本中进行计算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2012-02-11
      • 2020-09-03
      • 2020-11-13
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      相关资源
      最近更新 更多