1

First of all I am a complete novice to FORTRAN, and most forms of programming in general. With that said I am attempting to build a box, then randomly generate x, y, z coordinates for 100 atoms. From there, the goal is to calculate the distance between each atom and perform some math on the distance result. Below is my code. Even though n is defined as 100, and will print '100', when I print cx I only get 20 results.

    program energytot
    implicit none

    integer :: i, n, j, seed(12), k, m
    double precision:: sigma, r, epsilon, lx, ly, lz
    double precision, dimension(:), allocatable :: cx, cy, cz, dx, dy, dz, x, y, z, LJx, LJy, LJz
    allocate(x(n), y(n), z(n), LJx(n), LJy(n), LJz(n), dx(n), dy(n), dz(n))
    n = 100 !Number of molecules inside the box
    sigma = 4.1
    epsilon = 1.7
    !Box length with respect to the axis
    lx = 15
    ly = 15
    lz = 15

    do i=1,12
        seed(i)=1+3
    end do
    !generate n random numbers for x, y, z
    call RANDOM_SEED(PUT = seed)
    call random_number(x)
    call random_number(y)
    call random_number(z)
    !convert random numbers into x, y, z coordinates with (0,0,0) as the central point
    cx = ((2*x)-1)*(lx*0.5)
    cy = ((2*y)-1)*(lx*0.5)
    cz = ((2*z)-1)*(lz*0.5)

    do j=1,n-1
        do k=j+1,n
            dx = ABS((cx(j) - cx(j+1)))
            LJx = 4 * epsilon * ((sigma/dx(j))**12 - (sigma/dx(j))**6)
            dy = ABS((cy(j) - cy(j+1)))
            LJy = 4 * epsilon * ((sigma/dy(j))**12 - (sigma/dy(j))**6)
            dz = ABS((cz(j) - cz(j+1)))
            LJz = 4 * epsilon * ((sigma/dz(j))**12 - (sigma/dz(j))**6)
        end do
    end do
    print*,cx
    print*,x
    end program energytot
francescalus
  • 30,576
  • 16
  • 61
  • 96
  • I've rolled back your edit, which essentially removed the question. If John Bollinger's answer was helpful, then please consider accepting and/or upvoting it instead. This way, we retain the question's use for later readers who may have similar problems. – francescalus Apr 13 '15 at 22:32
  • @francescalus: I had thought about that as I was doing it, but I thought that John Bollinger's answer, which contained the erroneous portion of my code was enough. I apologize, please excuse my newbieousity. – Charles Butler Apr 13 '15 at 22:38
  • There's no harm done, but a good rule for a question edit is: "do the answers still make sense?". Also, if you are still uncertain about getting the size of the array you really need, then it may be more appropriate to ask a new question (perhaps linking to this one). – francescalus Apr 13 '15 at 22:44

1 Answers1

1

You declare cx (and cy and cz) allocatable, but you do not allocate space for them. Moreover, before you assign a value to variable n, you use it as the number of elements to allocate for your other allocatables. Why do any of those even need to be dynamically allocated in the first place?

I would replace this code ...

    integer :: i, n, j, seed(12), k, m
    double precision:: sigma, r, epsilon, lx, ly, lz
    double precision, dimension(:), allocatable :: cx, cy, cz, dx, dy, dz, x, y, z, LJx, LJy, LJz
    allocate(x(n), y(n), z(n), LJx(n), LJy(n), LJz(n), dx(n), dy(n), dz(n))
    n = 100 !Number of molecules inside the box

... with this:

    integer, parameter :: n = 100
    integer :: i, j, seed(12), k, m
    double precision :: sigma, r, epsilon, lx, ly, lz
    double precision, dimension(n) :: cx, cy, cz, dx, dy, dz, x, y, z, LJx, LJy, LJz

I also observe that in the loop where you compute distances, you loop over variable k, but you do not use its value. As a result, it looks like you compute the same distances many times over.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 1
    As a minor quibble: I would avoid "initialize" for `n` which means something quite specific and inapplicable. Also, `cx` etc. are automatically allocated by the rules of Fortran 2003. – francescalus Apr 13 '15 at 21:37
  • I haven't found a way to incorporate it yet, but cx (cy, cz) is going to be substantially larger than n itself. There are 100 atoms so I need the distance between atom 1 and 2 and 3 and 4 and 5... to 100 and then 2 and 3 and 4... – Charles Butler Apr 13 '15 at 21:41
  • @francescalus, right, I was a bit sloppy there. I hope my update is more satisfactory. – John Bollinger Apr 13 '15 at 21:44
  • 1
    Thanks. I'm a bit sensitive to that issue, perhaps. But still, `cx` _is_ allocated under Fortran (not ifort without explicitly asking, older compilers). [But seemingly to the wrong size (which we can't resolve), given asker's comment above.] – francescalus Apr 13 '15 at 21:47
  • @CharlesButler, it does not matter that you need specifically `(n * (n - 1)) / 2` or even `n * n` elements in `cx` etc.. You can provide for the space either statically or dynamically, and if the latter then you must not try to *use* the space until you have allocated it. – John Bollinger Apr 13 '15 at 21:52
  • @francescalus, I'm pretty sure that the allocation status of an allocatable array is undefined until that array is actually allocated, and that reading or writing elements of such an array produces undefined behavior. That the program does not crash is surprising, but running somewhat as expected is a permitted expression of undefined behavior. – John Bollinger Apr 13 '15 at 21:55
  • 1
    Undefined allocation status is not applicable here (and doesn't happen after Fortran 90). Until `cx` is allocated in this program it is "not allocated". However, in Fortran 2003 (see 7.4.1.3) and later such allocation does occur on intrinsic assignment of the allocatable variable. Yes, under the rules of Fortran 95 (or ifort) this would be invalid code. More so than just the undefined use of `n`, that is. – francescalus Apr 13 '15 at 22:03
  • Of course, you are quite correct to say that `n` is the issue here, so apologies for appearing too argumentative. – francescalus Apr 13 '15 at 22:05
  • @francescalus, clearly the rust on my Fortran skills is showing through. I appreciate your clarifications, and we agree that the usage of variable `n` is clearly part, if not all, of the issue here. I still maintain, though, that in the code presented, it serves no useful purpose to make any of the arrays allocatable in the first place. – John Bollinger Apr 13 '15 at 22:11
  • I agree with everything in your answer, except the first sentence. [And would strengthen it by saying that those loops don't redefine `cx`.] – francescalus Apr 13 '15 at 22:18
  • @JohnBollinger: Made your suggested changes, and it did solve the problem of only getting 20 number as output, but I still cannot wrap my head around how to get (n * (n - 1)) / 2 numbers out of 1 or even 2 do loops. – Charles Butler Apr 13 '15 at 22:23
  • You are correct btw, the output of dx is the same number over and over up to the size of the array. I know this should be so very simple, but I just can't see it. – Charles Butler Apr 13 '15 at 22:51
  • @CharlesButler, `n * (n - 1) / 2` is the total number of iterations that the `do k` loop in your existing code will perform. There will be `n - 1` iterations when `j` is 1, `n - 2` when `j` is 2, down to 1 when `j` is `n - 1`. The sum of this series is `n * (n - 1) / 2`. – John Bollinger Apr 14 '15 at 14:08