Fortran多态,函数和分配 [英] Fortran polymorphism, functions and allocation

查看:154
本文介绍了Fortran多态,函数和分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Fortran的OOP的初学者,我正在尝试编写一个程序来处理多态变量作为参数。
虽然我的原始代码要复杂得多(很多过程,几个派生类型等),但我可以隔离一个我的问题的简单例子,例如:我有一个过程复制一个多态变量并略微修改此副本。 / p>

我能够使用子程序成功编写我的测试程序

  MODULE my_module 

type :: my_type
real :: data
endtype my_type

type,extends(my_type) :: my_derived_type
结束类型my_derived_type

CONTAINS

子程序sub_copy(旧的,新的)
隐式无
class(my_type),intent (in):: old
class(my_type),allocatable,intent(out):: new
allocate(new,source = old)
new%data = new%data + 1
end子程序sub_copy

END MODULE my_module

程序my_prog
使用my_module
隐式无
类型(my_derived_type):: x
class(my_type),allocatable :: y

x%data = 1.0
call s ub_copy(x,y)
print *,y%data
解除分配(y)

结束程序my_prog

这对于预期结果和内存分配/释放都很好。



然而,我一直在努力尝试使用Fortran 函数来完成相同的工作。



看起来像一个类似于子程序的方法定义的函数(见下文)不能简单地用作

pre> y = fun_copy(x)

和我的gfortran编译器(v5.0.0)抱怨:

 错误:赋值给(1)处的可分配多态变量尚未支持

我在这里和那里看到,编译器不支持这样的赋值。等待这个,我试图通过定义我自己的赋值运算符(=)来解决这个问题。以下代码有效:

  MODULE my_module 

类型:: my_type
real ::数据
endtype my_type

类型,extends(my_type):: my_derived_type
结束类型my_derived_type

接口赋值(=)
模块过程myassign
结束界面

CONTAINS

函数fun_copy(旧)结果(新)
隐式无
class(my_type),intent( in):: old
class(my_type),allocatable :: new
allocate(new,source = old)
new%data = new%data + 1
end function fun_copy

子程序myassign(new,old)
class(my_type),intent(in):: old $ b $ class(my_type),allocatable,intent(out):: new
allocate(new,source = old)
结束子程序

END MODULE my_module

PROGRAM my_prog
使用my_module
隐含无
type(my_derived_type):: x
class(my_type),allocatable :: y

x%data = 1.0
y = fun_copy(x)
print *,y%data
deallocate(y)

END PROGRAM my_prog

它的工作原理的确如此, code> x 创建为 y
然而,检查这个简单测试程序的内存预算(我在OS X上使用了 Instrument 软件),似乎有些内存在其结束之前未被释放。
我怀疑 copy 函数和赋值子例程都分配了内存,而且我只释放了一次,剩下一次分配。



由于我打算在更复杂的代码中使用这样的例程很多次,所以我非常关心内存分配/释放。
当然,我可以使用程序的子程序版本,但如果有办法,我更喜欢功能版本。 b
$ b

有没有办法处理这样的问题?

解决方案

指针?

 模块my_module 

隐式无

型:: my_type
real :: data
包含
过程:: sub_copy
过程:: fun_copy_ptr
过程:: fun_copy_alloc
过程,pass(this):: my_assign
generic :: assignment(=)=> my_assign
结束类型my_type

类型,extends(my_type):: my_derived_type
结束类型my_derived_type

包含

子例程sub_copy(this,new)
class(my_type),intent(in):: this $ b $ class(my_type),allocatable,intent(out):: new

allocate( new,source = this)
new%data = new%data + 1

end子程序sub_copy

函数fun_copy_alloc(this)result(new)
class(my_type),intent(in):: this $ b $ class(my_type),allocatable :: new

allocate(new,source = this)
new%data =新%数据+ 1.0

结束函数fun_copy_alloc

函数fun_copy_ptr(this)结果(新)
class(my_type),intent(in):: this
class(my_type),pointer :: new

allocate(new,source = this)
new%data = new%data + 1.0

结束函数fun_copy_ptr

子程序my_assign(new,this)
class(my_type),intent( in):: this
class(my_type),allocatable,intent(out):: new

allocate(new,source = this)

结束子程序

结束模块my_module

程序my_prog

使用my_module,仅:&
my_type,&
my_derived_type
$ b隐式无
类型(my_derived_type):: x
class(my_type),allocatable :: y $ b $ class(my_type),指针: :y_ptr => null()

x%data = 1.0

!案例1
调用x%sub_copy(y)
print *,y%data
deallocate(y)

!案例2
y_ptr => x%fun_copy_ptr()
print *,y_ptr%data
deallocate(y_ptr)

!案例3
分配(y,源= x%fun_copy_alloc())
print *,y%data
解除分配(y)

