unknown wrong in a fortran array code - arrays

I checked this code many times and could not figure out how to correct it.
program main
implicit none
real, parameter :: dx=1
real, parameter :: dy=1
real :: a1, a2, a3, a4, a5
a1=dy/dx
a2=dx/dy
a3=-2*(dy/dx+dx/dy)
a4=dx/dy
a5=dy/dx
REAL, DIMENSION(5,1):: a
DATA a/a1,a2,a3,a4,a5/
!write (*,*) a(1),a(2)
pause
endprogram
thank you very much and the error:
error #6236:A specification statement cannot appear in the executable section.
error #6404: This name does not have a type, and must have an explicit type. [A]
error #6211: A symbol must be a defined parameter in this context.

You are mixing specification (data declaration) statements and executable statements. The declaration statements must go first and the executable statements can only follow after them inside each compilation unit or block.
Also, entity used for initialization in the DATA statement must be a constant expression.
One way to fix your code is:
program main
implicit none
real, parameter :: dx=1
real, parameter :: dy=1
real, parameter :: a1=dy/dx
real, parameter :: a2=dx/dy
real, parameter :: a3=-2*(dy/dx+dx/dy)
real, parameter :: a4=dx/dy
real, parameter :: a5=dy/dx
REAL, DIMENSION(5,1):: a
DATA a/a1,a2,a3,a4,a5/
!write (*,*) a(1),a(2)
end program
Don't use the PAUSE statement. It is deleted from modern Fortran and it is not clear (portably) what should it actually do even in the older versions.
You can also initialize the array using an array constructor. You don't need constant expressions in that case:
program main
implicit none
real, parameter :: dx=1
real, parameter :: dy=1
REAL, DIMENSION(5,1) :: a
a = reshape([dy/dx, dx/dy, -2*(dy/dx+dx/dy), dx/dy, dy/dx], [5,1])
end program

Related

How to create array of arrays from all variables in a module

I have a number of variables declared in a module such as
module test
use othermod, only: n
integer, dimension(n) :: var0
real, dimension(n) :: var1
real, dimension(n) :: var2
.....
real, dimension(n) :: var1000
end module test
Then I have a subroutine that fills these variables with values.
At this point I would like to create an array of arrays with all the variables declared in module test so that I can easily copy or print all variables of a particular (n) at the same time, like dimension(n,allvariablesin module test). For example I would like to do something like array(3,:)=array(2,:).
Because this code is part of a very large program I cannot really modify too much, but rather I need to create an array of arrays from all the variables in this module without typing all the variables.
How can I easily integrate this change in the current code?
I urge you follow to #Vladimir F's advice and encapsulate your variables inside a derived data type. You can employ the associate construct to call old codes expecting var0, var1, .., etc. Lastly, we can overload the type's name to get a Java style constructor in the code below
module type_MyArray
implicit none
private
type, public :: MyArray
! type-components
real, dimension(:), allocatable :: var0, var1, var2
contains
! type-bound procedures
procedure :: create => create_my_array
procedure :: destroy => destroy_my_array
end type MyArray
interface MyArray
module procedure my_array_constructor
end interface MyArray
contains
pure function my_array_constructor(n) result (return_value)
! Dummy arguments
integer, intent (in) :: n
type (MyArray) :: return_value
call return_value%create(n)
end function my_array_constructor
pure subroutine create_my_array(self, n)
! Dummy arguments
class(MyArray), intent(in out) :: self
integer, intent(in) :: n
allocate( self%var0(n) )
allocate( self%var1(n) )
allocate( self%var2(n) )
end subroutine create_my_array
pure subroutine destroy_my_array(self)
! Dummy arguments
class(MyArray), intent(in out) :: self
if (allocated(self%var0)) deallocate( self%var0 )
if (allocated(self%var1)) deallocate( self%var1 )
if (allocated(self%var2)) deallocate( self%var2 )
end subroutine destroy_my_array
end module type_MyArray
program main
use type_MyArray, only: MyArray
use old_code, only: do_something
implicit none
type (MyArray) :: foo, bar
! Allocate memory
foo = MyArray(42)
bar = MyArray(4200)
associate( var0 => foo%var0, var1 => bar%var1 )
! Call old code using var0 and var1
call do_something(var0, var1)
end associate
! Release memory
call foo%destroy()
call bar%destroy()
end program main

FORTRAN: Use character as changeable array name

