使用不同的输入参数在fortran中多次运行代码

时间:2017-10-09 16:01:00

标签: fortran gfortran fortran77

我想用不同的输入参数集多次运行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 

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

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

为了回应下面的评论之一,如果每个运行的文件都有不同的输入选择,那么如何让程序为每次运行的不同参数选择获取不同的行?

4 个答案:

答案 0 :(得分:7)

我曾经多次使用过“行人”式的方法。

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

我在下面给出一个单个参数的示例,但如果需要,您可以对其进行概括。它依赖于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的文件,并读取radius值的第一个条目。

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

  3. 评论:

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

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

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

    4. 我任意使用了11个文件单元号。您的实际情况确实需要为您的计划使用可用的单位编号。

答案 1 :(得分:1)

如果更改为代码,则需要重新编译。

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

检查CHECK_COMMAND_ARGUMENTNamelists,了解如何执行此操作。

但是如果你想沿着路径重新编译它,你可以使用预处理器来设置代码的某些部分。

请参阅此示例代码:

"python.pythonPath": "python3.6"

要使用预处理器,您必须明确告诉编译器执行此操作(例如 PROGRAM area IMPLICIT NONE PRINT *, "area of circle with radius ", RADIUS, " is ", & 3.15159 * RADIUS**2 END PROGRAM area gfortran -cpp),或者您可以将扩展名更改为大写ifort -fpp(或现代Fortran的.F,默认启用预处理器。

.F90

答案 2 :(得分:1)

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

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

在我的情况下,我可能正在使用无法进行长达一个月的QA循环而无法重新编译的代码,因此将参数化变体代码编写为单独的脚本要比使用它便宜得多。将它集成到我的Fortran代码中。

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

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

答案 3 :(得分:1)

命令行参数方法

  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)

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