如何在不破坏模块性的情况下公开程序数据以进行灵敏度分析?

时间:2014-04-11 12:32:09

标签: oop fortran modularity

我有一个包含大量模型的计算机程序(Fortran)。这些模型在相关性中包含常数系数。目前,这些常数系数都是模型所在的例程的私有和局部。然而,我希望对这些相关系数中的许多进行敏感性研究,这意味着我需要能够从他们的默认通过用户输入。我还需要这种能力来改变这些参数,以便随着代码的进一步发展而保持最新状态。

最明显的解决方案是将所有这些参数打到自己的模块中,使它们全局化,然后创建一个例程来读取用户输入并相应地修改这些参数。但这绝对会破坏代码的模块性。包含依赖于这些参数的模型的所有例程将依赖于包含所有全局变量的那个模块。

另一个更加劳动密集的解决方案是创建" setter"每个模块中具有需要修改的模型参数的例程。参数在模块中保持私有,但可以通过可从我的灵敏度分析模块调用的setter例程进行修改。

还有什么我想念的吗?更优雅的解决方案?

1 个答案:

答案 0 :(得分:1)

这很大程度上取决于程序的结构,但我喜欢的方法是使用带有默认参数的模块init / finalize子程序:

module paramcalculation
implicit none

real    :: param1
integer :: param2
real,    parameter :: defaultParam1 = 1.0
integer, parameter :: defaultParam2 = 2

contains

    subroutine paramCalcInit( p1, p2 )
        real,    optional, intent(in) :: p1
        integer, optional, intent(in) :: p2

        if (present(p1)) then
            ! do any checking needed
            param1 = p1
        else
            param1 = defaultParam1
        end if

        if (present(p2)) then
            ! do any checking needed
            param2 = p2
        else
            param2 = defaultParam2
        end if
    end subroutine paramCalcInit

    subroutine paramCalcFinalize
        ! clean up any module stuff that needs cleaning up
    end subroutine paramCalcFinalize

    elemental function doParamCalc(x, y)
       real, intent(in) :: x
       real, intent(in) :: y
       real :: doParamCalc
       doParamCalc = param1*x + param2*y
    end function doParamCalc

end module paramcalculation


program testCalc
    use paramcalculation
    implicit none

    real, dimension(5) :: x
    real, dimension(5) :: y
    real, dimension(5) :: z

    x = 10
    y = 2

    call paramCalcInit( p2 = 0 )

    z = doParamCalc(x, y)

    print *, 'Input:  ', x
    print *, 'Output: ', z

    call paramCalcFinalize
end program testCalc

跑步给出

$ gfortran -o params params.f90
$ ./params
 Input:     10.000000       10.000000       10.000000       10.000000       10.000000
 Output:    10.000000       10.000000       10.000000       10.000000       10.000000