Fortran语言:试图更新在三维阵列粒子的位置时,分段故障 [英] Fortran: segmentation fault when trying to update particle position in 3-d array

查看:267
本文介绍了Fortran语言:试图更新在三维阵列粒子的位置时,分段故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个程序来的粒子走动基于三维流场的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 。然后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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