如何在 Fortran 中即时增加数组大小?
我的程序通过 3D 数组运行,标记它找到的“簇”,然后进行一些检查以查看是否有任何相邻簇的标签高于当前簇。还有第二个数组保存“正确的”簇标签。如果发现第 n 个相邻簇被正确标记,则将该元素分配给 0,否则将其分配给正确的标签(例如,如果第 n 个站点的标签为 2,并且邻居被标记为 3,则该元素的第 3 个元素被标记为 3)。 labelArray
设置为 2)。我有充分的理由这样做,老实说!
我想要的只是能够动态分配 labelArray
的第 n 个元素。我研究过可分配数组并将其声明为 labelArray(*)
但我并不真正理解这些,尽管搜索了网络和 StackOverflow。
因此,任何对此方面的帮助都会很棒。
My program is running though 3D array, labelling 'clusters' that it finds and then doing some checks to see if any neighbouring clusters have a label higher than the current cluster. There's a second array that holds the 'proper' cluster label. If it finds that the nth adjoining cluster is labelled correctly, that element is assigned to 0, otherwise is assigns it to the correct label (for instance if the nth site has label 2, and a neighbour is labeled 3, the 3rd element of the labelArray
is set to 2). I've got a good reason to do this, honest!
All I want is to be able to assign the nth element of the labelArray
on the fly. I've looked at allocatable arrays and declaring things as labelArray(*)
but I don't really understand these, despite searching the web, and StackOverflow.
So any help on doing this would be awesome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一个 Stack Overflow 问题,其中包含一些代码示例,显示了使用 Fortran 可分配数组的几种方法: 如何获取先前未知的数组作为 Fortran 中函数的输出:声明、分配、测试是否已分配,使用新的 move_alloc 和分配分配。未显示显式释放,因为示例使用 move_alloc 并在过程退出时自动释放。
PS 如果您想重复添加一个元素,您应该考虑您的数据结构方法。通过增长数组来一次添加一个元素并不是一种有效的方法。在 Fortran 中将数组从 N 个元素增加到 N+1 可能意味着创建一个新数组并复制所有现有元素。更合适的数据结构可能是链表。您可以通过创建用户定义类型并使用指针来在 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
Here is a Stack Overflow question with some code examples showing several ways of using Fortran allocatable arrays: How to get priorly-unkown array as the output of a function in Fortran: declaring, allocating, testing for being already being allocated, using the new move_alloc and allocation on assignment. Not shown there is explicit deallocation, since the examples are using move_alloc and automatic deallocation on exit of a procedure.
P.S. If you want to repeatedly add one element you should think about your data structure approach. Adding one element at a time by growing an array is not an efficient approach. To grow an array from N elements to N+1 in Fortran will likely mean creating a new array and copying all of the existing elements. A more appropriate data structure might be a linked list. You can create a linked list in Fortran by creating a user-defined type and using pointers. You chain the members together, pointing from one to the next. The overhead to adding another member is minor. The drawback is that it is easiest to access the members of the list in order. You don't have the easy ability of an array, using indices, to access the members in any order.
Info about linked lists in Fortran that I found on the web: http://www-uxsup.csx.cam.ac.uk/courses/Fortran/paper_12.pdf and http://www.iag.uni-stuttgart.de/IAG/institut/abteilungen/numerik/images/4/4c/Pointer_Introduction.pdf
如果声明数组可分配,则可以使用 real、
allocatable :: labelArray(:,:)
或
real,dimension(:,:),allocatable :: labelArray 形式的延迟形状
带有双冒号的数量,表示数组的排名(索引数量)。
如果数组未分配,则使用
正确数量的索引。例如,
allocate(labelarray(2:3,-1:5))
对于维度 1 中索引为 2 到 3 且维度 2 中索引为 -1 到 5 的数组。要更改维度,您必须取消分配 要将已分配的数组
重新分配到新形状,您首先需要使用新形状分配一个新数组,将现有数组复制到新数组,然后使用以下命令将旧数组的引用移动到新数组:
move_alloc()
。当通过
move_alloc()
移动新数组引用时,旧数组会自动释放。如果数组超出范围(例如子例程结束),Fortran 95 会自动释放数组。
Fortran 2008 有一个很好的功能,即分配时自动分配。如果您说 array1=array2 且 array1 未分配,则会自动分配它以具有正确的形状。
它还可以用于重新分配(另请参阅 Fortran 数组自动增长添加值时 和 如何在 Fortran 90 中向动态数组添加新元素)
If you declare an array allocatable, you use deffered shape in the form real,
allocatable :: labelArray(:,:)
, or
real,dimension(:,:),allocatable :: labelArray
with number of double colons meaning rank (number of your indexes) of your array.
If the array is unallocated you use
with the correct number of indexes. For example
allocate(labelarray(2:3,-1:5))
for array with indexes 2 to 3 in demension 1 and -1 to 5 in dimension 2.For change of dimension you have to deallocate the array first using
To reallocate an allocated array to a new shape you first need to allocate a new array with the new shape, copy the existing array to the new array and move the reference of the old array to the new array using
move_alloc()
.The old array is deallocated automatically when the new array reference is moved by
move_alloc()
.Fortran 95 deallocates arrays automatically, if they fall out of scope (end of their subroutine for example).
Fortran 2008 has a nice feature of automatic allocation on assignment. If you say
array1=array2
and array1 is not allocated, it is automatically allocated to have the correct shape.It can also be used for re-allocation (see also Fortran array automatically growing when adding a value and How to add new element to dynamical array in Fortran 90)
迟到的评论...检查 Fortran 90 的数值食谱。他们实现了一个很好的重新分配功能,并且符合 Fortran 90。在这种情况下,您的数组必须是指针属性,而不是可分配属性。
该函数接收旧数组和所需的大小,并返回指向调整大小的新数组的指针。
如果可能的话,请使用 Fortran 95 或 2003。如果 2003 不可能,那么 95 是一个很好的折衷方案。它提供了更好的指针语法。
Late comment... check Numerical Recipes for Fortran 90. They implemented a nice reallocate function that was Fortran 90 compliant. Your arrays must be pointer attributed in this case, not allocatable attributed.
The function receives the old array and desired size, and returns a pointer to the new resized array.
If at all possible, use Fortran 95 or 2003. If 2003 is impossible, then 95 is a good compromise. It provides better pointer syntax.
总结以上答案,在 Fortran 中增加可分配数组大小的最先进方法如下:
请注意,move_alloc 仅涉及复制内部描述符(而不是数组中的实际数据),因此指向的存储是相同的。
总之,move_alloc 提供了一种有效的方法来将数组重新分配到更大的大小,而无需复制数据两次(您只需复制数据一次)。也就是说,您需要抄入,但不需要抄出。
Summarizing the above answers, the state of art method of increasing size of an allocatable array in Fortran is as follows:
Note that
move_alloc
only involves copying the internal descriptors (not the acutal data in array), so that the storage pointed to is the same.In summary,
move_alloc
provides an efficient way to reallocate an array to a larger size without copying the data twice (you need to copy the data only once). That is, you need a copying in, but you do not need a copying out.