Fortran90-How to allocate an array dimension

In summary, the conversation is about a student in physics who is working on a code in Fortran 90 to calculate the half-life time of Polonium. The code is 300 lines long with 5 subroutines, and one of them is causing segmentation faults. The student is trying to define an allocatable array to generate random numbers and satisfy certain conditions, but they are having trouble allocating the array and selecting acceptable points. They have tried multiple methods, but are still encountering errors.
  • #1
Aner
9
0
Hi,
I have a problem with a code I'm working with. I'm a student in physics and I'm writing a code in Fortran 90 that should calculate the Polonium's half-life time.
I have no data to work with so I generated them with the library random number and here is the problem, I have a 300 lines code with something like 5 subroutine but one of them is the one that is generating the data with which I'll work with and it is the one creating several segmentation faults.
What I'd like to do, and I hope someone of you could help me, is to define an allocatable array, in which generate n times random numbers of which just r will satisfied some given conditions. So the fact is that I'm trying to allocate the array dimension after having create some of his component.
Being more specific I'll write just the piece of code that generate those number because it is the same as the subroutine and is much shorter than the whole code.

Fortran:
program polly

implicit none

REAL::dx,l,p,q,z,m
INTEGER::i,n,r
REAL,DIMENSION(:),allocatable::x,y

n=100

dx=0.05

l=3.0 

p=10.0
q=10.0

r=0

!allocate (x(n),y(n))do i=1,n

call random_number(x)

call random_number(y)