I am trying to write a subroutine to access arrays in a certain manner.
One input argument of the subroutine is a character containing the name of the array whose access is desired. Here is a rather simplified code example of how I generally imagine this to work:
PROGAM prog
real, dimension(3,3) :: array1(3,3)
real, dimension(3,3) :: array2(3,3)
real value1
real value2
... fill 'array1' and 'array2'...
call sub(array1,2,2,value1)
call sub(array2,2,2,value2)
... do something with 'value1' and 'value2'...
END
SUBROUTINE sub(name,x,y,out)
character(len=*), intent(in) :: name
integer, intent(in) :: x
integer, intent(in) :: y
real, intent(out) :: out
out = name(x,y)
RETURN
END
What I want is the subroutine to access array1(2,2) as requested in the argument and return this value to value1. Then access array2(2,2) and return this value to value2. Above code snippet does not work - no wonder about that. How do I get name(x,y) replaced with array1(x,y) respectively array2(x,y)?
Thanks a lot and best regards!
It is not necessary to use the name of the array to get at its content, if the array is declared in caller. You then use normal argument association.
You could write your subroutine as
subroutine sub(a,x,y,out)
integer, intent(in) :: x, y
real, intent(out) :: out
real, dimension(:,:), intent(in) :: a
out = a(x,y)
end subroutine sub
Much simpler would be to do, in the main program
value1 = array1(2,2)
value2 = array2(2,2)
I would recommend a textbook on Fortran, or even a look at http://en.wikipedia.org/wiki/Fortran_95_language_features .
Edit:
You could also use a SELECT CASE statement, like this:
subroutine bar(c, i, j, out)
character(len=*), intent(in) :: c
integer, intent(in) :: i,j
real, intent(out) :: out
select case (trim(c))
case ("array1")
out = array1(i,j)
case ("array2")
out = array2(i,j)
case default
stop "Argument is bletchful"
end case
end subroutine bar
I am simply at a loss to understand what good this would do, as opposed to using the array directly.
Is this what you want?
select case (array_name)
case ("array_dog")
array_ptr => array_dog
case ("array_cat")
array_ptr => array_cat
end select
where array_name is a character variable, array_dog and array_cat are arrays declared in the module (needing target attribute), and array_ptr is another array with the pointer attribute.

multiple definition link error in fortran (ifort - gfortran)

Well, I've this problem (the description is long, but I think it is easy to solve) . I've three files:
nrtype.f90, which have some stupid definitions, but it is used by the following files:
module nrtype
integer, parameter :: I4B = SELECTED_INT_KIND(9)
integer, parameter :: I2B = SELECTED_INT_KIND(4)
integer, parameter :: I1B = SELECTED_INT_KIND(2)
integer, parameter :: SP = KIND(1.0)
integer, parameter :: DP = KIND(1.0D0)
endmodule nrtype
LUd.f90, which makes part of the work:
module descomposicionLU
use nrtype
implicit none
contains
subroutine LUd(A, LU, bk)
implicit none
real(DP), intent (in), dimension(:,:) :: A
real(DP), intent (out), dimension(:,:) :: LU
integer(I2B), dimension(size(A,1),2) :: bk
<more code that doesn't worth to mention>
endsubroutine LUd
<more code that doesn't worth to mention>
endmodule descomposicionLU
A file called FrontBackSub.f90, which does the other part of the work:
module FrontBack
use nrtype
implicit none
contains
function FrontSLU(A,B) result (X)
implicit none
real(DP), dimension(:,:), intent (in) :: A, B
real(DP), dimension(size(B,1),size(B,2)) :: X
<more code>
endfunction FrontSLU
endmodule FrontBack
And finallymain.f90, which is something like this:
program main
use descomposicionLU
use FrontBack
implicit none
integer, parameter :: N=3
real(DP), dimension(N,N) :: MA, MLU
integer(I2B), dimension(N,2) :: Vbk
MA(1,:)=(/1.0, 7.0, 11.0/)
MA(2,:)=(/14.0, 24.0, 19.0/)
MA(3,:)=(/7.0, 8.0, 9.0/)
call LUd(MA, MLU, Vbk)
endprogram main
But, the issue comes during compilation, with ifort nrtype.f90 FrontBackSub.f90 LUd.f90 FrontBackSub.f90 main.f90 i've got:
/tmp/ifortbW2y7D.o: In function `frontback._':
FrontBackSub.f90:(.text+0x0): multiple definition of `frontback._'
/tmp/ifortVQdBCN.o:FrontBackSub.f90:(.text+0x0): first defined here
/tmp/ifortbW2y7D.o: In function `frontback_mp_frontslu_':
FrontBackSub.f90:(.text+0x10): multiple definition of `frontback_mp_frontslu_'
/tmp/ifortVQdBCN.o:FrontBackSub.f90:(.text+0x10): first defined here
/tmp/ifortbW2y7D.o: In function `frontback_mp_backs_':
FrontBackSub.f90:(.text+0x460): multiple definition of `frontback_mp_backs_'
/tmp/ifortVQdBCN.o:FrontBackSub.f90:(.text+0x460): first defined here
Or, more clear, with gfortran nrtype.f90 FrontBackSub.f90 LUd.f90 FrontBackSub.f90 main.f90:
/tmp/ccpZnjOp.o: In function `__frontback_MOD_backs':
FrontBackSub.f90:(.text+0x0): multiple definition of `__frontback_MOD_backs'
/tmp/ccsr4QjQ.o:FrontBackSub.f90:(.text+0x0): first defined here
/tmp/ccpZnjOp.o: In function `__frontback_MOD_frontslu':
FrontBackSub.f90:(.text+0x582): multiple definition of `__frontback_MOD_frontslu'
/tmp/ccsr4QjQ.o:FrontBackSub.f90:(.text+0x582): first defined here
collect2: error: ld returned 1 exit status
So, it says that the functions (it is plural because when I add new functions the issue expand to them) in FrontBackSub.f90 are defined several times which, clearly, the are not.
Where is the problem that I can't see?
Thanks for your time pals.
Why do you have the source FrontBackSub.f90 two times in the compile command? Just don't do that.

