Как увеличить размер массива на лету в Fortran?

моя программа работает через 3D-массив, помечая "кластеры", которые он находит, а затем выполняет некоторые проверки, чтобы увидеть, имеют ли какие-либо соседние кластеры метку выше текущего кластера. Есть второй массив, который содержит "правильную" метку кластера. Если он обнаруживает, что N-й смежный кластер помечен правильно, этот элемент присваивается 0, в противном случае присваивается ему правильная метка (например, если n-й сайт имеет метку 2, а соседний помечен 3, 3-й элемент labelArray имеет значение 2). У меня есть веская причина сделать это, честно!

все, что я хочу, это иметь возможность назначить N-й элемент labelArray на лету. Я смотрел на выделяемые массивы и объявлял вещи как labelArray(*) но я действительно не понимаю их, несмотря на поиск в интернете и StackOverflow.

Так что любая помощь в этом будет потрясающей.

3 ответов


вот вопрос переполнения стека с некоторыми примерами кода, показывающими несколько способов использования выделяемых массивов Fortran:Как получить массив priorly-unkown в качестве вывода функции в Fortran: объявление, выделение, тестирование на наличие уже выделенного, использование нового move_alloc и выделение при назначении. Не показано явное освобождение, так как примеры используют move_alloc и автоматическое освобождение при выходе из процедуры.

P. S. Если вы хотите повторно добавить один элемент, вы должны подумать о своем подходе к структуре данных. Добавление одного элемента за раз путем увеличения массива не является эффективным подходом. Чтобы вырастить массив из N элементов до N+1 в Fortran, скорее всего, придется создать новый массив и скопировать все существующие элементы. Более подходящей структурой данных может быть связанный список. Связанный список можно создать в Fortran, создав пользовательский тип и используя указатели. Вы связываете членов вместе, указывая от одного к другому. Накладные расходы на добавление другого члена незначительны. Недостатком является то, что проще всего получить доступ к членам списка по порядку. У вас нет простой возможности массива, используя индексы, получить доступ к членам в любом порядке.

информация о связанных списках в Fortran, которые я нашел в интернете:http://www-uxsup.csx.cam.ac.uk/courses/Fortran/paper_12.pdf и http://www.iag.uni-stuttgart.de/IAG/institut/abteilungen/numerik/images/4/4c/Pointer_Introduction.pdf


если вы объявляете массив allocatable, вы используете deffered shape в форме real,

allocatable :: labelArray(:,:)

или

real,dimension(:,:),allocatable :: labelArray

с числом двойных двоеточий, означающим ранг (количество ваших индексов) вашего массива.

если массив нераспределен, вы используете

 allocate(labelarray(shapeyouwant))

С правильным количеством индексов. Например allocate(labelarray(2:3,-1:5)) для массива с индексами 2 до 3 в demension 1 и -1 до 5 в размерности 2.

для изменения размера вы должны сначала освободить массив, используя

deallocate(labelArray)

чтобы перераспределить выделенный массив в новую форму, вам сначала нужно выделить новый массив с новой формой, скопировать существующий массив в новый массив и переместить ссылку старого массива в новый массив с помощью move_alloc().

  call allocate(tmp(size_old+n_enlarge))
  tmp(1:size_old) = array(1:size_old)
  call move_alloc(tmp, array)

старый массив освобождается автоматически при перемещении ссылки на новый массив move_alloc().


Fortran 95 освобождает массивы автоматически, если они выпадают из области видимости (например, конец их подпрограммы).

Fortran 2008 имеет приятную особенность автоматического распределения по назначению. Если ты скажешь array1=array2 и array1 не выделяется, он автоматически выделяется для правильной формы.


поздний комментарий... проверьте численные рецепты для Fortran 90. Они реализовали хорошую функцию перераспределения, которая была совместима с Fortran 90. В этом случае массивы должны быть атрибутивными указателями, а не присваиваемыми.

функция получает старый массив и нужный размер и возвращает указатель на новый массив с измененным размером.

Если это вообще возможно, используйте Fortran 95 или 2003. Если 2003 год невозможен, то 95-хороший компромисс. Он обеспечивает лучший синтаксис указателя.