m=y(i)*q
z=x(i)*p
if ((exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then 
         
                                                write(unit=1,fmt=*), x,y
r=r+1  else

x=0
y=0

END IF

print*,"r",r,"x",x,"y",yend program polly
So here the value of r after the do cycle should be the times which the condition is satisfied so it is the dimension I wish x and y had.
I tried multiple times and multiple ways, even setting the dimension as n and giving the value 0 to all the n-r "holes" in the array. Then in the whole program I have those other subroutine that are based on the same x and y that are intent in, which are the two arrays that I calculate in the subroutine above. Moreover these subroutines calculate several mean value that need to be divided by the real number of component and not the whole n. Furthermore, I don't know where the accepted point will be in the array so that it is not sufficient to just allocate the vectors but I need also a procedures to select only the acceptable points ignoring all the others.
I don't know if I made it clear to you or not, I tried. I hope you can help.
Thanks anyway.
 
Technology news on Phys.org
  • #2
Aner said:
Hi,
I have a problem with a code I'm working with. I'm a student in physics and I'm writing a code in Fortran 90 that should calculate the Polonium's half-life time.
I have no data to work with so I generated them with the library random number and here is the problem, I have a 300 lines code with something like 5 subroutine but one of them is the one that is generating the data with which I'll work with and it is the one creating several segmentation faults.
What I'd like to do, and I hope someone of you could help me, is to define an allocatable array, in which generate n times random numbers of which just r will satisfied some given conditions. So the fact is that I'm trying to allocate the array dimension after having create some of his component.
Being more specific I'll write just the piece of code that generate those number because it is the same as the subroutine and is much shorter than the whole code.

Fortran:
program polly

implicit none

REAL::dx,l,p,q,z,m
INTEGER::i,n,r
REAL,DIMENSION(:),allocatable::x,y

n=100

dx=0.05

l=3.0

p=10.0
q=10.0

r=0

!allocate (x(n),y(n))do i=1,n

call random_number(x)

call random_number(y)

m=y(i)*q
z=x(i)*p

if ((exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then

write(unit=1,fmt=*), x,y

r=r+1

else

x=0
y=0

END IF

print*,"r",r,"x",x,"y",yend program polly
So here the value of r after the do cycle should be the times which the condition is satisfied so it is the dimension I wish x and y had.
I tried multiple times and multiple ways, even setting the dimension as n and giving the value 0 to all the n-r "holes" in the array. Then in the whole program I have those other subroutine that are based on the same x and y that are intent in, which are the two arrays that I calculate in the subroutine above. Moreover these subroutines calculate several mean value that need to be divided by the real number of component and not the whole n. Furthermore, I don't know where the accepted point will be in the array so that it is not sufficient to just allocate the vectors but I need also a procedures to select only the acceptable points ignoring all the others.
I don't know if I made it clear to you or not, I tried. I hope you can help.
Thanks anyway.

You can't do this:
Code:
!allocate (x(n),y(n))

You need a separate allcocate statement for each array, as in this example.
Code:
allocate (x(n))
allocate (y(n))

Also, your calls to random_number() don't look right. I think they should be like so, I believe (based on the fact that you have them inside a do loop):
Code:
do i=1,n
   call random_number(x(i))
   call random_number(y(i))

   m=y(i)*q
   z=x(i)*p

   if ((exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then

   write(unit=1,fmt=*), x(i), y(i)
In addition, you are missing the end do for your do loop. There might be other errors...
 
  • Like
Likes Aner
  • #3
Mark44 said:
You can't do this:
Code:
!allocate (x(n),y(n))

You need a separate allcocate statement for each array, as in this example.
Code:
allocate (x(n))
allocate (y(n))

Also, your calls to random_number() don't look right. I think they should be like so, I believe (based on the fact that you have them inside a do loop):
Code:
do i=1,n
   call random_number(x(i))
   call random_number(y(i))

   m=y(i)*q
   z=x(i)*p

   if ((exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then

   write(unit=1,fmt=*), x(i), y(i)
In addition, you are missing the end do for your do loop. There might be other errors...

Thanks a lot, the end do is missing in the code I pasted because I deleted some comments that were written in Italian and were not useful for the problem. Anyway I modified the other things you said and it ends up calculating the array but the problem is that in order to have some interesting point I need to run the do cycle at least 1000 times and it gives me r=4 and it wrote me the 4 components for x and y (with the command print* in the do cycles), but at the end of the programs, the other print command should write the whole vectors and it just give me two vectors, x and y with n zero inside.
if I find something I'll write again.
Thanks for your help.
 
  • #4
Aner said:
but at the end of the programs, the other print command should write the whole vectors and it just give me two vectors, x and y with n zero inside.
I'm not sure what you're saying here. Possibly what you're seeing is due to this code:
Code:
else
x=0
y=0
END IF

Since that code is in your do loop, it should probably look like this:
Code:
else
   x(i) = 0
   y(i) = 0
end if
I believe that your intent is to set just specific elements of your arrays to zero, not all of the elements.
 
  • Like
Likes Aner
  • #5
Mark44 said:
I'm not sure what you're saying here. Possibly what you're seeing is due to this code:
Code:
else
x=0
y=0
END IF

Since that code is in your do loop, it should probably look like this:
Code:
else
   x(i) = 0
   y(i) = 0
end if
I believe that your intent is to set just specific elements of your arrays to zero, not all of the elements.

Thank you so much, those were pretty dummy errors but you helped me find the way to make it works!I've even found out how to solve the initial problem of the array, I've left the dimension n and create an if cycle in order to avoid the 0 components.
Thank you very much!
 
  • #6
Actually, it is possible to allocate more than one array in a single call...for as long as the statement is not commented out ;-)

Also, it is possible populate an entire array with a single call to random_number...this function is smart enough to do that...this means that you would need to make those calls BEFORE entering the do loop.

In all, you need to approach this a bit differently so that at the end you do get as many random numbers as desired... basically, you allocate you arrays to the desire length..then, instead of a do loop with finite range, you use a while loop to get a couple of random numbers (no directly array entries but two other auxiliary variables), you test those number if they meet the condition you assign them to the arrays and increase your counter, if the counter reaches a given value, you exit the while loop; otherwise, you repeat the loop.
 
  • Like
Likes Aner
  • #7
gsal said:
Actually, it is possible to allocate more than one array in a single call...for as long as the statement is not commented out ;-)

Also, it is possible populate an entire array with a single call to random_number...this function is smart enough to do that...this means that you would need to make those calls BEFORE entering the do loop.

In all, you need to approach this a bit differently so that at the end you do get as many random numbers as desired... basically, you allocate you arrays to the desire length..then, instead of a do loop with finite range, you use a while loop to get a couple of random numbers (no directly array entries but two other auxiliary variables), you test those number if they meet the condition you assign them to the arrays and increase your counter, if the counter reaches a given value, you exit the while loop; otherwise, you repeat the loop.

Thank you so much, that's a really interesting thing to know, I forgot about the while loop, but surely it would have helped a lot (maybe my now 400 plus lines codes would be shorter). I'll surely try that!
 
  • #8
Fortran:
program polly
    implicit none
    integer::n,r
    real::dx,l,p,q,z,m,a,b
    real,dimension(:),allocatable::x,y   
    dx = 0.05 ; l = 3.0 ; p = 10.0 ; q = 10.0
    n = 100
    allocate (x(n),y(n))
  
    r = 0
    do
        call random_number(a) ; z = a*p
        call random_number(b) ; m = b*q     
        if ( (exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then
            r = r + 1
            x(r) = a
            y(r) = b
            if (r == n) exit
        end if
    end do
    write(*,'(i3, 2x, f5.2, 2x, f5.2)') (r, x(r), y(r), r = 1, n)
end program polly
 
  • Like
Likes Aner
  • #9
gsal said:
Fortran:
program polly
    implicit none
    integer::n,r
    real::dx,l,p,q,z,m,a,b
    real,dimension(:),allocatable::x,y  
    dx = 0.05 ; l = 3.0 ; p = 10.0 ; q = 10.0
    n = 100
    allocate (x(n),y(n))
 
    r = 0
    do
        call random_number(a) ; z = a*p
        call random_number(b) ; m = b*q    
        if ( (exp(-l*(z+dx))) <= log(m) .AND. log(m) <= (exp(-l*(z-dx)))) then
            r = r + 1
            x(r) = a
            y(r) = b
            if (r == n) exit
        end if
    end do
    write(*,'(i3, 2x, f5.2, 2x, f5.2)') (r, x(r), y(r), r = 1, n)
end program polly

It's fantastic! Thank you so much! It made my program better and even the result are more precise!I ended up deleting something like 100 lines with your help! Now my program is working perfectly and without all the if cycles that were necessary before! A really big thanks to you!
 

FAQ: Fortran90-How to allocate an array dimension

What is the syntax for allocating an array dimension in Fortran90?

The syntax for allocating an array dimension in Fortran90 is allocate(array_name(dimensions)). This allocates memory for the array with the specified dimensions.

Can I allocate multiple dimensions for an array in Fortran90?

Yes, you can allocate multiple dimensions for an array in Fortran90 by specifying the dimensions in the allocate statement. For example, allocate(array_name(dim1, dim2, dim3)).

Do I need to explicitly deallocate an array after using it in Fortran90?

Yes, it is good practice to explicitly deallocate an array after using it in Fortran90. This ensures that the memory is freed up for other parts of the program to use.

Can I use variables to specify the dimensions of an array in Fortran90?

Yes, you can use variables to specify the dimensions of an array in Fortran90. These variables must be of type integer and must have a value before using them in the allocate statement.

What happens if I try to allocate more memory than is available for an array in Fortran90?

If you try to allocate more memory than is available for an array in Fortran90, an error will occur and the program will terminate. It is important to carefully allocate memory for arrays to avoid this issue.

Similar threads

Replies
4
Views
2K
Replies
4
Views
2K
Replies
20
Views
3K
Replies
21
Views
2K
Replies
5
Views
7K
Replies
4
Views
4K
Replies
22
Views
3K
Back
Top