Fortran Fortran bug: rank problem gfortran

Click For Summary
The discussion centers around a Fortran code issue where the user encounters a compilation error related to the `minloc` intrinsic function. The error message indicates a rank mismatch between the expected integer variable and the array returned by `minloc`. Initially, the user mistakenly assumed that `minloc` would return a single integer, but it actually returns an array, even for a one-dimensional input. To resolve the issue, the user modified the code by introducing a temporary array to store the output of `minloc` and then extracted the desired integer value from this array. The final code successfully compiles and correctly identifies the index of the minimum value in the distance array. The discussion highlights the importance of understanding the output types of intrinsic functions in Fortran to avoid rank errors.
billiards
Messages
765
Reaction score
16
This is my own code, and it won't compile with gfortran. All I want to do is extract the location of the cell with the minimum value in an array. A seemingly simple task but one that does not work with the intrinsic function minloc, for reasons I do not understand.

The error message:

Code:
    iclosept=minloc(dist)
    1
Error: Incompatible ranks 0 and 1 in assignment at (1)

The code:

Code:
  subroutine distance_to_trench(pt,tr,mindist,iclosept)
  ! find (great circle) distance from point to each point on the trench
  ! distance = the minimum distance to the trench
  
    type(point) :: pt
    type(trench) :: tr
    real, parameter :: pi=3.14159265359
    real, parameter :: eradius=6371
    real :: rad,deg
    real :: x1,y1,z1,x2,y2,z2
    real,dimension(:),allocatable :: dist
    real :: mindist
    integer :: ii, length, iclosept, a
    
    rad=pi/180
    deg=180/pi
    
    length=size(tr%poly%points%x)
    allocate(dist(length))
    
  ! method:
  ! convert lat lons to cartesian vectors
  ! use angle between vectors to find the distance
  
    x1=cos(rad*pt%y)*cos(rad*pt%x)
    y1=cos(rad*pt%y)*sin(rad*pt%x)
    z1=sin(rad*pt%y)
  
    do ii=1, length
      
      x2=cos(rad*tr%poly%points(ii)%y)*cos(rad*tr%poly%points(ii)%x)
      y2=cos(rad*tr%poly%points(ii)%y)*sin(rad*tr%poly%points(ii)%x)
      z2=sin(rad*tr%poly%points(ii)%y)
  
      dist(ii)=eradius*acos(x1*x2+y1*y2+z1*z2)
      
      print *,dist(ii)
    
    enddo
    
    mindist=minval(dist)
    
    a=size(dist)
    print *,'size of dist', size(dist), a

    iclosept=minloc(dist)
    print *,'minloc', minloc(dist), iclosept
    
    deallocate(dist)
    
  end subroutine distance_to_trench
 
Technology news on Phys.org
Fixed it.

Turns out I was confused about the output of the minloc function. It returns an array of integer(s). I was assuming it returned an integer. Because I was only thinking about a 1-d array. But in the case of a 1-d array, it actually returns an array of size 1, where the element contains the integer I was after.

To fix my above code I introduced a temporary array and assigned it by minloc. Then I extracted the single element from it into a pure integer.

Thus:

Code:
  subroutine distance_to_trench(pt,tr,mindist,iclosept)
  ! find (great circle) distance from point to each point on the trench
  ! distance = the minimum distance to the trench
  
    type(point) :: pt
    type(trench) :: tr
    real, parameter :: pi=3.14159265359
    real, parameter :: eradius=6371
    real :: rad,deg
    real :: x1,y1,z1,x2,y2,z2
    real,dimension(:),allocatable :: dist
    real :: mindist
    integer :: ii, length, iclosept, temp(1)
    
    rad=pi/180
    deg=180/pi
    
    length=size(tr%poly%points%x)
    allocate(dist(length))
    
  ! method:
  ! convert lat lons to cartesian vectors
  ! use angle between vectors to find the distance
  
    x1=cos(rad*pt%y)*cos(rad*pt%x)
    y1=cos(rad*pt%y)*sin(rad*pt%x)
    z1=sin(rad*pt%y)
  
    do ii=1, length
      
      x2=cos(rad*tr%poly%points(ii)%y)*cos(rad*tr%poly%points(ii)%x)
      y2=cos(rad*tr%poly%points(ii)%y)*sin(rad*tr%poly%points(ii)%x)
      z2=sin(rad*tr%poly%points(ii)%y)
  
      dist(ii)=eradius*acos(x1*x2+y1*y2+z1*z2)
      
      print *,dist(ii)
    
    enddo
    
    mindist=minval(dist)
    temp=minloc(dist)
    
    iclosept=temp(1)
    
    deallocate(dist)
    
  end subroutine distance_to_trench
 
Learn If you want to write code for Python Machine learning, AI Statistics/data analysis Scientific research Web application servers Some microcontrollers JavaScript/Node JS/TypeScript Web sites Web application servers C# Games (Unity) Consumer applications (Windows) Business applications C++ Games (Unreal Engine) Operating systems, device drivers Microcontrollers/embedded systems Consumer applications (Linux) Some more tips: Do not learn C++ (or any other dialect of C) as a...

Similar threads

  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 4 ·
Replies
4
Views
9K
  • · Replies 11 ·
Replies
11
Views
7K
  • · Replies 2 ·
Replies
2
Views
4K
  • · Replies 11 ·
Replies
11
Views
6K
  • · Replies 3 ·
Replies
3
Views
2K
Replies
18
Views
3K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K