So I'm new at programming, and I'm writing a code to my master thesis.
My currents problems with the code are the following:
When I try to compile to do a distribution among the matrix elements, this error message appears: "Syntax error in iterator in (1)". The error is in the Initialization part of the code, as follows:
do j=2:rn2
do i=1:cn
do n=0:8
f(n,i,j)=rho*w(n)
enddo
enddo
enddo
When I promp the question of how many elements in X or Y direction, the user can input only up to 15257 element. I don't know if is a hardware limitation or there is something in my code.
ere is the full code:
program LBM
implicit none
real*8 cn,rn,rn2,omega,gx,gy,rho,w0,w1,w2
real, dimension(0:8) :: w, ex, ey, bb
real, dimension(:,:), allocatable :: f, fn
integer :: i,j,k
!--------------------------------Constants----------------------------
omega=1.d0
gx=0.001d0
gy=0.d0
rho=1.d0
!--------------------------Weights of D2Q9 model----------------------
w0=4.d0/9.d0
w1=1.d0/9.d0
w2=1.d0/36.d0
w(0)=w0
do i=1,4
w(i)=w1
enddo
do i=5,8
w(i)=w2
enddo
!--------------------------------Weight test--------------------------
!write(*,*) w
!w_sum=w(0)+w(1)+w(2)+w(3)+w(4)+w(5)+w(6)+w(7)+w(8)
!write(*,*) w_sum
!-------------------------Velocities of D2Q9 model--------------------
ex=(/ 0, 1, 0, -1, 0, 1, -1, -1, 1 /)
ey=(/ 0, 0, 1, 0, -1, 1, 1, -1, -1 /)
!-------------------------------Velocities test-----------------------
!write(*,*) ex, ey
!--------------------------------Bounce-Back--------------------------
bb=(/ 0, 3, 4, 1, 2, 7, 8, 5, 6 /)
!------------------------------Matrix creation------------------------
do while(cn.lt.3)
write(*,*) 'How many elements in X direction?'
read(*,*) cn
if (cn.lt.3) then
write(*,*) 'Number of elements must be more then 2.'
end if
enddo
do while (rn.lt.3)
write(*,*) 'How many elements in Y direction?'
read(*,*) rn
if (rn.lt.3) then
write(*,*) 'Number of element must be more then 2.'
end if
enddo
allocate(f(cn,rn), fn(cn,rn))
rn2=rn-1
!-----------------------------Inicialization--------------------------
do j=2:rn2
do i=1:cn
do n=0:8
f(n,i,j)=rho*w(n)
enddo
enddo
enddo
!-------------------------------End program---------------------------
deallocate(f,fn)
write(*,*) rn, cn, rn2
pause
end program LBM
Sorry for the long post.
Best regards.
I think you are using Matlab syntax for Fortran.
Try the following:
do j=2,rn2
do i=1,cn
do n=0,8
f(n,i,j)=rho*w(n)
end do
end do
end do
or
do j=2,rn2
do i=1,cn
f(0:8,i,j)=rho*w(0:8)
end do
end do
Related
I kindly request your help on this code where I kept on getting
an error: Rank mismatch in array reference at (1) (2/1). My objective is to go through each point in a cube(p = i+(j-1)*N + (k-1)NN) and calculate the gradient of the potential along each axis (gradphi_x, gradphi_y, gradphi_z).
PROGRAM sub_rho_phi
integer, parameter:: N=3
real, dimension(N):: gradphi_x, gradphi_y, gradphi_z
call output(gradphi_x, gradphi_y, gradphi_z)
open(unit=1,file="grad_phi.dat")
l = 0
do
l=l+1
write(1,*) gradphi_x(l),gradphi_y(l),gradphi_z(l)
if ( l == N**3) then
exit
end if
end do
END
SUBROUTINE output( gradphi_x, gradphi_y, gradphi_z )
real, parameter:: h=0.7,G=6.67,M=1.98892*(10**3)!!in(10**15) kg
integer, parameter:: N=3
real, dimension(N):: r, gradphi_x,gradphi_y,gradphi_z
integer, dimension(N**3):: x,y,z
integer:: p
real:: a
a=500/h !in kpc
do i=0, N
do j=0, N
do k=0, N
p = i+(j-1)*N + (k-1)*N*N
x(p,1)=i
y(p,2)=j
z(p,3)=k
r(p)=sqrt(x(p,1)*x(p,1)+y(p,2)*y(p,2)+z(p,3)*z(p,3))
gradphi_x(p)=(G*M)*x(p,1)/r(p)*(r(p)+a)**2
gradphi_y(p)=(G*M)*y(p,2)/r(p)*(r(p)+a)**2
gradphi_z(p)=(G*M)*z(p,3)/r(p)*(r(p)+a)**2
enddo
enddo
enddo
return
END
You have declared x, y and z as one dimensional arrays, but are using two dimensional indexing all the way through output.
First, I calculated the lower triangle and the main diagonal values with the formula: f(i,j)=(f(i,j-1))-(f(i-1,j-1))/(x(i)- x(i-j), I made the matrix(6,6) so i can have the main diagonal from it, which values are defined with b in the code and shown as "Cosntante" in the promt.
Then i did the interpolation defined as p in the code and shown as " El valor aproximado de f() es:" in the promt.
program p4
use ISO_C_Binding
implicit none
real :: x(6), y(6), b(6), xi, p
integer :: i, j, n, m, k
real, dimension(6,6) :: f=c_float
f=0
x=[1.6, 2.0, 2.5, 3.2, 4.0, 4.5]
y=[2, 8, 14, 15, 8, 2]
n=SIZE(x)
do i=1,n
f(i,1)=y(i)
end do
do i=1,n
f(i,2:n)=0
end do
do j=2,n
do i=j,n
f(i,j)=(f(i,j-1))-(f(i-1,j-1))/(x(i)- x(i-j))
end do
end do
do i=1,n
write(*,*) F(i,:)
end do
do i=1,n
b(i)=f(i,i)
write(*,*) "Constante b[",i,"]=",b(i)
end do
xi=2.8
m=size(x)-1
p=b(m)
do k=2,m+1
p=(b(m-k))+(xi-((x(m-k))*p))
end do
write(*,*) "El valor aproximado de f(",xi,") es:",p
pause
end program p4
it shows me the next values (these are the values i get in ForceFortran):
And it should show me (these are the values i get in Python):
What should i do?
my program display no error but it can't work?
program hw4
dimension a(i,j)
real a
common i,j
integer i,j
do i=1,4,1
do j=1,5,1
a(1,1)=0
a(1,2)=1
a(1,3)=2
a(1,4)=3
a(1,5)=25
a(2,1)=1
a(2,2)=1
a(2,3)=1
a(2,4)=1
a(2,5)=12
a(3,1)=2
a(3,2)=0
a(3,3)=3
a(3,4)=1
a(3,5)=19
a(4,1)=3
a(4,2)=4
a(4,3)=0
a(4,4)=6
a(4,5)=41
write(*,*) a(i,j)
enddo
enddo
stop
end
I expect it will show 4*5 matrix,but now it will show me the program stop work message
Firstly, your matrix "a" must have constant shape i.e. dimensions "i" and "j" must be explicitly defined.
Secondly, your nested loop sets matrix values every loop. Try putting it before the loop.
Something like:
program hw4
implicit none
integer, parameter :: ni=4, nj=5
real, dimension(ni,nj) :: a
integer :: i, j
! Set matrix values here
a(1,1) = 0
! ...
do i = 1, ni, 1
do j = 1, nj, 1
write(*,*) a(i,j)
end do
end do
end program hw4
Kind regards
I have problem with combining several 2D arrays into one big 2D array using MPI in Fortran.
I have equal size 2D arrays containing real numbers, every array is contained in different process:
numerical(subdsize,nt)
I want to combine them to one big array
numerical_final(nx,nt)
I am using the following command
CALL MPI_Gather(numerical(1:subdsize,nt),subdsize*nt,MPI_DOUBLE_PRECISION,numerical_final,subdsize*nt,MPI_DOUBLE_PRECISION,0, MPI_COMM_WORLD, mpierror)
Unfortunately the data that numerical_final array contains are a complete mess. I was looking for solutions really everywhere. I read this topic but it did not help me:
sending blocks of 2D array in C using MPI
I am using Intel Fortran 2018 compiler and Ubuntu 16.04.
Full code below.
I will be grateful for the help.
PROGRAM Advection
IMPLICIT NONE
INCLUDE 'mpif.h'
INTEGER :: nt,nx,i,steptime,tag,j
DOUBLE PRECISION :: R_dx, R_dt, R_c, R_cfl, R_t
DOUBLE PRECISION, DIMENSION(3) :: R_input
DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:) :: xcoord
DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:,:) :: numerical, numerical_final
DOUBLE PRECISION :: time_begin,time_end,time_elapsed
INTEGER:: myrank,nproc,mpierror,xdomains,subdsize
INTEGER:: status(MPI_STATUS_SIZE)
CALL MPI_Init(mpierror)
CALL MPI_Comm_size(MPI_COMM_WORLD,nproc,mpierror)
CALL MPI_Comm_rank(MPI_COMM_WORLD,myrank,mpierror)
IF (nproc<2) THEN
PRINT*, "Error, only more than 1"
CALL MPI_ABORT
END IF
IF (myrank .EQ. 0) THEN
OPEN(UNIT = 1, FILE = 'inputdata.dat')
READ(1,*) R_input(1)
READ(1,*) R_input(2)
READ(1,*) R_input(3)
READ(1,*) nx
CLOSE(1)
END IF
CALL MPI_Bcast(R_input, 3, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, mpierror)
CALL MPI_Bcast(nx, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, mpierror)
R_c=R_input(1)
R_cfl=R_input(2)
R_t=R_input(3)
R_dx=80./(nx-1)
nt=15
R_dt=R_t/(nt-1)
IF (myrank .EQ. 0) THEN
PRINT*, R_c*R_dt/R_dx
END IF
xdomains = nproc
IF ((MOD(nx,xdomains))==0) THEN
subdsize =nx/xdomains
ELSE
DO
nx=nx+1
IF ((MOD(nx,xdomains)) .EQ. 0) THEN
subdsize=nx/xdomains
EXIT
END IF
END DO
END IF
RAYS
ALLOCATE(xcoord(0:subdsize+1))
ALLOCATE(numerical(0:subdsize+1,nt))
DO i=0,subdsize+1
xcoord(i) = -40.-R_dx+i*R_dx+myrank*R_dx*subdsize
END DO
DO i = 0,subdsize+1
numerical(i,1)=0.5*(sign(1.,xcoord(i))+1.0)
END DO
IF (myrank .EQ. 0) THEN
DO i=1,nt
numerical(0:1,i)=0.
END DO
END IF
IF (myrank .EQ. nproc-1) THEN
DO i=1,nt
numerical(subdsize:subdsize+1,i)=1.
END DO
END IF
DO steptime=1, nt-1
tag = 1
IF (myrank .LT. nproc-1) THEN
CALL MPI_Send (numerical(subdsize,steptime),1,MPI_DOUBLE_PRECISION,myrank+1,tag,MPI_COMM_WORLD,mpierror)
END IF
IF (myrank .GT. 0) THEN
CALL MPI_Recv (numerical(0,steptime),1,MPI_DOUBLE_PRECISION,myrank-1,tag,MPI_COMM_WORLD,status,mpierror )
END IF
IF (myrank .EQ. 0) THEN
DO i = 2, subdsize+1
numerical(i,steptime+1)=numerical(i,steptime)-R_c*R_dt/R_dx*(numerical(i,steptime)-numerical(i-1,steptime))
END DO
ELSE
DO i = 1, subdsize+1
numerical(i,steptime+1)=numerical(i,steptime)-R_c*R_dt/R_dx*(numerical(i,steptime)-numerical(i-1,steptime))
END DO
END IF
END DO
ALLOCATE(numerical_final(nx,nt))
CALL MPI_Gather(numerical(1:subdsize,nt),subdsize*nt,MPI_DOUBLE_PRECISION,numerical_final,subdsize*nt,MPI_DOUBLE_PRECISION,0, MPI_COMM_WORLD, mpierror)
CALL MPI_Finalize(mpierror)
DEALLOCATE (numerical,numerical_final)
END PROGRAM
And inputfile
1.5 !c
0.5 !Courant
5.0 !time
100 !x points
I need to find a faster way to transpose a matrix using MKL. And I tried mkl_domatcopy from MKL but never get it right.
Here is the test code(Fortran):
PROGRAM MAIN
INTEGER, PARAMETER:: NROW = 3 !rows
INTEGER, PARAMETER:: NCOL = 3 !cols
REAL*8, ALLOCATABLE:: M(:,:)
REAL*8, ALLOCATABLE:: MT(:,:)
INTEGER:: i,j
ALLOCATE(M(NROW,NCOL))
ALLOCATE(MT(NROW,NCOL))
DO i = 1, NROW
DO j = 1, NCOL
M(i,j)=i
END DO
END DO
call mkl_domatcopy("c","t",3,3,9,M,3,MT,3)
print *,M
print *,"************************"
print *,MT
END
And the output is:
1.00000000000000 2.00000000000000 3.00000000000000
1.00000000000000 2.00000000000000 3.00000000000000
1.00000000000000 2.00000000000000 3.00000000000000
************************
0
why the MT is 0?Is it beacause I use it wrong or something?
Documents about this function:
https://software.intel.com/en-us/node/520863
PS:I still don't get what 'alpha' means.
As user roygvib suggests in the comments, by including the mkl.fi file would give you additional details.
This code
PROGRAM MAIN
INCLUDE 'mkl.fi'
INTEGER, PARAMETER:: NROW = 3 !rows
INTEGER, PARAMETER:: NCOL = 3 !cols
REAL*8, ALLOCATABLE:: M(:,:)
REAL*8, ALLOCATABLE:: MT(:,:)
INTEGER:: i,j
ALLOCATE(M(NROW,NCOL))
ALLOCATE(MT(NROW,NCOL))
DO i = 1, NROW
DO j = 1, NCOL
M(i,j)=i
END DO
END DO
call mkl_domatcopy("c","t",3,3,9,M,3,MT,3)
print *,M
print *,"************************"
print *,MT
END
raises the following error
test.f90(23): error #6633: The type of the actual argument differs
from the type of the dummy argument. [9]
call mkl_domatcopy("c","t",3,3,9,M,3,MT,3)
-----------------------------------------------^ compilation aborted for test.f90 (code 1)
Interestingly, if you turn that 9 into a double precision value (or variable) -- note that here I simply appended the d0 suffix to the floating point value.
PROGRAM MAIN
INCLUDE 'mkl.fi'
INTEGER, PARAMETER:: NROW = 3 !rows
INTEGER, PARAMETER:: NCOL = 3 !cols
REAL*8, ALLOCATABLE:: M(:,:)
REAL*8, ALLOCATABLE:: MT(:,:)
INTEGER:: i,j
ALLOCATE(M(NROW,NCOL))
ALLOCATE(MT(NROW,NCOL))
DO i = 1, NROW
DO j = 1, NCOL
M(i,j)=i
END DO
END DO
call mkl_domatcopy("c","t",3,3,9d0,M,3,MT,3)
print *,M
print *,"************************"
print *,MT
END
then your application returns
$ ./test
1.00000000000000 2.00000000000000 3.00000000000000
1.00000000000000 2.00000000000000 3.00000000000000
1.00000000000000 2.00000000000000 3.00000000000000
************************
9.00000000000000 9.00000000000000 9.00000000000000
18.0000000000000 18.0000000000000 18.0000000000000
27.0000000000000 27.0000000000000 27.0000000000000
Finally, with respect to what alpha means, the manual says
alpha This parameter scales the input matrix by alpha.
and notice that the output is the tranposed and each element multiplied by 9.
The fastest way to do a transpose in fortran90 is as follows
B = TRANSPOSE(A)
And the fastest way to do a MATMUL is:
C = MATMUL(A,B)
As it is inherent in the language, I am not sure where MKL/IMKL comes into play?