Operando elemento a elemento em um array
-
27-10-2019 - |
Pergunta
Estou tentando verificar se meus arrays estão retornando absurdos acessando elementos fora dos limites, em fortran.E quero verificar se esses valores são menores que um e, se forem, altere-os para um.
Esta é a parte do meu código que está causando problemas:
lastNeighLabel=(/clusterLabel(jj-1,kk,ll), clusterLabel(jj,kk-1,ll), clusterLabel(jj,kk,ll-1)/)
LastNeighLabel contém o rótulo do cluster (entre 1 e n, onde n é o número total de clusters separados exclusivos encontrados) para o último vizinho na direção x, y, z, respectivamente.
Quando jj
ou kk
ou ll
são 1, eles tentam acessar o 0º elemento na matriz, e como FORTRAN
conta a partir de 1 em arrays, ele tenta destruir o universo.Atualmente estou em uma confusão de cerca de 8 instruções if/elseif tentando codificar para cada eventualidade.Mas eu esperava que houvesse uma maneira de operar em cada elemento.Então, basicamente, eu gostaria de dizer where((/jj-1,kk-1,ll-1/).lt.1) do clusterLabel(jj-1,kk,ll)=0 etc
dependendo de qual elemento está causando o problema.
Mas não consigo pensar em uma maneira de fazer isso porque o where manipulará apenas as variáveis passadas para ele, e não um array diferente no mesmo índice.Ou eu estou errado?
Editarei com prazer se isso não fizer sentido.
Solução
Talvez você possa usar uma função?
real function f(A,i,j,k)
real :: A(:,:,:)
integer :: i,j,k
if (i==0.or.j==0.or.k==0) then
f=0
else
f=A(i,j,k)
endif
end function f
e então use f(clusterLabel,jj-1,kk,ll) etc.
Outras dicas
Não é obrigatório que o Fortran acesse arrays começando em um.Qualquer valor inicial é permitido.Se for mais conveniente para você ter um array indexado com zero, declare o array como:
real, dimension (0:N-1, 0:M-1) :: array
Ou
real, dimension (0:N, 0:M) :: array
e faça com que os índices 0 sejam extras para capturar casos especiais.
Esta pode ser outra solução para o seu problema, já que valores de índice zero seriam legais.
Outra maneira possível de abordar isso é criar uma matriz de rótulos de cluster estendida (com limites de índice começando em 0), que é igual à matriz de rótulos de cluster com uma camada de zeros pregados na parte externa.Você pode então deixar seu loop rodar com segurança em todos os valores de jj, kk e ll.Depende do tamanho do array se esta for uma solução viável.
integer :: extended_cluster_label(0:size(cluster_label,1), & 0:size(cluster_label,2), & 0:size(cluster_label,3) & ) extended_cluster_label(0,:,:) = 0 extended_cluster_label(:,0,:) = 0 extended_cluster_label(:,:,0) = 0 extended_cluster_label(1:, 1:, 1:) = cluster_label