Select 在Fortran中从p*p*n数组中选择k*k子数组

Select 在Fortran中从p*p*n数组中选择k*k子数组,select,multidimensional-array,fortran,extract,Select,Multidimensional Array,Fortran,Extract,我在Fortran中有一个ppn数组,我想从那个更大的数组中提取k*k子数组。我试过这样做,但不确定是否有效: do i=1,p vp(i)=i end do help=y(1:p,t)*vp do t = 1, n A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t) end do 其中y包含值0和1,1表示希望将行/列作为子阵列。这行得通吗?如果不行,那同一件事怎么办?谢谢。如果我了解您想要做什么,下面

我在Fortran中有一个ppn数组,我想从那个更大的数组中提取k*k子数组。我试过这样做,但不确定是否有效:

do i=1,p
     vp(i)=i
end do
help=y(1:p,t)*vp
do t = 1, n
  A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t)
end do

其中y包含值0和1,1表示希望将行/列作为子阵列。这行得通吗?如果不行,那同一件事怎么办?谢谢。

如果我了解您想要做什么,下面是一个示例程序,它提取选定的列和行,但不使用太多的数组表示法

program test

integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb


if (count (good_row) /= Adim  .or.  count (good_col) /= Adim) then
   write (*, *) 'selection arrays not setup correctly.'
   stop
end if

do i=1, Bdim
   do j=1, Bdim
      B (i,j) = i + i*j**2  ! test values
   end do
end do

do i=1, Bdim
   write (*, *) (B (i, j), j=1, Bdim)
end do

ia = 0
do ib=1, Bdim
  if (good_row (ib)) then
     ia = ia + 1
     ja = 0
     do jb=1, Bdim
        if (good_col (jb)) then
           ja = ja + 1
           !write (*, *) ia, ja, ib, jb
           A(ia,ja) = B(ib,jb)
        end if
     end do
  end if
end do

write (*, *)
do i=1, Adim
   write (*, *) (A (i, j), j=1, Adim)
end do

stop
end program test

如果我了解您想要做什么,下面是一个示例程序,它提取选定的列和行,但不使用太多的数组表示法

program test

integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb


if (count (good_row) /= Adim  .or.  count (good_col) /= Adim) then
   write (*, *) 'selection arrays not setup correctly.'
   stop
end if

do i=1, Bdim
   do j=1, Bdim
      B (i,j) = i + i*j**2  ! test values
   end do
end do

do i=1, Bdim
   write (*, *) (B (i, j), j=1, Bdim)
end do

ia = 0
do ib=1, Bdim
  if (good_row (ib)) then
     ia = ia + 1
     ja = 0
     do jb=1, Bdim
        if (good_col (jb)) then
           ja = ja + 1
           !write (*, *) ia, ja, ib, jb
           A(ia,ja) = B(ib,jb)
        end if
     end do
  end if
end do

write (*, *)
do i=1, Adim
   write (*, *) (A (i, j), j=1, Adim)
end do

stop
end program test

解决方案二,在矢量1D阵列级别使用阵列操作-将主回路替换为:

ia = 0
do ib=1, Bdim
  if (good_row (ib)) then
     ia = ia + 1
     A (ia,:) = pack (B(ib,:), good_col)
  end if
end do
解决方案三,完全使用阵列操作:

program test

integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j

mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]


do i=1, Bdim
   do j=1, Bdim
      B (i,j) = i + i*j**2  ! test values
   end do
end do

do i=1, Bdim
   write (*, *) (B (i, j), j=1, Bdim)
end do

A  = reshape ( pack (B, mask), [Adim, Adim] )

write (*, *)
do i=1, Adim
   write (*, *) (A (i, j), j=1, Adim)
end do

stop
end program test

解决方案二,在矢量1D阵列级别使用阵列操作-将主回路替换为:

ia = 0
do ib=1, Bdim
  if (good_row (ib)) then
     ia = ia + 1
     A (ia,:) = pack (B(ib,:), good_col)
  end if
end do
解决方案三,完全使用阵列操作:

program test

integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j

mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]


do i=1, Bdim
   do j=1, Bdim
      B (i,j) = i + i*j**2  ! test values
   end do
end do

do i=1, Bdim
   write (*, *) (B (i, j), j=1, Bdim)
end do

A  = reshape ( pack (B, mask), [Adim, Adim] )

write (*, *)
do i=1, Adim
   write (*, *) (A (i, j), j=1, Adim)
end do

stop
end program test

不确定这些非代码片段是否对您有用,但是

不要忘记Fortran的数组分段功能。 不要忘记,您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示:

v/1、3、6、5、10/


向量下标可以应用于秩大于1的数组。用这种方式了解您的订阅需求会伤到我的头,但您可能想试试。

不确定这些非代码片段是否对您有用,但是

不要忘记Fortran的数组分段功能。 不要忘记,您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示:

v/1、3、6、5、10/


向量下标可以应用于秩大于1的数组。这样弄清楚你的订阅要求会伤到我的头,但你可能想试试。

是的,它应该会起作用,你甚至不需要dot=。。。环路

使用gfortran 4.2.3正确编译后

b=
 111 112 113 114
 121 122 123 124
 131 132 133 134
 141 142 143 144
 211 212 213 214
 221 222 223 224
 231 232 233 234
 241 242 243 244
a=
 111 113 114
 131 133 134
 141 143 144
 211 213 214
 231 233 234
 241 243 244
你也可以使用

  k = count( y> 0)
  a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
或者用逻辑思维。对。还有,错。而不是1和0

  program main
  integer,dimension(3,3,2):: a
  integer,dimension(4,4,2):: b
  logical,dimension(4):: y
  integer,dimension(4):: idx
  integer:: i,j,k

  idx = (/ (i,i=1,4) /)
  y = idx /= 2
  b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))

  k = count( y )
  a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)

  print '(A2/,(4I4))','b=',b
  print '(A2/,(3I4))','a=',a

  end

是的,它应该工作,你甚至不需要做t=。。。环路

使用gfortran 4.2.3正确编译后

b=
 111 112 113 114
 121 122 123 124
 131 132 133 134
 141 142 143 144
 211 212 213 214
 221 222 223 224
 231 232 233 234
 241 242 243 244
a=
 111 113 114
 131 133 134
 141 143 144
 211 213 214
 231 233 234
 241 243 244
你也可以使用

  k = count( y> 0)
  a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
或者用逻辑思维。对。还有,错。而不是1和0

  program main
  integer,dimension(3,3,2):: a
  integer,dimension(4,4,2):: b
  logical,dimension(4):: y
  integer,dimension(4):: idx
  integer:: i,j,k

  idx = (/ (i,i=1,4) /)
  y = idx /= 2
  b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))

  k = count( y )
  a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)

  print '(A2/,(4I4))','b=',b
  print '(A2/,(3I4))','a=',a

  end