# Compilation error most of the times

In most of the times i try to to run this code, it returns the error:

``````Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0xffffffff
#1  0xffffffff
#2  0xffffffff
#3  0xffffffff
#4  0xffffffff
#5  0xffffffff
#6  0xffffffff
#7  0xffffffff
#8  0xffffffff
#9  0xffffffff
#10  0xffffffff
#11  0xffffffff
#12  0xffffffff
#13  0xffffffff
#14  0xffffffff
``````

I’m still strugglin to learn the language but it’s (or it must be) a code for partciles collision using monte carlo method. I think the problem is the subroutine that change the velocities but i really have no idea. I know it is’nt the most efficient whey of writting this type of code and some of the code it’s temporary but the idea is pretty much it

``````program collision
use rf_mod, only: rf
implicit none

integer                                  :: n_particles = 10, i, j, k=0, t, ts=1000
real(8), parameter                       :: radius=0.06, dt=0.00008, c=1.0
integer, dimension(:,:)    , allocatable :: id_pairs, id_pairs_collide
real(8), dimension(:)      , allocatable :: ids, d_pairs
real(8), dimension(:,:)    , allocatable :: r, v, v1, v2,v1new, v2new, r1, r2
real(8), dimension(:,:,:), allocatable   :: rs, vs

!GENARATING THE PARTICLES
allocate(r(2,n_particles)) !position of the particles
allocate(v(2,n_particles)) !vellocities of the particles
allocate(ids(n_particles))

allocate(rs(ts, 2, n_particles))
allocate(vs(ts, 2, n_particles))
rs = 0.0
vs = 0.0

ids = [(i, i=1, n_particles)]

call random_number(r)
!do i=1, 2 !randomly positioning each particle
!do j=1, n_particles
!r(i,j) = rf()
!end do
!end do

open(40, file = 'pos.txt', status='unknown')
do j =1, n_particles
if(r(1,j) > 0.5) then
write(40,1)r(:,j)!, 'red'
1 format(2f20.6)
else
write(40,2)r(:,j)!, 'green'
2 format(2f20.6)
end if
end do
close(40)
!call system ('gnuplot -p grafico.plt')

!initial vellocities
!if the particle is in the left corner, v=100.
!if it's in the right, v=-100
v(2,:) = 0
where(r(1,:) < 0.5)
v(1,:) = 100.
elsewhere
v(1,:) = -100.
end where

!DISTANCE BETWEEN ALL THE PAIR OF PARTICLES

!all pair of particles
id_pairs = combination(ids)

do t=1, ts

do i=1, size(d_pairs)
k = k+1
end if
enddo

allocate(id_pairs_collide(2,k))

j=1
do i=1, size(d_pairs)
id_pairs_collide(:,j) =  id_pairs(:,i)
j=j+1
end if
enddo

!Now, we need to calculate the velocities of each particle, iterate, compare distances and change the vellocities
v1 = v(:, id_pairs_collide(1,:)) !particle i
v2 = v(:, id_pairs_collide(2,:)) !particle j
r1 = r(:, id_pairs_collide(1,:))
r2 = r(:, id_pairs_collide(2,:))

call get_new_v(v1, v2, v1new, v2new)
v(:, id_pairs_collide(1,:)) = v1new
v(:, id_pairs_collide(2,:)) = v2new

where(r(1,:) > 1.0)
v(1,:) = -abs(v(1,:))
end where
where(r(1,:) < 0.0)
v(1,:) = abs(v(1,:))
end where
where(r(2,:) > 1.0)
v(2,:) = -abs(v(2,:))
end where
where(r(2,:) < 0.0)
v(2,:) = abs(v(2,:))
end where

r = r + v*dt
rs(i,:,:) = r(:,:)
vs(i,:,:) = v(:,:)

deallocate(id_pairs_collide)
deallocate(v1)
deallocate(v2)
deallocate(r1)
deallocate(r2)
!print *, r(:,1)

