Fortran bug: rank problem gfortran

Click For Summary

Discussion Overview

The discussion revolves around a Fortran coding issue related to the use of the intrinsic function minloc, specifically regarding a rank error encountered when trying to assign its output to a variable. Participants explore the nature of the error and the correct usage of minloc in the context of extracting the index of the minimum value from an array.

Discussion Character

  • Technical explanation, Debate/contested, Exploratory

Main Points Raised

  • One participant describes an error message indicating incompatible ranks when using minloc, expressing confusion about why it occurs.
  • Another participant identifies that minloc returns an array of integers, not a single integer, which clarifies the misunderstanding regarding its output.
  • A participant suggests that rank errors indicate issues with variable dimensions, specifically noting that iclosept is defined as a rank 0 integer while minloc returns a rank 1 array.
  • There is a reiteration of the rank issue, confirming that the initial misunderstanding was indeed the source of the error.

Areas of Agreement / Disagreement

Participants generally agree on the nature of the error related to variable ranks and the output of minloc, but the discussion reflects an initial misunderstanding that was clarified through the exchange.

Contextual Notes

The discussion highlights the importance of understanding the output types of intrinsic functions in Fortran, particularly in relation to variable definitions and dimensions.

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
 

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