Fortran循环输出不正确

时间:2014-01-09 18:40:12

标签: loops fortran

我编写了一个例程,为包含1的进一步右侧单元格提供列索引位置,在掩码数组中标记多边形的右边缘。

但是当我打印索引数组时(我意识到行位置数组是冗余的),所有行都报告一个位置(0除外),我知道不应该这样。我似乎无法找到以下可能不正确的地方。

示例掩码数组:

0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 0 0 0 0 0 
0 0 0 0 0 1 1 1 1 1 1 0 0 0 
0 0 0 1 1 1 1 1 1 1 1 0 0 0 
0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0

期望的输出:

[0,10,10,11,11,11,9,8,0]

这是Fortran的事情,还是我的逻辑关闭(

例程:

  subroutine get_right_idx(mask_array, idx_x, idx_y)                        
  integer, parameter :: x = 169 ! num columns                               
  integer, parameter :: y = 124 ! num rows                                  
  integer i ! iterator for rows                                             
  integer j ! iterator for columns                                          
  integer row_x ! x position for furthest south cell in row                 
  integer row_y ! y position for furthest south cell in row                 
  integer :: idx_x(y) ! index positions for lowest lat in model grid - x    
  integer :: idx_y(y) ! index positions for lowest lat in model grid - y    
  real mask_array(y,x) ! mask array of zeros, containing polygon of ones    

  do j=1,y                                                                  
    row_x = 0                                                               
    row_y = 0                                                               
    do i=1,x                                                                
      if (mask_array(j,i).eq.1) then                                        
        row_x = i                                                           
        row_y = j                                                           
      endif                                                                 
    enddo                                                                   
    idx_x(j)=row_x                                                          
    idx_y(j)=row_y                                                          
  enddo                                                                     
  endsubroutine get_right_idx  

实际屏蔽(在Open Office中缩小): enter image description here

以下是我要评估的面具。我得到的数组对于所有元素都具有非零值,其中在数组的开始和结束处应该有零元素,无论从哪个方向进行评估。

输出:

125         104         104         104         104         104         104         114         114         114         114         103         103         103         108         108         103         103         103         103          97          97          97         107         107         107         107         107         107         107         107         107          97         101         101         101         101         101         111         111         111         111         111         111         101         101         100         105         105         105         105         105         105         100         115         115         104         104         104         104         104         104         104         104         104         104          98          98          98          98         108         108         108         108         108         108         108         108          98         102         102         102         102         102         112         112         112         112         112         112         101         101         101         106         106         106         101         101         101          95          95         105         105         105         105         105         105         105         105         105         105          99          99          99          99          99         109         109         109         109         109         109         109          99          99

2 个答案:

答案 0 :(得分:2)

我制作了一个快速的代码模板,但我提出了建议。由于您要查找其中包含1的最大索引 j ,您只需通过启动您的j循环即可对其进行测试。最大值(在示例中为14)并向下工作但是如果mask_array==1退出内部执行循环

您可以将149替换为这些维度的最大值,从而对此进行概括。

program get_right
   implicit none
   integer, dimension(9,14) :: mask_array
   integer :: i,j,mask_out(9),j_tmp
   mask_array(1,:)=[0,0,0,0,0,0,0,0,0,0,0,0,0,0]
   mask_array(2,:)=[0,0,0,0,0,0,0,1,0,0,0,0,0,0]
   mask_array(3,:)=[0,0,0,0,0,0,1,1,1,0,0,0,0,0]
   mask_array(4,:)=[0,0,0,0,0,1,1,1,1,1,1,0,0,0]
   mask_array(5,:)=[0,0,0,1,1,1,1,1,1,1,1,0,0,0]
   mask_array(6,:)=[0,0,0,1,1,1,1,1,1,1,1,0,0,0]
   mask_array(7,:)=[0,0,0,0,0,0,1,1,1,1,0,0,0,0]
   mask_array(8,:)=[0,0,0,0,0,0,0,0,0,1,0,0,0,0]
   mask_array(9,:)=[0,0,0,0,0,0,0,0,0,0,0,0,0,0]

   mask_out=0
   do i=1,9
      j_tmp=0
      print '(14(i0,2x))',mask_array(i,:)
      do j=14,1,-1
         if(mask_array(i,j)==1) then
            j_tmp=j
            exit
         endif
      enddo
      mask_out(i)=j
   enddo

   print *,""
   print '(9(i0,2x))',mask_out

end program get_right

我得到了0,8,9,11,11,11,10,10,0作为答案(这是你所得到的但是向后)。

答案 1 :(得分:2)

或者,如果输入让你累了,你可以评估这个

maxval(mask_array*spread([(ix,ix=lbound(mask_array,dim=2),&
        ubound(mask_array,dim=2))],dim=1, ncopies=size(mask_array,dim=1)),dim=2)

正如您所看到的,这会使用spread和隐含do循环创建一个临时数组(如果您的掩码很大,这可能是不受欢迎的),此临时数的每个元素都包含其自己的列索引号。然后它将临时值与mask_array相乘,执行逐元素乘法而不是矩阵乘法。最后取结果每行的maxval。这将按照与Kyle代码相同的顺序返回向量。

我已编辑代码以使用lboundubound而不是1size,以防您想在较低的数组上使用代码除1以外的界限。

鲍勃是你的叔叔,但不要问这是否比凯尔的代码更快。如果您对执行速度测试和测量感兴趣。

顺便说一句,由于这只返回一个向量而不修改其参数或有任何其他副作用,我将其打包为函数而不是子例程。