I want to do a fixed calculation step for multiple .dat files.
Here is my code for what I want to do with one .dat file i.e. the calculation:
dimension t(128716),x(128716)
open (unit=88,file='ALFA-gua-100m-2.dat',status='unknown')
do i=1,128716
read(88,*)t(i),x(i)
enddo
sum=0
do j=1,128716
sum=sum+x(j)
enddo
write(*,*)sum/128716
close(88)
stop
end
How do I go about this? Please suggest!
Here is my code for multiple file :
dimension t(128716),x(128716)
open (unit=11,file='ALFA-gua-100m-2.dat',status='unknown')
open (unit=12,file='ALFA-gua-100m-5.dat',status='unknown')
do i=1,2
ii = i + 10
do j=1,128716
read(ii,*)t(j),x(j)
enddo
sum=0
do k=1,128716
sum=sum+x(k)
enddo
enddo
do l=1,2
ll = l + 10
write(ll,*)sum/128716.0
close(ll)
enddo
stop
end
But its not working.
An addendum to #VladimirF's answer.
To sum all the elements in an array called x we can simply write
sumx = sum(x)
there is no need for the programmer to write a loop at all. If using an array of sums, then something like
sums(1) = sum(x)
would be appropriate.
Then to calculate the mean of an array I'd write
meanx = sum(x)/size(x)
While I'm writing: it's not a good idea to call a variable sum. There's an existing intrinsic function of that name and it will only confuse readers (though not the compiler) to have a variable of that name too.
You cannot use the same sum for two iterations of the i loop when you have two separate loops. It will get overwritten when processing the second file.
You can join the loops into one.
do i=1,2
ii = i + 10
do j=1,128716
read(ii,*)t(j),x(j)
enddo
sum=0
do k=1,128716
sum=sum+x(k)
enddo
write(ii,*)sum/128716.0
close(ii)
enddo
You can use an array for the sums sums(i).
do i=1,2
ii = i + 10
do j=1,128716
read(ii,*)t(j),x(j)
enddo
sum=0
do k=1,128716
sums(i)=sums(i)+x(k)
enddo
enddo
do l=1,2
ll = l + 10
write(ll,*)sums(l)/128716.0
close(ll)
enddo
Related
The task is to write the code for calculating integral of the polynomial function. the function id displayed in the image I attached. I wrote the code and it compiled and the answer came out. However, it is completely different with the analytical solution. The code:
program rectangularApproximation
write(*,*) "Input values of a ,b and eps"
read(*,*) a,b,eps
1 continue
n=1000
h=(b-a)/n
s=0.0
do i=1,n
x=a+h*i
s=s+f(x)*h
enddo
sprev=s
n=10*n
h=(b-a)/n
s=0.0
do i=1,n
x=a+h*i
s=s+f(x)*h
enddo
snext=s
if (abs(sprev-snext)<eps) then
write(*,*) snext,n
stop
end if
goto 1
write(*,*) s
end
real function f(x)
implicit none
real, intent(in) :: x
integer :: i
real, dimension(8) :: numbers
numbers = (/1,3,1,4,2,3,0,1 /)
do i = 1,8
f = f + numbers(i) * x**(numbers(i))
end do
end function
The result obtained by running the code is 588189248 (the interval (a,b) is (1,2) and i chose epsillon=0.001) Analytical solution is following :
The answer of analytical solution is 169.256 . What could have gone wrong in my code?
Your polynomial code is wrong:
do i = 1,8
f = f + numbers(i) * x**(numbers(i))
end do
That should be
do i = 1,8
f = f + numbers(i) * x**i
end do
I am trying to parallelize the following nested DO loop structure (the first code below) using 'Collapse' directive in OpenACC. The variable 'nbl' present in the outermost loop is present in the other DO loops, so there is dependency. Thanks to the compiler its showing an error in advance. So I had to compromise and construct 'collapse' directive only to the remaining four inner most loops. Is there a way to parallelize this loop to get maximum performance by utilizing the parallelism of "nbl = 1,nblocks" as well?
Compiler: pgfortran
Flags: -acc -fast -ta=tesla:managed -Minfo=accel
Code that's giving error due to data dependency between outer most DO loop and other inner DO loops:
!$acc parallel loop collapse(5)
DO nbl = 1,nblocks
DO n_prim = 1,nprims
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)
Px(i,j,k,nbl,n_prim) = i*j + Cx(i,j,k,nbl,1)*Cx(i,j,k,nbl,5) + Cx(i,j,k,nbl,2)
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$acc end parallel loop
Compromised working code with lesser parllelism:
DO nbl = 1,nblocks
!$acc parallel loop collapse(4)
DO n_prim = 1,nprims
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)
Px(i,j,k,nbl,n_prim) = i*j + Cx(i,j,k,nbl,1)*Cx(i,j,k,nbl,5) + Cx(i,j,k,nbl,2)
ENDDO
ENDDO
ENDDO
ENDDO
!$acc end parallel loop
ENDDO
Thanks!
The dependency is with the array look-ups for the upper bounds of the loops. In order to collapse loops, the iteration count of the loop must be known before entering, but here the count is variable.
Try something like the following and split the parallelism into two levels:
!$acc parallel loop collapse(2)
DO nbl = 1,nblocks
DO n_prim = 1,nprims
!$acc loop collapse(3)
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)
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 am currently working on adding openmp parallelization for a do loop in one of the codes I have written for research. I am fairly new to using openmp so I would appreciate if you had any suggestions for what might be going wrong.
Basically, I have added a parallel do loop to the following code (which works prior to parallelization). r(:,:,:,:) is a vector of a ton of molecular coordinates indexed by time, molecule, atom, and (xyz). This vector is about 100 gb of data (I am working on an HPC with plenty of RAM). I am trying to parallelize the outer loop and subdivide it between processors so that I can reduce the amount of time this calculation goes. I thought it would be a good one to do it with as msd and cm_msd are the only things that would need to be edited by multiple processors and stored for later, which since each iteration gets its own element of these arrays they won't have a race condition.
The problem: If I run this code 5 times I get varying results, sometimes msd is calculated correctly (or appears to be), and sometimes it outputs all zeros later when I average it together. Without parallelization there are no issues.
I have been trying altering the shared vs private variables in the code and I think I have accounted for everything. The i index of the msd array and msd_cm array should never be equivalent between threads so I would think that they wouldn't be an issue.
! Loop over time origins
counti = 0
ind = 0
!$OMP PARALLEL DO schedule(static) PRIVATE(i,j,k,it,r_old,r_cm_old,shift,shift_cm,dsq,ind) &
!$OMP& SHARED(msd,msd_cm)
do i=1, nconfigs-nt, or_int
if(MOD(counti*or_int,500) == 0) then
write(*,*) 'Reached the ', counti*or_int,'th time origin'
end if
! Set the Old Coordinates
counti = counti + 1
ind = (i-1)/or_int + 1
r_old(:,:,:) = r(i,:,:,:)
r_cm_old(:,:) = r_cm(i,:,:)
shift = 0.0
shift_cm = 0.0
! Loop over the timesteps in each trajectory
do it=i+2, nt+i
! Loop over molecules
do j = 1, nmols
do k=1, atms_per_mol
! Calculate the shift if it occurs.
shift(j,k,:) = shift(j,k,:) - L(:)*anint((r(it,j,k,:) - &
r_old(j,k,:) )/L(:))
! Calculate the square displacements
dsq = ( r(it,j,k,1) + shift(j,k,1) - r(i,j,k,1) ) ** 2. &
+( r(it,j,k,2) + shift(j,k,2) - r(i,j,k,2) ) ** 2. &
+( r(it,j,k,3) + shift(j,k,3) - r(i,j,k,3) ) ** 2.
msd(ind, it-1-i, k) = msd(ind, it-1-i, k) + dsq
! Calculate the contribution to the c1,c2
enddo ! End Atoms Loop (k)
! Calculate the shift if it occurs.
shift_cm(j,:) = shift_cm(j,:) - L(:)*anint((r_cm(it,j,:) - &
r_cm_old(j,:) )/L(:))
! Calculate the square displacements
dsq = ( r_cm(it,j,1) + shift_cm(j,1) - r_cm(i,j,1) ) ** 2. &
+( r_cm(it,j,2) + shift_cm(j,2) - r_cm(i,j,2) ) ** 2. &
+( r_cm(it,j,3) + shift_cm(j,3) - r_cm(i,j,3) ) ** 2.
msd_cm(ind,it-1-i) = msd_cm(ind, it-1-i) + dsq
enddo ! End Molecules Loop (j)
r_old(:,:,:) = r(it,:,:,:)
r_cm_old(:,:) = r_cm(it,:,:)
enddo ! End t's loop (it)
enddo
!$OMP END PARALLEL DO
When this code is run, when I later print the averaged msd results out they either come out as correctly or they come out as zero and it is always one or the other. Do you see an issue that might explain why it is only working part of the time. I am brand new to openmp so it is completely possible there is just something incredibly stupid with how I am trying to do this.
Thanks in advance!
My Fortran code is as follows:
! ...................... initialization
do ia=1,NLEV
do ic=1,NLEV
ZGamma(ia,ic) =zero
enddo
enddo
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(H,ZRO) REDUCTION(+: ZGamma)
!$OMP DO SCHEDULE(DYNAMIC)
do iabcd=1,H%iabcd_max
ia = H%ka(iabcd)
ib = H%kb(iabcd)
ic = H%kc(iabcd)
id = H%kd(iabcd)
ZGamma(ia,ic)=ZGamma(ia,ic) + H%ME2BM(iabcd)*ZRO(id,ib)
ZGamma(ib,ic)=ZGamma(ib,ic) - H%ME2BM(iabcd)*ZRO(id,ia)
ZGamma(ia,id)=ZGamma(ia,id) - H%ME2BM(iabcd)*ZRO(ic,ib)
ZGamma(ib,id)=ZGamma(ib,id) + H%ME2BM(iabcd)*ZRO(ic,ia)
if(ia+ib.eq.ic+id) cycle
ZGamma(ic,ia)=ZGamma(ic,ia) + H%ME2BM(iabcd)*ZRO(ib,id)
ZGamma(id,ia)=ZGamma(id,ia) - H%ME2BM(iabcd)*ZRO(ib,ic)
ZGamma(ic,ib)=ZGamma(ic,ib) - H%ME2BM(iabcd)*ZRO(ia,id)
ZGamma(id,ib)=ZGamma(id,ib) + H%ME2BM(iabcd)*ZRO(ia,ic)
enddo ! iabcd
!$OMP END DO
!$OMP END PARALLEL
In the above code, I calculated the 2D array ZGamma(i,j) using OpenMP. Even though I can compile the code without any problem. Could anyone tell me what the problem is in the code? What changes should I make?
By the way, as the index "iabcd" running from "1" to "H%iabcd_max", the values of "(ia,ib,ic,id)" can be "(1,1,1,1),(1,1,1,2),(1,1,1,...), (1,1,2,1),(1,1,2,..)," etc.