在Fortran中以牛顿方法传递其他参数

时间:2018-09-06 03:51:17

标签: fortran parameter-passing newtons-method

我无法在Fortran程序中实现一种调用牛顿方法的方法。 因此,我想使用牛顿法来求解the link

之后的方程

但是,我的程序与上面的示例略有不同。在我的情况下,方程式需要一些其他信息,这些信息是在运行时生成的。

pandas

这意味着f不仅基于x进行计算,还基于其他一些变量(但x是未知数)计算。

我有一个解决方案,该解决方案仅适用于简单情况: 我使用了一个模块来包含牛顿的求解器。我还定义了一个派生数据类型来保存模块内部的所有参数。现在效果很好。

我的问题是:我需要多次调用牛顿方法,并且每次参数都不相同。我应该如何设计模块的结构?还是应该使用其他解决方案?

我在下面提供了一个简单的示例:

subroutine solve(f, fp, x0, x, iters, debug)

调用模块是:

module solver
  type argu
    integer :: m
  end type argu
  type(argu):: aArgu_test  !should I put here?
  contains
    subroutine solve(f, fp, x0, x, iters, debug)
       ...
       !m is used inside here
    end subroutine solve
    subroutine set_parameter(m_in)
       aArgu%m = m_in
    end subroutine set_parameter()

end module solver

我的理解是,如果将argu对象放在Solver模块中,则所有Solver调用都将使用相同的参数(我仍然可以使用上述方法将所有参数保存在A模块中)。在那种情况下,我必须在每个for循环中更新参数吗?

因为程序使用MPI / OpenMP运行,所以我想确保线程之间没有覆盖。 谢谢。

2 个答案:

答案 0 :(得分:3)

现代Fortran中有一个常见的模式可以解决您面临的问题(partial function application)。与其他语言不同,Fortran没有函数闭包,因此为函数建立词法作用域有点“费解”,而且有点局限。

您应该真正考虑重新访问评论中@VladmirF共享的所有链接,其中大多数直接适用于您的案例。我会给你一个解决方案的例子。

这是不使用包装器类型的解决方案。我将使用Fortran 2008标准中包含的功能:传递内部过程作为参数。它与最新的gfortran,Intel等兼容。 如果您无法使用此功能访问编译器,或者您希望使用派生类型的解决方案,则可以参考this答案。

headers.add("Content-Disposition", "attachment; filename=" + "example.pdf");

此代码的原理是:由于df = df1.merge(df2, how='left', left_on='A', right_on = 'A') def select(row, field): if row['{}_y'.format(field)] is np.nan: return row['{}_x'.format(field)] else: return row['{}_y'.format(field)] df['C'] = df[['C_x', 'C_y']].apply(select, field='C', axis=1) df['B'] = df[['B_x', 'B_y']].apply(select, field='B', axis=1) module without_custom_type use, intrinsic :: iso_fortran_env, only: r8 => real64 use :: solver contains subroutine solve_quad(a, b, c, x0, x, iters, debug) integer, intent(in) :: a, b, c real(r8), intent(in) :: x0 real(r8), intent(out) :: x integer, intent(out) :: iters logical, intent(in) :: debug call solve(f, fp, x0, x, iters, debug) contains real(r8) function f(x) real(r8),intent(in) :: x f = a * x * x + b * x + c end real(r8) function fp(x) real(r8),intent(in) :: x fp = 2 * a * x + b end end end 位于f过程中,因此他们可以访问参数fpsolve_quada(通过主机关联),而无需触摸这些功能的签名。产生的效果就像更改函数的Arity。

使用gfortran 8.0和您共享的链接中的b实现对其进行测试,我得到了:

c

答案 1 :(得分:1)

与同事讨论后,我对问题2有了解决方案。

如果求解器模块只有一个参数对象,则所有调用将访问相同的参数,因为它们共享相同的内存空间。

为避免这种情况,我们希望将参数对象作为参数传递给求解器。 因此,我们将使用牛顿的方法来重写它,以接受其他参数,而不是使用默认的求解器子例程。

(我之前使用了最简单的Newton子例程,因为我希望保持不变。)

这样,我们将定义一个参数对象数组,并在运行时传递它们。

谢谢您的评论。