Я задал этот вопрос во избежание дублирования кода путем реструктуризации цикла if / do , чтобы определить, как я мог бы сделать свой код более эффективным.Решение очень помогло мне и показано ниже.
function grad(psi)
implicit none
integer, parameter :: nx = 24, ny = 24, nxx = nx / 2, nyy = ny / 2
real, parameter :: pi = 4 * atan(1.0), f0 = pi ** 2 * 1.3
complex, dimension(3,3,-nx:nx,-ny:ny) :: psi, grad
grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1)
grad(:,:,0,0) = psi(:,:,1,0)
grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]) = psi(:,:,[-nxx+1,nxx+1],[-nyy,nyy,ny]) - f0 * psi(:,:,[-nxx,nxx],[-nyy,nyy,ny])
end
Однако теперь мне нужно еще больше оптимизировать свой код.
В приведенном выше примере есть часть, заданная
grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]) = psi(:,:,[-nxx+1,nxx+1],[-nyy,nyy,ny]) - ...
, которая эффективно выполняет то, что янужно с учетом всех комбинаций списков -nxx,-nyy, -nxx, nyy,
и т. д.
Однако список нужных мне индексов намного больше, чем просто [-nxx,nxx],[-nyy,nyy]
.Мне действительно нужно что-то вроде [-nxx,nxx,-nxx1,nxx1,-nxx2,nxx2,-nxx3,nxx3], [-nyy,nyy,-nyy1,nyy1,-nyy2,nyy2,-nyy3,nyy3]
и т. Д., Где nxx = nx/2, nxx1 = nx/4, nxx2 = nx/8, nxx3 = nx/16
и т. Д.
Есть ли способ, которым я могу сделать это эффективно?Например, я могу просто определить одну переменную, такую как:
integer : Listx, Listy
Listx = [-nxx,nxx,-nxx1,nxx1,-nxx2,nxx2,-nxx3,nxx3]
Listy = [-nyy,nyy,-nyy1,nyy1,-nyy2,nyy2,-nyy3,nyy3]
и затем получить что-то вроде
grad(:,:,Listx,Listy) = psi(:,:,Listx+1,Listy) - ...
Я попытался сделать это, но определение Listx, Listy как целых чисел кажетсядавать проблемы.Я попытался сделать следующее:
Integer :: Listx, Listy
Listx = [-nxx,nxx,-nxx1,nxx1,-nxx2,nxx2,-nxx3,nxx3]
Listy = [-nyy,nyy,-nyy1,nyy1,-nyy2,nyy2,-nyy3,nyy3]
, но затем при компиляции Фортран говорит мне, что «Несовместимые ранги 0 и при назначении в ...»
Как я могу правильно определить это?Спасибо