enddo
open(40, file = 'all_pos.txt', status='unknown')
do i = 1, ts
write(40,*)rs(i,2,:)
end do
close(40)
PRINT*, v1new
contains

!get the distance between all the particles
!d_ij = sqrt(x_ij ^ 2 + y_ij ^ 2)

function combination(arg) result(comb)
implicit none
real(8), dimension(:,:), allocatable :: comb
real(8), intent(in), dimension(:) :: arg
integer :: M, N, counter, i, j

N=size(arg)
M=int(N*(N-1)/2)
allocate(comb(2,M))
counter=1
do i=1,N
do j=i+1,N
comb(1,counter)=arg(i)
comb(2,counter)=arg(j)
counter = counter + 1
enddo
enddo

end function combination

function diff(v)
implicit none
real(8), intent(in), dimension(:,:) :: v
real(8), allocatable:: diff(:), v1(:), v2(:)
integer :: n

n = size(v)/2
allocate(v1(n))
allocate(v2(n))
v1 = v(1,:)
v2 = v(2,:)
diff = abs(v1 - v2)
end function diff

subroutine get_new_v(v1, v2, v1n, v2n)

implicit none
real(8), dimension(:,:), intent(in)  :: v1, v2
real(8), dimension(:,:), allocatable :: G, gr, grnew
real(8), dimension(:,:), allocatable, intent(out) :: v1n, v2n
real(8) :: cosx, sinx, e, RF1, RF2, PI=4.D0*DATAN(1.D0)
integer :: i, j

gr = v1 - v2       !relative velocities
G  = (v1 + v2)/2.0 !relative velocities o the center of mass

do i=1, 2
do j=1, size(gr)/2
call random_number(RF2)
call random_number(RF1)
cosx = 2.0*RF1 - 1.0
sinx = sqrt(1 - cosx**2)
e = 2*RF2*pi

if(i==1) then

grnew(i,j) = sqrt(sum(gr(i,:)**2))*cosx

else

grnew(i,j) = sqrt(sum(gr(i,:)**2))*sinx*sin(e)

endif
enddo
enddo

v1n = G + 0.5*grnew
v2n = G - 0.5*grnew
return

end subroutine get_new_v

end program

module rf_mod
contains
DOUBLE PRECISION FUNCTION RF()
IMPLICIT DOUBLE PRECISION (A-H, O-Z)
data IX1,IX2,IX3,IX4,IX5,IX6/1500419,1400159,1364,1528,1,3/
RR1=1.0/FLOAT(IX1)
RR2=1.0/FLOAT(IX2)
IX5=MOD(IX5*IX3,IX1)
IX6=MOD(IX6*IX4,IX2)
RF=RR1*IX5+RR2*IX6
IF(RF.GE.1.0)RF=RF-1.0
END FUNCTION

end module
``````
1 Like

In subroutine get_newv(), you are using the 2-D allocatable array grnew without allocating it!

Another thing to check: does your code satisfies the following rule?

If a vector subscript has two or more elements with the same value, an array section with that vector subscript shall not appear in a variable definition context

2 Likes

I see these problems in your code:

• Some allocatable variables are not allocated
• Mixed mode arithmetic
• Mixed mode variable assignments
2 Likes

Using debugging compiler options can aid in debugging. On WSL2, compiling with
`gfortran -g -fbacktrace collision.f90` and running

gives

``````Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7fe1bdf1d700 in ???
#1  0x7fe1bdf1c8a5 in ???
#2  0x7fe1bdc0120f in ???
#3  0x55df3f479b98 in get_new_v
at /mnt/c/fortran/test/collision.f90:207
#4  0x55df3f47ce6d in collision
at /mnt/c/fortran/test/collision.f90:130
#5  0x55df3f47f0e9 in main
at /mnt/c/fortran/test/collision.f90:18
Segmentation fault
``````

The code was rearranged to put the module before the main program:

