Assign 2D Array with Reals in Fortran - Help Needed

  • Context: Fortran 
  • Thread starter Thread starter davidfur
  • Start date Start date
  • Tags Tags
    2d Array Assignment
Click For Summary
SUMMARY

The forum discussion centers on a Fortran programming issue involving the assignment of a 2D array with real numbers. The user encountered segmentation faults and bus errors when attempting to reshape an array within the subroutine get_energy_and_grad. Key problems identified include improper subroutine call syntax, undeclared global variables, and incorrect usage of the reshape function. The user successfully resolved the issue by properly declaring and allocating the coords and gradvec variables outside the subroutine.

PREREQUISITES
  • Fortran programming language fundamentals
  • Understanding of subroutine syntax in Fortran
  • Knowledge of array handling and memory management in Fortran
  • Familiarity with the reshape function in Fortran
NEXT STEPS
  • Study the Fortran subroutine syntax and best practices
  • Learn about memory allocation and management in Fortran
  • Explore the reshape function in detail, including its requirements
  • Investigate debugging techniques for segmentation faults in Fortran
USEFUL FOR

Fortran developers, computational scientists, and anyone involved in numerical simulations requiring array manipulations in Fortran.

davidfur
Messages
18
Reaction score
2
Hi guys,
On with my Fortran adventures...I'm trying to accomplish a simple task: assign a 2D array with some reals. Here's an excerpt from the code:

Fortran:
subroutine get_energy_and_grad(natoms_,coords,ereal,gradmat)

    include 'cbka.blk'
    include 'opt.blk'
    integer, intent(in)    :: natoms_
    double precision, intent(in)    :: coords(3*natoms_)
    real*8, intent(out)    :: ereal    ! total energy
    real*8, dimension(3,3), intent(out)    :: gradmat

    call vlist
    call srtbon1
    call encalc
     
    ereal = estrc ! total energy

!    write (*,*) 'natoms_ is: ', natoms_

    write (*,*) 'size of gradmat is:', size(gradmat)
    write (*,*) 'size of d is:', size(d)
    write (*,*) 'shape of gradmat is:', shape(gradmat)
    write (*,*) 'shape of d is:', shape(d)

    gradmat = reshape((/ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 /),(/3, 3/))

    write(*,*) 'gradmat is: ', gradmat(2,3)

end subroutine get_energy_and_grad

This just won't assign the 1.0-9.0 reals into gradmat and throws out the following:

Code:
 size of gradmat is:           9
 size of d is:        7500
 shape of gradmat is:           3           3
 shape of d is:           3        2500

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

Backtrace for this error:
#0  0x7F3B8F78EE08
#1  0x7F3B8F78DF90
#2  0x7F3B8F0D54AF
#3  0x40151C in __reaxff_interface_MOD_get_energy_and_grad
#4  0x402C5E in MAIN__ at main.f90:?
Segmentation fault (core dumped)

I'm obviously doing something really stupid, but I just can't figure out what's wrong... need help!

Dave
 
Last edited:
Technology news on Phys.org
Here's a tutorial on the reshape function:

https://www.tutorialspoint.com/fortran/reshape.htm

I don't see what wrong but a memory error often indicates referencing an element outside the array bounds.

Perhaps, you could try being more explicit and breaking the statement up a bit:

Fortran:
 real*8, dimension (1:9) :: b = (/ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 /)

 gradmat = reshape( b , (/3, 3/) )
 
Thanks jedishrfu, but it doesn't work either. I suspect there's something wrong with my declarations...
I post here the full code if this helps

Main program

Fortran:
program main

use reaxff_interface
implicit none

integer natoms_
real*8 ereal
real*8, allocatable :: coords(:,:)
real*8, allocatable :: gradvec(:,:)

call get_energy_and_grad(gradvec)

write (*,*) "This is main. grad(3,3) is : ", gradvec(3,3)

end program main

Module

Fortran:
    module reaxff_interface
    implicit none

subroutine get_energy_and_grad(grad)
    include 'cbka.blk'
    include 'opt.blk'
    real*8, dimension(3,3), intent(out)     :: grad
    real*8, dimension (1:9) :: b

    b = (/ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 /)
    grad = reshape( b , (/3, 3/) ) 
end subroutine get_energy_and_grad

end module reaxff_interface

output:
Code:
Program received signal SIGBUS: Access to an undefined portion of a memory object.

Backtrace for this error:
#0  0x7F4FB566DE08
#1  0x7F4FB566CF90
#2  0x7F4FB4FB44AF
#3  0x7F4FB574563F
#4  0x7F4FB5748154
#5  0x7F4FB5748D3E
#6  0x402DBF in MAIN__ at main.f90:?
Bus error (core dumped)
 
davidfur said:
Here's an excerpt from the code:
Fortran:
subroutine get_energy_and_grad(natoms_,coords,ereal,gradmat)

    include 'cbka.blk'
    include 'opt.blk'
    integer, intent(in)    :: natoms_
    double precision, intent(in)    :: coords(3*natoms_)
    real*8, intent(out)    :: ereal    ! total energy
    real*8, dimension(3,3), intent(out)    :: gradmat

    call vlist
    call srtbon1
    call encalc
    
    ereal = estrc ! total energy

!    write (*,*) 'natoms_ is: ', natoms_

    write (*,*) 'size of gradmat is:', size(gradmat)
    write (*,*) 'size of d is:', size(d)
    write (*,*) 'shape of gradmat is:', shape(gradmat)
    write (*,*) 'shape of d is:', shape(d)

    gradmat = reshape((/ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 /),(/3, 3/))

    write(*,*) 'gradmat is: ', gradmat(2,3)

end subroutine get_energy_and_grad
I see two or maybe three problems:
1. In your three call statements, none of the subroutine calls is written correctly. The syntax for a call statement is
call SubName(argument1, argument2, ...). If a subroutine has no parameters, the parentheses still must be used. See http://pages.mtu.edu/~shene/COURSES/cs201/NOTES/F90-Subprograms.pdf, on page titled "Subroutines: 2/2".
You don't show the definitions for the three subroutines, so I can't tell if any of them takes any arguments.

2. What is d? There is no declaration for d in either the parameter list or in the declarations for local variables, so d apparently is a global variable. It's very bad practice for a function of subroutine to access global variables. At the very least, doing this makes debugging much more difficult.

3. I'm not sure that reshape will take a list of constants as its first argument. Per the GNU Fortran Compiler man page for reshape (https://gcc.gnu.org/onlinedocs/gfortran/RESHAPE.html), it appears to me that the first argument has to be a variable, but I'm not certain of this.
 
  • Like
Likes   Reactions: jim mcnamara
Thanks Mark44 for your help!
I managed to solve the problem by properly declaring and allocating coords and gradvec variables outside the get_energy_and_grad subroutine.

Cheers!
 

Similar threads

  • · Replies 20 ·
Replies
20
Views
3K
  • · Replies 11 ·
Replies
11
Views
3K
  • · Replies 5 ·
Replies
5
Views
8K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 13 ·
Replies
13
Views
2K
  • · Replies 5 ·
Replies
5
Views
13K
  • · Replies 8 ·
Replies
8
Views
3K
  • · Replies 10 ·
Replies
10
Views
26K
  • · Replies 5 ·
Replies
5
Views
9K
  • · Replies 5 ·
Replies
5
Views
3K