结束程序my_prog


I am quite a beginner in OOP with Fortran and I am trying to write a program with procedures that deal with polymorphic variables as arguments. Although my original code is much more complicated (many procedures, several derived types etc), I could isolate a simple example of my problem, say: I have a procedure that copies a polymorphic variable and slightly modifies this copy.

I was able to successfully write my test program using a subroutine:

MODULE my_module

type :: my_type
    real :: data
endtype my_type

type, extends(my_type) :: my_derived_type
end type my_derived_type

CONTAINS

subroutine sub_copy(old,new) 
implicit none
class(my_type), intent(in) :: old
class(my_type), allocatable, intent(out) :: new
allocate(new, source = old)
new%data = new%data + 1
end subroutine sub_copy

END MODULE my_module

PROGRAM my_prog
use my_module
implicit none
type(my_derived_type) :: x
class(my_type), allocatable :: y

x%data = 1.0
call sub_copy(x,y)
print*,y%data
deallocate(y)

END PROGRAM my_prog

This performs nicely both regarding the expected result and the memory allocation/deallocation.

However, I have been fighting for days trying to make working a Fortran function that would do the same job.

It seems that a function defined in a similar way to the subroutine (see here after) cannot be used simply as

y = fun_copy(x)

and my gfortran compiler (v5.0.0) complains:

Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported

I have read here and there that indeed such assignment is not supported by my compiler. Waiting for that, I have tried to work that around by defining my own assignment operator (=). The following code works:

MODULE my_module

type :: my_type
    real :: data
endtype my_type

type, extends(my_type) :: my_derived_type
end type my_derived_type

interface assignment(=)
  module procedure myassign
end interface

CONTAINS

function fun_copy(old) result(new) 
implicit none
class(my_type), intent(in) :: old
class(my_type), allocatable :: new
allocate(new, source = old)
new%data = new%data + 1
end function fun_copy

subroutine myassign(new,old)
class(my_type), intent(in)  :: old
class(my_type), allocatable, intent(out) :: new
allocate(new, source=old)
end subroutine

END MODULE my_module

PROGRAM my_prog
use my_module
implicit none
type(my_derived_type) :: x
class(my_type), allocatable :: y

x%data = 1.0
y = fun_copy(x)
print*,y%data
deallocate(y)

END PROGRAM my_prog

It works in the sense that indeed, a copy of x is created as y. However, inspecting the memory budget of this simple test program (I use the Instrument software on OS X), it appears that some memory is not deallocated before the end of it. I suspect that the copy function and the assignment subroutine both allocate memory and that I only free one occurrence, leaving one allocated.

As I intend to use such a routine a large number of times in a much more complicated code, I am really concerned about memory allocation/deallocation. Of course, I can use the subroutine version of the program, but if there is a way, I would prefer the function version.

Is there a way to deal with such a problem?

解决方案

Have you tried using pointers?

    module my_module

        implicit none

        type :: my_type
            real :: data
        contains
            procedure              :: sub_copy
            procedure              :: fun_copy_ptr
            procedure              :: fun_copy_alloc
            procedure, pass (this) :: my_assign
            generic                :: assignment(=) => my_assign
        end type my_type

        type, extends(my_type) :: my_derived_type
        end type my_derived_type

    contains

        subroutine sub_copy(this, new)
            class(my_type), intent (in)               :: this
            class(my_type), allocatable, intent (out) :: new

            allocate(new, source=this)
            new%data = new%data + 1

        end subroutine sub_copy

        function fun_copy_alloc(this) result (new)
            class(my_type), intent(in)  :: this
            class(my_type), allocatable :: new

            allocate(new, source=this)
            new%data = new%data + 1.0

        end function fun_copy_alloc

        function fun_copy_ptr(this) result (new)
            class(my_type), intent(in) :: this
            class(my_type), pointer    :: new

            allocate(new, source=this)
            new%data = new%data + 1.0

        end function fun_copy_ptr

        subroutine my_assign(new, this)
            class(my_type), intent(in)               :: this
            class(my_type), allocatable, intent(out) :: new

            allocate(new, source=this)

        end subroutine

    end module my_module

    program my_prog

        use my_module, only: &
            my_type, &
            my_derived_type

        implicit none
        type(my_derived_type)       :: x
        class(my_type), allocatable :: y
        class(my_type), pointer     :: y_ptr => null()

        x%data = 1.0

        ! Case 1
        call x%sub_copy(y)
        print *, y%data
        deallocate(y)

        ! Case 2
        y_ptr => x%fun_copy_ptr()
        print *, y_ptr%data
        deallocate(y_ptr)

        ! Case 3
        allocate( y, source=x%fun_copy_alloc() )
        print *, y%data
        deallocate(y)

    end program my_prog

这篇关于Fortran多态,函数和分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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