collision.f90
``````module rf_mod
contains
DOUBLE PRECISION FUNCTION RF()
IMPLICIT DOUBLE PRECISION (A-H, O-Z)
data IX1,IX2,IX3,IX4,IX5,IX6/1500419,1400159,1364,1528,1,3/
RR1=1.0/FLOAT(IX1)
RR2=1.0/FLOAT(IX2)
IX5=MOD(IX5*IX3,IX1)
IX6=MOD(IX6*IX4,IX2)
RF=RR1*IX5+RR2*IX6
IF(RF.GE.1.0)RF=RF-1.0
END FUNCTION

end module

program collision
use rf_mod, only: rf
implicit none

integer                                  :: n_particles = 10, i, j, k=0, t, ts=1000
real(8), parameter                       :: radius=0.06, dt=0.00008, c=1.0
integer, dimension(:,:)    , allocatable :: id_pairs, id_pairs_collide
real(8), dimension(:)      , allocatable :: ids, d_pairs
real(8), dimension(:,:)    , allocatable :: r, v, v1, v2,v1new, v2new, r1, r2
real(8), dimension(:,:,:), allocatable   :: rs, vs

!GENARATING THE PARTICLES
allocate(r(2,n_particles)) !position of the particles
allocate(v(2,n_particles)) !vellocities of the particles
allocate(ids(n_particles))

allocate(rs(ts, 2, n_particles))
allocate(vs(ts, 2, n_particles))
rs = 0.0
vs = 0.0

ids = [(i, i=1, n_particles)]

call random_number(r)
!do i=1, 2 !randomly positioning each particle
!do j=1, n_particles
!r(i,j) = rf()
!end do
!end do

open(40, file = 'pos.txt', status='unknown')
do j =1, n_particles
if(r(1,j) > 0.5) then
write(40,1)r(:,j)!, 'red'
1 format(2f20.6)
else
write(40,2)r(:,j)!, 'green'
2 format(2f20.6)
end if
end do
close(40)
!call system ('gnuplot -p grafico.plt')

!initial vellocities
!if the particle is in the left corner, v=100.
!if it's in the right, v=-100
v(2,:) = 0
where(r(1,:) < 0.5)
v(1,:) = 100.
elsewhere
v(1,:) = -100.
end where

!DISTANCE BETWEEN ALL THE PAIR OF PARTICLES

!all pair of particles
id_pairs = combination(ids)

do t=1, ts

do i=1, size(d_pairs)
k = k+1
end if
enddo

allocate(id_pairs_collide(2,k))

j=1
do i=1, size(d_pairs)
id_pairs_collide(:,j) =  id_pairs(:,i)
j=j+1
end if
enddo

!Now, we need to calculate the velocities of each particle, iterate, compare distances and change the vellocities
v1 = v(:, id_pairs_collide(1,:)) !particle i
v2 = v(:, id_pairs_collide(2,:)) !particle j
r1 = r(:, id_pairs_collide(1,:))
r2 = r(:, id_pairs_collide(2,:))

call get_new_v(v1, v2, v1new, v2new)
v(:, id_pairs_collide(1,:)) = v1new
v(:, id_pairs_collide(2,:)) = v2new

where(r(1,:) > 1.0)
v(1,:) = -abs(v(1,:))
end where
where(r(1,:) < 0.0)
v(1,:) = abs(v(1,:))
end where
where(r(2,:) > 1.0)
v(2,:) = -abs(v(2,:))
end where
where(r(2,:) < 0.0)
v(2,:) = abs(v(2,:))
end where

r = r + v*dt
rs(i,:,:) = r(:,:)
vs(i,:,:) = v(:,:)

deallocate(id_pairs_collide)
deallocate(v1)
deallocate(v2)
deallocate(r1)
deallocate(r2)
!print *, r(:,1)

enddo
open(40, file = 'all_pos.txt', status='unknown')
do i = 1, ts
write(40,*)rs(i,2,:)
end do
close(40)
PRINT*, v1new
contains

!get the distance between all the particles
!d_ij = sqrt(x_ij ^ 2 + y_ij ^ 2)

