Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Fortran90-How to allocate an array dimension

  1. Jul 14, 2015 #1
    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.

    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",y


    end 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.
     
  2. jcsd
  3. Jul 14, 2015 #2

    Mark44

    Staff: Mentor

    You can't do this:
    Code (Text):
    !allocate (x(n),y(n))
    You need a separate allcocate statement for each array, as in this example.
    Code (Text):
    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 (Text):

    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...
     
  4. Jul 14, 2015 #3
    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.
     
  5. Jul 14, 2015 #4

    Mark44

    Staff: Mentor

    I'm not sure what you're saying here. Possibly what you're seeing is due to this code:
    Code (Text):
    else
    x=0
    y=0
    END IF
    Since that code is in your do loop, it should probably look like this:
    Code (Text):
    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.
     
  6. Jul 14, 2015 #5
    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!
     
  7. Jul 14, 2015 #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.
     
  8. Jul 15, 2015 #7
    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!
     
  9. Jul 15, 2015 #8
    Code (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
     
     
  10. Jul 17, 2015 #9

    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!
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Fortran90-How to allocate an array dimension
Loading...