Fortran语言:试图更新在三维阵列粒子的位置时,分段故障 [英] Fortran: segmentation fault when trying to update particle position in 3-d array
问题描述
我写了一个程序来的粒子走动基于三维流场的3-D领域。不过,我在该行获得一个段错误,当我更新粒子位置,我不知道为什么!我在一个文件pviously写了这个程序$ P $,它工作得很好。但现在我得到分段错误时,我有一个模块中的所有函数/子程序。
编辑:我实现了以下的建议,现在分段故障从更新粒子线的地方,我打电话writeResults行移动。任何帮助仍然是AP preciated!
主要程序:
程序hw4Fortran
使用hw4_module
隐无 !定义类型
整数:: I,J,K,num_ts,num_particles,field_size_x,field_size_y,&安培;
field_size_z,num_arguments
类型(矢量),可分配:: VFIELD(:,:,:)
类型(矢量),可分配::粒子阵列(:)
字符(30):: out_file_basename,vel_file,part_file,文件名,string_num_ts !读取命令行
num_arguments = NARGS()
如果(num_arguments→1),然后
调用GETARG(1,string_num_ts)
读(string_num_ts,*)num_ts
其他
num_ts = 50
万一
如果(num_arguments→2)然后
调用GETARG(2,out_file_basename)
其他
out_file_basename =结果
万一
如果(num_arguments→3)然后
调用GETARG(3 vel_file)
其他
万一
如果(num_arguments→4),然后
调用GETARG(4,part_file)
其他
part_file =particles.dat
万一 !打开文件
开(单位= 1,文件= vel_file)
开(单位= 2,文件= part_file) !读粒子数
num_particles = readNumParticles(2) !调整为零指数
num_particles = num_particles - 1 !分配和阅读粒子阵列
粒子阵列= readParticles(2,num_particles) !读字段大小
field_size_x = readFieldSize(1)
field_size_y = readFieldSize(1)
field_size_z = readFieldSize(1) !调整为零指数
field_size_x = field_size_x - 1
field_size_y = field_size_y - 1
field_size_z = field_size_z - 1 !分配和读取矢量场
VFIELD = readVectorField(1,field_size_x,field_size_y,field_size_z) !移动粒子和写结果
做I = 0,num_ts
如果(模(I,10)== 0),则
写(文件名,FMT =(2A,I0.4,A)),TRIM(out_file_basename),_,我.DAT
开(单位= 3,文件=文件名)
万一
做J = 0,num_particles
如果(ⅰ大于0),那么
粒子阵列(J)= updateParticle(VFIELD(INT(FLOOR(粒子阵列(J)%X)),INT(FLOOR(粒子阵列(J)%Y)),INT(FLOOR(粒子阵列(J)%Z))),粒子阵列(J))
万一
如果(模(I,10)== 0),则
调用writeResults(3,粒子阵列(J))
万一
做到底
如果(模(I,10)== 0),则
接近(3)
万一
做到底 !关闭文件
关闭(1)
接近(2) !取消分配数组
DEALLOCATE(VFIELD)
DEALLOCATE(粒子阵列)程序结束hw4Fortran
模块:
模块hw4_module
隐无 矢量型
真正:: X,Y,Z
结束类型 包含
功能readNumParticles(FP)结果(num_particles)
整数:: FP,num_particles
阅读(FP,*)num_particles
最终功能 功能readParticles(FP,num_particles)结果(粒子阵列)
整数:: FP,num_particles,我
类型(矢量),可分配::粒子阵列(:)
分配(粒子阵列(0:num_particles))
做I = 0,num_particles
读(FP,*)粒子阵列(ⅰ)
做到底
最终功能 功能readFieldSize(FP)结果(field_size)
整数:: FP,field_size
阅读(FP,*)field_size
最终功能 功能readVectorField(FP,field_size_x,field_size_y,&安培;
field_size_z)结果(VFIELD)
整数:: FP,field_size_x,field_size_y,field_size_z,I,J
类型(矢量),可分配:: VFIELD(:,:,:)
分配(VFIELD(0:field_size_x,0:field_size_y,0:field_size_z))
做I = 0,field_size_x
做J = 0,field_size_y
读(FP,*)VFIELD(I,J,:)
做到底
做到底
最终功能 功能updateParticle(速度,old_particle)结果(new_particle)
类型(矢量):: new_particle,old_particle,速度
new_particle%X = old_particle%X +速度%×
new_particle%Y = old_particle%Y +速度%Y
new_particle%Z = old_particle%Z +速度%Z
最终功能 子程序writeResults(FP,颗粒)
整数:: FP
类型(矢量)::粒子
写(FP,*)颗粒%X,粒子%Y,粒子%Z
结束子程序前端模块
此功能
函数readParticles(FP,num_particles)结果(粒子阵列)
整数:: FP,num_particles,我
类型(矢量),可分配::粒子阵列(:)
分配(粒子阵列(0:num_particles))
做I = 0,num_particles
读(FP,*)粒子阵列(ⅰ)
做到底
最终功能
中分配粒子阵列
与索引值 0:num_particles
。不幸的是,这许多新人人次最多的Fortran(一些oldcomers太),这些数组边界不会传递到调用code将愉快地在 1 $假设索引范围起点C $ C>。然后code继续访问
粒子阵列(0)
...和约翰乙警告出现的问题。
Fortran语言的从任意一个整数值数组索引的能力从来就因为它似乎是有用的。您可以通过边界进入和退出过程,但谁又能困扰?容易只是pretend从 1
Fortran数组的索引和应用,始终贯穿的程序。
I've written a program to move around particles in a 3-D field based on a 3-D velocity field. However, I get a segmentation fault at the line when I update the particle positions, and I have no idea why! I wrote this program previously in a single file, and it worked fine. But now I'm getting the segmentation fault error when I have all the functions/subroutines in a module.
Edit: I implemented the suggestions below, and now the segmentation fault has moved from the update particle line to the line where I call writeResults. Any help is still appreciated!
Main Program:
program hw4Fortran
use hw4_module
implicit none
!Define types
integer::i ,j, k, num_ts, num_particles, field_size_x, field_size_y, &
field_size_z, num_arguments
type(vector),allocatable::vfield(:,:,:)
type(vector),allocatable::parray(:)
character(30)::out_file_basename, vel_file, part_file, filename, string_num_ts
!Read command line
num_arguments = NARGS()
if (num_arguments > 1) then
call GETARG(1, string_num_ts)
read(string_num_ts, *) num_ts
else
num_ts = 50
end if
if (num_arguments > 2) then
call GETARG(2, out_file_basename)
else
out_file_basename = "results"
end if
if (num_arguments > 3) then
call GETARG(3, vel_file)
else
end if
if (num_arguments > 4) then
call GETARG(4, part_file)
else
part_file = "particles.dat"
end if
!Open files
open(unit=1, file=vel_file)
open(unit=2, file=part_file)
!Read number of particles
num_particles = readNumParticles(2)
!Adjust for zero index
num_particles = num_particles - 1
!Allocate and read particle array
parray = readParticles(2, num_particles)
!Read field size
field_size_x = readFieldSize(1)
field_size_y = readFieldSize(1)
field_size_z = readFieldSize(1)
!Adjust for zero index
field_size_x = field_size_x - 1
field_size_y = field_size_y - 1
field_size_z = field_size_z - 1
!Allocate and read vector field
vfield = readVectorField(1, field_size_x, field_size_y, field_size_z)
!Move particles and write results
do i=0,num_ts
if (mod(i,10) == 0) then
write(filename, fmt = "(2A, I0.4, A)") trim(out_file_basename), "_", i, ".dat"
open(unit = 3, file=filename)
end if
do j=0, num_particles
if (i > 0) then
parray(j) = updateParticle(vfield(INT(FLOOR(parray(j)%x)),INT(FLOOR(parray(j)%y)),INT(FLOOR(parray(j)%z))), parray(j))
end if
if (mod(i,10) == 0) then
call writeResults(3, parray(j))
end if
end do
if (mod(i,10) == 0) then
close(3)
end if
end do
!Close files
close(1)
close(2)
!Deallocate arrays
deallocate(vfield)
deallocate(parray)
end program hw4Fortran
Module:
module hw4_module
implicit none
type vector
real::x,y,z
end type
contains
function readNumParticles(fp) result(num_particles)
integer::fp, num_particles
read(fp, *) num_particles
end function
function readParticles(fp, num_particles) result(parray)
integer::fp, num_particles, i
type(vector),allocatable::parray(:)
allocate(parray(0:num_particles))
do i=0, num_particles
read(fp, *) parray(i)
end do
end function
function readFieldSize(fp) result(field_size)
integer::fp, field_size
read(fp, *) field_size
end function
function readVectorField(fp, field_size_x, field_size_y, &
field_size_z) result(vfield)
integer::fp, field_size_x, field_size_y, field_size_z, i, j
type(vector),allocatable::vfield(:,:,:)
allocate(vfield(0:field_size_x,0:field_size_y,0:field_size_z))
do i=0, field_size_x
do j=0, field_size_y
read(fp, *) vfield(i,j,:)
end do
end do
end function
function updateParticle(velocity, old_particle) result(new_particle)
type(vector)::new_particle,old_particle,velocity
new_particle%x = old_particle%x + velocity%x
new_particle%y = old_particle%y + velocity%y
new_particle%z = old_particle%z + velocity%z
end function
subroutine writeResults(fp, particle)
integer::fp
type(vector)::particle
write(fp, *) particle%x, " ", particle%y, " ", particle%z
end subroutine
end module
This function
function readParticles(fp, num_particles) result(parray)
integer::fp, num_particles, i
type(vector),allocatable::parray(:)
allocate(parray(0:num_particles))
do i=0, num_particles
read(fp, *) parray(i)
end do
end function
allocates parray
with index values 0:num_particles
. Unfortunately, and this trips up many a newcomer to Fortran (some oldcomers too), those array bounds are not passed out to the calling code which will blithely assume an index range starting at 1
. And then the code goes on to access parray(0)
... and the problem that John B warns of arises.
Fortran's capability of indexing arrays from an arbitrary integer value is never quite as useful as it seems. You can pass the bounds into and out of procedures, but who can be bothered ? Easier just to pretend that Fortran arrays index from 1
and apply that consistently throughout a program.
这篇关于Fortran语言:试图更新在三维阵列粒子的位置时,分段故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!