派生类型的可变长度数组 [英] variable length array in derived type

查看:86
本文介绍了派生类型的可变长度数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我主要使用Python进行科学编程,并且没有大量的Fortran(90/95)经验.对于我的一个项目,我想定义一个派生类型,并为该类型重载一堆运算符.至关重要的是,我希望派生类型的变量之一为可变长度的数组.至少,我在代码的不同部分需要两个不同的长度.如何才能最好地有效地做到这一点并避免代码重复?

I am mostly doing scientific programming in Python and do not have a whole lot of Fortran (90/95) experience. For one of my projects I want to define a derived type and overload a bunch of operators for that type. Critically, I'd like one of the variables of the derived type to an array of variable length; at least, I need two different lengths in different parts of the code. How can I best achieve this efficiently and avoiding code duplication?

我的第一种方法是使用可分配的数组,但是该方法涉及整个代码中的多个分配语句,包括重载的运算符.这也导致在MPI应用程序中使用代码时遇到困难.

My first approach was to use an allocatable array but that involved several allocate statements throughout the code including the overloaded operators. It also led to difficulties when using the code in an MPI application.

我目前的方法是两个在两个单独的模块中定义一个具有相同名称的类型,并在代码的不同部分使用一个或另一个.可以使用头文件(在下面的示例中为mytype_operators.h)共享重载的运算符.

My current approach is two define a type of the same name in two separate modules and use one or the other in different parts of the code. The overloaded operators can be shared using a header file (mytype_operators.h in the example below).

    module mod1
      type mytype
        real :: x1
        real,dimension(1) :: x2
      end type mytype
#include "mytype_operators.h"
    end module mod1

    module mod2
      type mytype
        real :: x1
        real,dimension(10) :: x2
      end type mytype
#include "mytype_operators.h"
    end module mod2

不幸的是,代码中有一个模块带有我想对两种类型都使用的子例程.目前,我有该代码的两个副本.一个带有"use mod1",另一个带有"use mod2".我可以改善这一点并避免代码重复吗?

Unfortunately, there is one module in the code with subroutines that I would like to use for both types. Currently I have two copies of that code; one with "use mod1", the other with "use mod2". Can I improve this and avoid the code duplication?

推荐答案

您的案例非常适合使用名为

Your case is very suitable for using a Fortran feature introduced in the 2003 standard (and adopted much later by compilers) named parameterized derived types. First of all, you should check the compliance status of your compiler to know if it's fully supported.

此功能允许您在声明或构造派生类型时传递自定义参数,因此将相应地调整内部功能.它们有利于将不同的行为替代方案分组在一个类型名称中,可能会有相当大的编码或存储差异.参数有2种类型:

This feature allows you to pass custom parameters when declaring or constructing a derived-type, so internal functionality will be adjusted accordingly. They are good for having different behaviour alternatives grouped in a single type name, possibly with considerable coding or storage differences. There are 2 types of parameters:

  • kind参数的行为与内在类型的种类说明符非常相似.所有变量的种类参数在编译时都必须知道,并且实际上被视为常量值.方便之处在于,您可以通过仅更改声明或构造中的值来轻松地(在代码时间内)更改它.通常用于专门说明内在类型的组件的类型.
  • len参数的行为非常类似于固有字符类型的len说明符.您可以在编译时或运行时定义len参数,并且变量的len参数除非声明为可分配的,否则不能更改.此外,您可以在过程中使用带有假定len参数的参数,并避免代码冗长.通常将它用作派生类型的长度"或尺寸"参数,因为您可以在数组边界和字符长度的声明中使用它们.
  • kind parameters behave much like the kind specifier of intrinsic types. Kind parameters of all variables must be known at compile time and are treated practically as constant values. The convenience is that you could change it easily (in code time) by altering just a value in the declaration or construction. This is commonly used for specializing the kind of components of intrinsic type.
  • len parameters behave much like the len specifier of intrinsic character type. You can define len parameters at compile time or runtime, and a len parameter of a variable cannot change unless you declared it allocatable. Moreover, you can have arguments with assumed len-parameters in procedures, and avoid code verbosity. This is commonly used as a "length" or "dimension" parameter for a derived type, because you can use them in the declaration of array bounds and character length.

通常,类型参数用于模拟派生类型中内在类型的功能,但您也可以获取创意"并将其用于其他事物,例如转换矩阵类型的维空间;例如,用于自定义联合类型"(如枚举);因为计量单位"数据类型中的物理量的性质(标注为质量"单位的实数值与温度"单位不直接兼容,但是可以用相同的方式处理它们)代码);元组类型的"arity" ...

In general, type parameters are used to mimic the functionality of intrinsic types in derived types, but you could also get "creative" and use it for other things, like the dimension-space of a transformation-matrix type; for a custom "union type" (like an enumeration); as the nature of a physical quantity in a "units of measurement" data-type (a real value annotated with "mass" unity is not directly compatible with a "temperature" one, but they can be handled pretty much the same way in the code); the "arity" of a tuple type...

module mod1
  type :: mytype(n)
    integer, len :: n
    real :: x1
    real, dimension(n) :: x2
  end type mytype
contains
  ! your operations here...
end module mod1

并像这样使用它:

program test_pdt
  use mod1
  implicit none

  type(mytype(10)) :: mt10
  type(mytype(1)) :: mt1
  integer :: i

  mt10%x1 = 40.0
  mt10%x2 = [(0.5 * i, i = 1, 10)]
  mt1 = mytype(1)(20.0, [30.0])

  call sub(mt10)
  call sub1(mt1)

contains
  subroutine sub(m)
    ! accepts values with any "n" parameter
    type(mytype(*)) :: m
    ! you can also use them in declarations
    integer, dimension(m%n + 1) :: y
    type(mytype(m%n)) :: w
    print *, m%n, w%n, size(y)
  end

  subroutine sub1(m)
    type(mytype(1)) :: m  ! only accepts values with n=1
    print *, m%x1, m%x2, m%n
  end
end


警告: 尽管很多年前就宣布了此功能,但最近才将其添加到大多数编译器中,您应该意识到实现中仍然存在一些错误.常规使用可能会很好,但是在某些特殊情况下,甚至在ICE上,我经常会遇到错误的语法错误.


Warning: This is feature, despite of having been announced many years ago, was just recently added to most compilers, and you should be aware that there are still some bugs in implementation. You should probably be fine with regular use, but I often face false syntax errors in some corner cases, and even ICE sometimes.

这篇关于派生类型的可变长度数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