Can a input argument of a Fortran subroutine be deallocated and allocated in the body of the subroutine?

UPDATE: My modified code looks like this:
program run_module_test
use module_test
implicit none
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
call update(xyzArray)
write(6,*)'xyzArray',xyzArray
end program run_module_test
module module_test
implicit none
TYPE :: newXYZ
real(4) :: x, u
real(4) :: y, v
real(4) :: z, w
real(4),dimension(3) :: uvw
END TYPE
integer(4) :: shape = 3
contains
subroutine update(xyzArray)
integer(4) :: i
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
allocate( xyzArray(shape) )
do i = 1, shape
xyzArray(i)%x = 0
xyzArray(i)%y = 0
xyzArray(i)%z = 0
xyzArray(i)%u = 0
xyzArray(i)%v = 0
xyzArray(i)%w = 0
xyzArray(i)%uvw = (/0,0,0/)
end do
return
end subroutine update
end module module_test
When they are compiled, they generate a similar error:
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
1
Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)
When I eliminate the argument in update() subroutine, I receive a contradictory error:
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
1
Error: Symbol at (1) is not a DUMMY variable
Have I eliminated the sources of error pointed out in the helpful suggestions? Could this be a compiler related error (using mpi90)?
~~~First Edit~~~
I have a subroutine whose input argument is an array of user defined type XYZ. I wish to deallocate xyzArray and allocate/modify it to a different size in the body of the subroutine. I attempted the method suggested by changing array dimensions in fortran, but when I do the following:
subroutine update(xyzArray, ...)
...
TYPE (XYZ), allocatable :: xyzArray(:)
I receive an error message:
Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)
When I try:
subroutine update(xyzArray, ...)
...
deallocate( xyzArray(myshape) )
allocate( xyzArray(newshape) )
I receive error messages:
Error: Expression in DEALLOCATE statement at (1) must be ALLOCATABLE or a POINTER
Error: Expression in ALLOCATE statement at (1) must be ALLOCATABLE or a POINTER
What do I need to do to change the size of the array in the subroutine?
To do this:
The dummy argument must be allocatable. Allocatable dummy arguments require a compiler that implements the relevant part of the Fortran 2003 standard (or a Fortran 95 compiler that implements the so called "allocatable" TR).
An explicit interface to the procedure is required (the procedure must be a module procedure, an internal procedure or have an interface block in the calling scope).
The dummy argument must not be intent(in). If you are not using the allocation status or other aspects of the value of the dummy argument at all in the subroutine then intent(out) may be appropriate (if allocated beforehand the dummy argument will be automatically deallocated when the procedure is called), otherwise intent(inout) or no intent.
(Your second block of example code has a syntax error with the deallocate statement - you should simply specify the xyzArray variable, leave off the (myshape) shape specification))
For example, in a module:
subroutine update(xyzArray)
type(xyz), allocatable, intent(inout) :: xyzArray(:)
...
if (allocated(xyzArray)) deallocate(xyzArray)
allocate(xyzArray(newshape))
...
If you are sure, you want to deallocate the array in your subroutine, you can declare the dummy argument being intent(out), so that it is deallocated automatically when the subroutine is entered:
module whatever
implicit none
type :: xyz
:
end type xyz
contains
subroutine update(xyzArray)
type(xyz), allocatable, intent(out) :: xyzArray(:)
:
allocate(xyzArray(someshape))
:
end subroutine update
end module whatever
As already noted by IanH, the process must have an explicit interface (e.g. being enclosed in a module) and in the caller program you must declare the actual argument allocatable:
program test
use whatever
implicit none
type(xyz), allocatable :: array(:)
:
call update(array)
:
end program test

Error when using SUM intrinsic function

using the g95 compiler, I get an error that says:
ERROR: Procedure attribute conflicts with INTENT attribute in 'quantityarray'
I was trying to take find the total sum of the array. Here is the subroutine in which this error appears:
SUBROUTINE findTotals(pricearray,quantityarray,totalprice, totalquantity)
INTEGER, INTENT(IN)::quantityarray
REAL, INTENT(IN):: pricearray
INTEGER, INTENT(OUT)::totalquantity
REAL, INTENT(OUT)::totalprice
totalquantity = SUM(quantityarray)
totalprice = SUM(pricearray)
END SUBROUTINE
Thanks so much for your time.
program SummingAnArray
implicit none
integer, dimension(10) :: array=(/ (i, i=1,10) /)
integer :: i, Total
call VectorSum(array,Total)
print *,Total
read(*,*)
contains
!===================================================
subroutine VectorSum(Vector,Total)
implicit none
integer, intent(in), dimension(:) :: Vector
integer, intent(out) :: Total
Total = SUM(Vector)
end subroutine VectorSum
!===================================================
end program SummingAnArray
Is this perhaps what you wished to achieve?

Resources