Как увеличить размер массива в Фортране на лету? - PullRequest
9 голосов
/ 05 декабря 2011

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

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

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

Ответы [ 3 ]

10 голосов
/ 05 декабря 2011

Вот вопрос Stack Overflow с некоторыми примерами кода, показывающими несколько способов использования выделяемых массивов Fortran: Как получить ранее неизвестный массив в качестве вывода функции в Fortran : декларирование, выделение, тестирование длябудучи уже распределенным, используя новый move_alloc и распределение при назначении.Не показано, что есть явное освобождение, так как в примерах используются move_alloc и автоматическое освобождение при выходе из процедуры.

PS Если вы хотите повторно добавить один элемент, вам следует подумать о подходе к структуре данных.Добавление одного элемента за один раз путем увеличения массива не является эффективным подходом.Увеличение массива с 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 / Numberrik / images / 4 / 4c / Pointer_Introduction.pdf

6 голосов
/ 05 декабря 2011

Если вы объявляете массив размещаемым, вы используете отложенную форму в реальной форме,

allocatable :: labelArray(:,:)

или

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

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

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

 allocate(labelarray(shapeyouwant))

с правильным количеством индексов.Например, allocate(labelarray(2:3,-1:5)) для массива с индексами от 2 до 3 в измерении 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 и массив1 не выделен, он автоматически выделяется, чтобы иметь правильную форму.

1 голос
/ 11 июня 2014

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

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

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

...