gfortran 运算符重载派生类型和 real()
gfortran operator overloading derived type and real()
我想重载运算符 (*) 以在以下 class 中执行向量标量乘法:
module vectorField_mod
use constants_mod
implicit none
private
public :: vectorField
public :: allocateVectorField
public :: delete
type vectorField
real(dpn),dimension(:,:,:),allocatable :: x,y,z
end type
interface operator (*)
module procedure scalarMultiply
end interface
contains
function scalarMultiply(f,g) result(q)
implicit none
type(vectorField),intent(in) :: f
real(dpn),intent(in) :: g
type(vectorField) :: q
q%x = f%x * g
q%y = f%y * g
q%z = f%z * g
q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
end function
...
end module
但我收到以下错误:
Error: Operands of binary numeric operator '*' at (1) are REAL(8)/TYPE(vectorfield)
我正在尝试像这样实现:
type(vectorField) :: a
real(8) :: dt = 0.001
call allocateVectorField(a,..)
a = a*dt
这不是二元运算吗?还有办法做到这一点吗?非常感谢任何帮助!
总结:
1) @francescalus 的回答是必要的,但不足以产生成功的编译。
2) 另外,事实证明乘法的顺序很重要。即 a = adt 有效,但 a = dta 无效(这是我遇到的问题)
这是一个示例:
module constants_mod
integer,parameter :: dpn = selected_real_kind(14)
end module
module vectorField_mod
use constants_mod
implicit none
private
public :: vectorField
public :: allocateX,allocateY,allocateZ
public :: delete
public :: operator(*)
type vectorField
integer,dimension(3) :: sx,sy,sz
real(dpn),dimension(:,:,:),allocatable :: x,y,z
end type
interface delete
module procedure deallocateVectorField
end interface
interface operator (*)
module procedure scalarMultiply
end interface
contains
function scalarMultiply(f,g) result(q)
implicit none
type(vectorField),intent(in) :: f
real(dpn),intent(in) :: g
type(vectorField) :: q
q%x = f%x * g; q%y = f%y * g; q%z = f%z * g
q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
end function
subroutine allocateX(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%x)) deallocate(field%x)
allocate(field%x(Nx,Ny,Nz))
field%sx = shape(field%x)
end subroutine
subroutine allocateY(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%y)) deallocate(field%y)
allocate(field%y(Nx,Ny,Nz))
field%sy = shape(field%y)
end subroutine
subroutine allocateZ(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%z)) deallocate(field%z)
allocate(field%z(Nx,Ny,Nz))
field%sz = shape(field%z)
end subroutine
subroutine deallocateVectorField(field)
implicit none
type(vectorField),intent(inout) :: field
deallocate(field%x,field%y,field%z)
field%sx = 0; field%sy = 0; field%sz = 0
end subroutine
end module
program test
use constants_mod
use vectorField_mod
implicit none
type(vectorField) :: a,b
integer :: N = 1
real(dpn) :: dt = 0.1
call allocateX(a,N,N,N)
call allocateY(a,N,N,N)
call allocateZ(a,N,N,N)
call allocateX(b,N,N,N)
call allocateY(b,N,N,N)
call allocateZ(b,N,N,N)
a%x = dble(1.0); a%y = dble(1.0); a%z = dble(1.0)
b%x = dble(1.0); b%y = dble(1.0); b%z = dble(1.0)
a = b
a = a*dt ! compiles fine
a = dt*a ! does not compile
call delete(a)
call delete(b)
end program
模块的默认可访问性是private
。此默认值也适用于定义的运算符。
要使运算符标识符 public(以便它可以在模块外使用),请使用 public
语句,例如:
public :: operator(*)
我想重载运算符 (*) 以在以下 class 中执行向量标量乘法:
module vectorField_mod
use constants_mod
implicit none
private
public :: vectorField
public :: allocateVectorField
public :: delete
type vectorField
real(dpn),dimension(:,:,:),allocatable :: x,y,z
end type
interface operator (*)
module procedure scalarMultiply
end interface
contains
function scalarMultiply(f,g) result(q)
implicit none
type(vectorField),intent(in) :: f
real(dpn),intent(in) :: g
type(vectorField) :: q
q%x = f%x * g
q%y = f%y * g
q%z = f%z * g
q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
end function
...
end module
但我收到以下错误:
Error: Operands of binary numeric operator '*' at (1) are REAL(8)/TYPE(vectorfield)
我正在尝试像这样实现:
type(vectorField) :: a
real(8) :: dt = 0.001
call allocateVectorField(a,..)
a = a*dt
这不是二元运算吗?还有办法做到这一点吗?非常感谢任何帮助!
总结:
1) @francescalus 的回答是必要的,但不足以产生成功的编译。
2) 另外,事实证明乘法的顺序很重要。即 a = adt 有效,但 a = dta 无效(这是我遇到的问题)
这是一个示例:
module constants_mod
integer,parameter :: dpn = selected_real_kind(14)
end module
module vectorField_mod
use constants_mod
implicit none
private
public :: vectorField
public :: allocateX,allocateY,allocateZ
public :: delete
public :: operator(*)
type vectorField
integer,dimension(3) :: sx,sy,sz
real(dpn),dimension(:,:,:),allocatable :: x,y,z
end type
interface delete
module procedure deallocateVectorField
end interface
interface operator (*)
module procedure scalarMultiply
end interface
contains
function scalarMultiply(f,g) result(q)
implicit none
type(vectorField),intent(in) :: f
real(dpn),intent(in) :: g
type(vectorField) :: q
q%x = f%x * g; q%y = f%y * g; q%z = f%z * g
q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
end function
subroutine allocateX(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%x)) deallocate(field%x)
allocate(field%x(Nx,Ny,Nz))
field%sx = shape(field%x)
end subroutine
subroutine allocateY(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%y)) deallocate(field%y)
allocate(field%y(Nx,Ny,Nz))
field%sy = shape(field%y)
end subroutine
subroutine allocateZ(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%z)) deallocate(field%z)
allocate(field%z(Nx,Ny,Nz))
field%sz = shape(field%z)
end subroutine
subroutine deallocateVectorField(field)
implicit none
type(vectorField),intent(inout) :: field
deallocate(field%x,field%y,field%z)
field%sx = 0; field%sy = 0; field%sz = 0
end subroutine
end module
program test
use constants_mod
use vectorField_mod
implicit none
type(vectorField) :: a,b
integer :: N = 1
real(dpn) :: dt = 0.1
call allocateX(a,N,N,N)
call allocateY(a,N,N,N)
call allocateZ(a,N,N,N)
call allocateX(b,N,N,N)
call allocateY(b,N,N,N)
call allocateZ(b,N,N,N)
a%x = dble(1.0); a%y = dble(1.0); a%z = dble(1.0)
b%x = dble(1.0); b%y = dble(1.0); b%z = dble(1.0)
a = b
a = a*dt ! compiles fine
a = dt*a ! does not compile
call delete(a)
call delete(b)
end program
模块的默认可访问性是private
。此默认值也适用于定义的运算符。
要使运算符标识符 public(以便它可以在模块外使用),请使用 public
语句,例如:
public :: operator(*)