移植旧的fortran程序以使用python + numpy

oso*_*maz 5 python fortran numpy fortran90 f2py

我应该用这个庞大的Fortran 77程序进行研究(我最近将它移植到Fortran 90表面).它是一个非常古老的软件,用于使用有限元方法进行建模.

  • 这是一个怪物.它大约有240,000行.
  • 自从它在Fortran 77中开始使用以来,它使用了一些非常脏的黑客进行动态内存分配; 基本上它使用C标准库中的函数,使用C和Fortran进行混合编程.我还没有完全掌握分配的工作原理.该程序可以由用户轻松扩展,用户通常需要分配一些全局可访问的数组供以后使用.这是通过具有一组内存地址来完成的,这些内存地址指向动态可分配数组的起始地址.当然,在开始真正编程之前,地址数组的哪个元素指向哪些信息都取决于用户必须学习的约定.有两个地址数组,一个用于整数,另一个用于浮点.
  • 肮脏的黑客,我的意思是不一致的.例如,GNU编译器的优化算法中的更新导致程序以随机​​内存泄漏退出.
  • 该计划远非优雅.全局变量名称通常较短(3-4个字符)且含糊不清.当然,通过使用包括所有程序开关和前述阵列的公共块来实现跨例程传递数据.
  • 该程序的使用大致类似于交互式shell,尽管是一个愚蠢的程序.首先,程序本身读取输入文件,然后根据选择,将用户放入伪shell中,用户必须键入4个字符宽的命令,然后输入参数.然后解析器解析命令,并使用参数调用相应的子例程.你猜,有在这个伪解析器循环结构(一个goto富矿,而),其包装在更复杂的比它应该是在21世纪的方式子程序的行为.
  • 输入文件的格式是相同的(命令,然后是参数),因为它是相同的解析器.但是语法并不是真的一致(我的意思是它缺乏控制结构,有些命令会导致有限状态机做与其他命令相矛盾的行为;它缺乏明确的语法),不时导致最终用户发现陷阱.用户必须通过经验了解这些陷阱; 我没有在程序的任何文档中看到它们.这是一个可以使用python轻松避免的问题,甚至不需要实现解析器.

我想做的事:

  • 程序的端口部分为python,即与数值计算无关的部分.这包括
    • 在python中使用OOP方法清理和抽象API,
    • 给出有意义的变量名,
    • 将动态分配迁移到numpy或Fortran 90并丢失C部分,
    • 将非数字执行迁移到python,并使用包装数字对象f2py,因此性能没有损失.我已经告诉该节目是该死在当前状态快?希望将对数字子程序和I/O的调用移植到python不会减慢到不切实际的水平(或者它会吗?).
    • 利用python的交互式shell作为伪shell的替代品.这样,最终用户就不会有任何不一致之处.上述命令将简单地由python中定义的函数替换.这将允许用户实际访问数据.此外,用户将能够扩展程序而无需深入.

我想知道:

  • 是否f2py适合并完成包装众多子程序和公共块而没有任何混淆的任务?我只在网上看过单文件示例f2py; 我知道numpy已经用它来包装LAPACK和东西,但我需要保证这f2py是一个足以完成这项任务的工具.
  • 是否对我应该遵循的总体策略有任何建议,或者我应该避免陷阱.
  • 如何在这个python包装的Fortran 90环境中实现一个系统,以便我能够在fortran例程中修改(分配和分配)全局可访问的数组和变量.这应该优选地省略地址数组,并且我应该优选地能够将口头表示注入命名空间.这些变量最好在python和fortran中都可以访问.

笔记:

  • 我可能一直在要求太多,超出了可能范围的界限.在这种情况下,请原谅我,因为我是这方面编程的初学者; 并且毫不犹豫地纠正我.
  • 我一直在谈论的"程序"是开源的,但它是商业的,许可证不允许其分发,所以我决定不提它的名字.但是,您可以从第二句和我给出的描述中推断出它.

Jon*_*eld 3

我正在做一些令人沮丧的类似事情。我们没有通过 C 进行动态内存分配,而是使用带有整数索引的单个全局数组(也在全局范围内),但除此之外它几乎是相同的。奇怪的、不一致的输入文件等等。

我建议不要尝试重写大部分程序,无论是用 python 还是其他任何东西。这是耗时的、令人不愉快的并且基本上是不必要的。作为替代方案,获取 F77 代码库,使其编译得足够干净以至于您愿意信任它,然后编写一个接口例程。

我现在有一个又大又丑的 F77 代码库,它位于界面后面。该程序需要以文本文件形式输入,因此界面的大部分工作是生成该文本文件。除此之外,遗留代码被简化为单个网关例程,该例程采用一些参数(包括识别文本文件的方法)并返回答案。如果您使用 Fortran 2003 的 iso_c_binding,您可以以 C 理解的格式公开接口,此时您可以将其链接到您想要的任何内容。

就现代代码(主要是优化例程)而言,遗留代码库是 C 接口背后的单个子例程。这比尝试进一步修改旧代码要好得多,并且对于您的情况来说可能也是一个有效的策略。