function combination(arg) result(comb)
implicit none
real(8), dimension(:,:), allocatable :: comb
real(8), intent(in), dimension(:) :: arg
integer :: M, N, counter, i, j

N=size(arg)
M=int(N*(N-1)/2)
allocate(comb(2,M))
counter=1
do i=1,N
do j=i+1,N
comb(1,counter)=arg(i)
comb(2,counter)=arg(j)
counter = counter + 1
enddo
enddo

end function combination

function diff(v)
implicit none
real(8), intent(in), dimension(:,:) :: v
real(8), allocatable:: diff(:), v1(:), v2(:)
integer :: n

n = size(v)/2
allocate(v1(n))
allocate(v2(n))
v1 = v(1,:)
v2 = v(2,:)
diff = abs(v1 - v2)
end function diff

subroutine get_new_v(v1, v2, v1n, v2n)

implicit none
real(8), dimension(:,:), intent(in)  :: v1, v2
real(8), dimension(:,:), allocatable :: G, gr, grnew
real(8), dimension(:,:), allocatable, intent(out) :: v1n, v2n
real(8) :: cosx, sinx, e, RF1, RF2, PI=4.D0*DATAN(1.D0)
integer :: i, j

gr = v1 - v2       !relative velocities
G  = (v1 + v2)/2.0 !relative velocities o the center of mass

do i=1, 2
do j=1, size(gr)/2
call random_number(RF2)
call random_number(RF1)
cosx = 2.0*RF1 - 1.0
sinx = sqrt(1 - cosx**2)
e = 2*RF2*pi

if(i==1) then

grnew(i,j) = sqrt(sum(gr(i,:)**2))*cosx

else

grnew(i,j) = sqrt(sum(gr(i,:)**2))*sinx*sin(e)

endif
enddo
enddo

v1n = G + 0.5*grnew
v2n = G - 0.5*grnew
return

end subroutine get_new_v

end program
``````

Line 207 is
` grnew(i,j) = sqrt(sum(gr(i,:)**2))*cosx`
consistent with what @mecej4 wrote. Other gfortran debugging options were discussed at Stack Overflow.

Btw your question is about a run-time error, not a compilation error.

2 Likes

If you are using gfortran, compile your code with the following options: `-g -O0 -Wall -Werror -fmax-errors=1 -fcheck=all`. This set typically catches errors such as accessing an array with an out-of-bounds index.

2 Likes

about line 207, i don’t think i understood what’s wrong

1 Like

Thanks, but could you point me on how to fix those problems?

1 Like

Jorvz, looks like you missed this:

You need to allocate the allocatable arrays before using them. It looks like you did not explicitly allocate `gr`, `G`, or `grnew`. `gr` got allocated through the automatically allocated on assignment feature on the line which reads `gr=v1-v2`. Similar with `G`. `grnew` array is being used without being allocated.

1 Like
• You need to allocate all allocatable variables, like `gr`, `G`, `grnew`, …

• I would like to suggest you to use a module for kinds as follows:

``````!==============================================================================
MODULE MOD_KINDS

INTEGER, PARAMETER :: REL8 = 8

END MODULE MOD_KINDS
!==============================================================================
``````

Now to declare and define a variable using module `MOD_KINDS` you can use:
`real(REL8)` instead of `real(8)`,
`rs = 0.0_REL8` instead of `rs = 0.0`,
`0.5_REL8` instead of `0.5`
and `2.0_REL8*radius` instead of `2*radius`. Find all the same problems and fix them.

• To convert `x` to real(kind=8), you can use `REAL(x,KIND=REL8)`.

• `ids` is `real(kind=8)`: `ids = REAL([(i, i=1, n_particles)], KIND=REL8)`

• Check `n = size(v)/2` and `M = int(N*(N-1)/2)`. Are they correct?

• I think there are more problems but you can find them yourself, also debug each function and subroutine with a test program first, then use them in your program, and finally debug your main program. (as @beliavsky mentioned use `-g -fbacktrace` flags.)