segmentation error in linux for ansys

2020-04-23 08:18发布

问题:

I am writting a usersubroutine using Fortran (Intel Composer (2011.1.107)) for ANSYS14.5.7 I have edited the code to write some data into an external sequential file and read them to an array for calculations as follows:

c Writes the array elements into the relevent elementID file and Integration point
   Do ElementNo=1,MaxEleNo
c writes the file name for the relevent element
   write (filename1, '( "Element_", I4)' )  ElementNo 
c opens the relevent file for the element data  
   OPEN(unit=ElementNo,status='unknown',ACCESS='APPEND'
 & ,file=filename1)    
   Write(ElementNo,fmt='(*(D))')(sthistory(ElementNo,:))
   close (ElementNo)
  end do
  sthistory=ZERO
  else
  endif

When I run this I get this error from the HPC system:

Lyra: Ansys (v14.5.7) loaded.
Lyra: Intel Composer (2011.1.107) module loaded.
/pkg/suse11/ansys/v145/ansys/bin/ansys145: line 817: 50102 Segmentation fault           /pkg/suse11/ansys/v145/ansys/bin/linx64/ansys.e145 -np 4

But no problem with the code when I run with a static array with save attribute in the subroutine. But this is not suffiecient to hold all the data in my calculations. Can someone help me to find what can be the prob.

回答1:

Low unit numbers are typically reserved for "special units" like STDOUT, STDERR, STDIN. Do not use these (unless you know what you are doing), or something unexpected might happen. I'm mildly aware that there is some upper limit for unit numbers, but I can't find a reference at the moment.

So the easiest way to solve your problem would be to add an offset to the unit (which again would lead to problems for large arrays), or use newunit= if your compiler supports it. But since you close the files at the end of the loop body, way not use a fixed number like 1234?

But you have more issues with your code: The line

write (filename1, '( "Element_", I4)' )  ElementNo

will lead to problems (for most compilers).

Consider this simple program:

program test
  write (*, '( "Element_", I4)' )  1
  write (*, '( "Element_", I4)' )  10
  write (*, '( "Element_", I4)' )  100
  write (*, '( "Element_", I4)' )  1000
  write (*, '( "Element_", I4)' )  10000
end program

The output is:

Element_   1
Element_  10
Element_ 100
Element_1000
Element_****

Which leads to a file name that contains spaces. This might lead to an error! What you could do is change the format specifier to use a fixed length by using '( "Element_", I4.4)', which would give you:

Element_0001
Element_0010
Element_0100
Element_1000
Element_****

You can see that four digits is still too small to hold the larger elements, but no spaces any more.

Finally, if you wanted the numbers to start after the slash directly without the leading zeros you could use a combination of adjustl() and trim():

program test
  character(len=32)  :: filename

  write (filename, '(I4)')  1
  filename = "Element_" // adjustl(trim(filename))
  write(*,'(a)') filename
  write (filename, '(I4)')  10
  filename = "Element_" // adjustl(trim(filename))
  write(*,'(a)') filename
  write (filename, '(I4)')  100
  filename = "Element_" // adjustl(trim(filename))
  write(*,'(a)') filename
end program

results in

Element_1                       
Element_10                      
Element_100  


标签: linux fortran