Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Loading parameters from a file and saving data

Erez_K_1
Beginner
1,480 Views

Hello,

I am working on a solver that has a large number of input parameters that I would like to load from a file. One issue I though I would have is that the size of some arrays are defined by said input. 

Eventually my program solves some distribution function (some n_x by n_v matrix) that I would like to save to a file as well.

Any ideas whats the best to do that on the Windows compiler? 

example code

program test_1

implicit none

real , parameter :: alpha=1

integer , parameter :: n_x=10

integer , parameter :: n_v=10

real,dimension(n_x,n_v) :: f

integer :: i, j

do i=1,n_x

do j =1,n_v

f(i,j)= i*j

end do

end do

end program

 

Here is where I want to save f to an external file for some farther analysis.

Thanks!

Best,

Erez

0 Kudos
10 Replies
mecej4
Honored Contributor III
1,480 Views
integer :: nx, ny, mystat
real, dimension(:,:), allocatable :: f
..
open(11,file='my.dat',status='old')
read(11,*)nx,ny
close(11)
! check if nx and ny are reasonable
allocate(f(nx,ny,status=mystat)
! check if allocation succeeded
! do calculations
open(12,file='my.res',status='replace')
write(12)nx,ny,f
close(12)

 

0 Kudos
Les_Neilson
Valued Contributor II
1,480 Views

Just one comment to clarify a little something (for others who may not realise).

Because n_x and n_v are "parameters" they are compile time constants and not variables, so their value cannot be changed during program execution.

If the values need to be set at run time then they need to be variables. First read the file containing these values, allocate the arrays as necessary, and proceed with the computation.

That way problems of different size can be run by using different input files and no need to recompile the program.

Les

0 Kudos
Johannes_Rieke
New Contributor III
1,480 Views

Hi Erez,

in case there is more than one matrix or multiple input data (control, output, plot, etc.), I think a container format such as XML, JSON (Fortran Interface e.g. https://github.com/jacobwilliams/json-fortran), HDF5 or whatever could be helpful and make it more user friendly and flexible. If you just need a very small amount of data a self made structure would do it.

A simple version I prefer:

# some comment
*my_data_type_keyword
{
0.1 0.2
0.3 0.4
}
# second data entry
*my_2nd_data_type_keyword
42
#
*my_output_file
'control.log'

With some little parsing you can also avoid to give explicitly the matrix dimensions. Non-matching matrix dimensions normally generates ugly errors...

Johannes

0 Kudos
Erez_K_1
Beginner
1,480 Views

Thanks for the great replay guys,

One quick questions.

If I  use the method described in the first reply, do I simply need to put the input file 11 (this is simply a text file right?) in the same folder as my solution?

Also, I simply need to put the value for each variable in a different line in that file right? As such

content of file 11.text (for two variables)

30

40

end of file

Also, the Fortran solution will make me a new file with my results right? (12.text) I wouldn't need to make a file in the folder with that name?

Last question, I will need to save my matrix f through the calculation as well. I am interested in how it evolves as well as its final state. Would a text file be a good way to do this? or is there a better format? I want to take it to MATLAB for plotting later. 

Thanks,

Erez

0 Kudos
Johannes_Rieke
New Contributor III
1,480 Views

Hi Erez,

I would look into the documentation for I/O with Fortran. The help for write contains some more examples and show how to write 'formatted' ASCII or binary files. The latter would be an option for intermediate big files, Matlab can read Fortran binary data files. Fixed units (11) should not be used anymore, since newunit is an elegant alternative IMHO.

You can also work with sub-folders etc. (e.g. changedirqq or by giving the path in the file statement in the open command).

Regards, Johannes

0 Kudos
Les_Neilson
Valued Contributor II
1,480 Views

Hi Erez,

The values don't have to be on separate lines. With an appropriate format on the READ statement you can read several values at one go.

As regards the output file: it depends on what your program does.

You should look at the help on OPEN, READ, WRITE and FORMAT (the Fortran I/O) statements as Johannes suggests.

Les

0 Kudos
FortranFan
Honored Contributor II
1,480 Views

Erez K. wrote:

.. If I  use the method described in the first reply, do I simply need to put the input file 11 (this is simply a text file right?) in the same folder as my solution? .. Last question, I will need to save my matrix f through the calculation as well. I am interested in how it evolves as well as its final state. Would a text file be a good way to do this? or is there a better format? I want to take it to MATLAB for plotting later.  ..

@Erez,

Perhaps it will be helpful if you can provide some background about yourself, what are you to trying to do, and how far you want to "take it" as far "software engineering" for your work is concerned.  On one hand, you're asking very basic questions which are well-covered in many Fortran sources including books, on the other hand it's unclear you're even making use of material readily available at your fingertips such as Intel Fortran User and Reference Guide, but then there is need for systems integration such as making use of MATLAB which can be quite simple for those "in the know" but for some who don't "read up by themselves", it can be umpteen posts on online forums all over.  Given the lack of clarity of your situation, suggestions such as using JSON and XML may just the right thing you need or they may be "a sledgehammer to crack a nut".

Say your need is to do fairly simple stuff that invidiual coders often do (as opposed to a team of professional developers building some big, software) and you seek a Fortran-only situation.   In that case, look into Fortran standard NAMELIST feature: https://software.intel.com/en-us/node/580891

Per your original post, you indicate simulation parameters such as n_x and n_y and simulation data such as f.  In that event, you might find it easy to create an input file for your calculations in human-readable and understandable format such as this:

 &sim_params
    n_x=2,
    n_y=3,
/
 &sim_data
    f=1.0,2.0,3.0,4.0,5.0,6.0,
/

You can create a Fortran program, say mysim.exe, and run it with standard Windows command prompt action such as mysim xxx\in.txt yyy\out.txt where xxx is the folder path for your input file and yyy is the folder path for your simulation output.  This addresses your other question of where the files need be located; they can be anywhere, as long the location is accessible to the Fortran program.  Example code to do so is given below, hopefully it is self-explanatory.

module m

   implicit none

   private

   !.. "Simulation" parameters
   integer :: n_x = 0
   integer :: n_y = 0

   !.. "Simulation" data
   real, allocatable :: f(:,:)

   !.. I/O variables
   namelist /sim_params/ n_x, n_y
   namelist /sim_data/ f
   logical :: FileExists
   integer :: FileUnit
   character(len=256) :: msg

   !.. Public methods
   public :: ReadData
   public :: RunSimulation
   public :: WriteData

contains

   subroutine ReadData( FileName, ErrorCode, ErrorMessage )

      !.. Argument List
      character(len=*), intent(in)    :: FileName
      integer, intent(inout)          :: ErrorCode
      character(len=*), intent(inout) :: ErrorMessage

      !.. Local variables
      integer :: I

      !..
      ErrorCode = 0
      ErrorMessage = ""

      inquire( file=FileName, exist=FileExists)

      if ( FileExists ) then

         open( newunit=FileUnit, file=FileName, status="old", iostat=ErrorCode, iomsg=msg )
         if ( ErrorCode /= 0 ) then
            !.. Error handling elided
            ErrorMessage = msg
            return
         end if
         read( unit=FileUnit, nml=sim_params, iostat=ErrorCode, iomsg=msg )
         if ( ErrorCode /= 0 ) then
            !.. Error handling elided
            ErrorMessage = msg
            return
         end if
         if ( (n_x <= 0).or.(n_y <=0 ) ) then
            !.. Invalid data; error handling elided
            msg = "Invalid values for n_x/n_y in input file."
            ErrorCode = 2
            return
         end if

         !.. Proper action elided; here the "simulation data" is allocated
         f = reshape( source=[( 0.0, I=1,n_x*n_y)], shape=[ n_x, n_y ] )

         !.. Then read the data in from the file
         read( unit=FileUnit, nml=sim_data, iostat=ErrorCode, iomsg=msg )
         if ( ErrorCode /= 0 ) then
            !.. Error handling elided
            ErrorMessage = msg
            return
         end if

      else
         !.. Error handling elided
         ErrorCode = 1
         msg = "Input file cannot be found."
         ErrorMessage = msg
         return
      end if

      !..
      return

   end subroutine ReadData

   subroutine RunSimulation( ErrorCode, ErrorMessage )

      !.. Argument List
      integer, intent(inout) :: ErrorCode
      character(len=*), intent(inout) :: ErrorMessage

      !.. Local variables

      !..
      ErrorCode = 0
      ErrorMessage = ""

      !.. Proper action elided; here the action is simply to add 42 to existing data!
      f = f + 42.0

      !..
      return

   end subroutine RunSimulation

   subroutine WriteData( FileName, ErrorCode, ErrorMessage )

      !.. Argument List
      character(len=*), intent(in)    :: FileName
      integer, intent(inout)          :: ErrorCode
      character(len=*), intent(inout) :: ErrorMessage

      !.. Local variables

      !..
      ErrorCode = 0
      ErrorMessage = ""

      !.. Appropriate action elided; here any existing file is overwritten
      open( newunit=FileUnit, file=FileName, status="replace", iostat=ErrorCode, iomsg=msg )
      if ( ErrorCode /= 0 ) then
         !.. Error handling elided
         ErrorMessage = msg
         return
      end if
      !.. Add "simulation parameters" to file in NAMELIST format
      write( unit=FileUnit, nml=sim_params, iostat=ErrorCode, iomsg=msg )
      if ( ErrorCode /= 0 ) then
         !.. Error handling elided
         ErrorMessage = msg
         return
      end if
      !.. Add "simulation data" to file in NAMELIST format
      write( unit=FileUnit, nml=sim_data, iostat=ErrorCode, iomsg=msg )
      if ( ErrorCode /= 0 ) then
         !.. Error handling elided
         ErrorMessage = msg
         return
      end if

      !..
      return

   end subroutine WriteData

end module m
program p

   use, intrinsic :: iso_fortran_env, only : output_unit
   use m, only : ReadData, RunSimulation, WriteData

   implicit none

   integer :: irc
   integer :: leni
   integer :: leno
   integer :: numargs
   character(len=2048) :: errtxt
   character(len=256) :: InputFile
   character(len=256) :: OutputFile

   NumArgs = command_argument_count()
   if ( NumArgs > 0) then

      call get_command_argument(1, InputFile, leni, irc)
      if (irc /= 0) then
         write( unit=output_unit, fmt='(*(g0))' ) "Error processing first argument."
         stop
      end if

      if (numargs > 1) then

         call get_command_argument(2, OutputFile, leno, irc)
         if (irc /= 0) then
            write( unit=output_unit, fmt='(*(g0))' ) "Error processing first argument."
            stop
         end if

      end if

   end if

   call ReadData( FileName=InputFile, ErrorCode=irc, ErrorMessage=errtxt  )
   if (irc /= 0) then
      write( unit=output_unit, fmt='(*(g0))' ) "ReadData failed: ", trim(errtxt)
      stop
   end if

   call RunSimulation( ErrorCode=irc, ErrorMessage=errtxt  )
   if (irc /= 0) then
      write( unit=output_unit, fmt='(*(g0))' ) "RunSimulation failed: ", trim(errtxt)
      stop
   end if

   call WriteData( FileName=OutputFile, ErrorCode=irc, ErrorMessage=errtxt  )
   if (irc /= 0) then
      write( unit=output_unit, fmt='(*(g0))' ) "WriteData failed: ", trim(errtxt)
      stop
   end if

   stop

end program

Upon execution with Intel Fortran, the above code creates an output:

 &SIM_PARAMS
 N_X     = 2,
 N_Y     = 3
 /
 &SIM_DATA
 F       = 43.00000       , 44.00000       , 45.00000       , 46.00000       , 47.00000       , 48.00000       
 /

The above output can now be read back by the Fortran program since it is in a supported format.  Also, by encapsulating the "ReadData" procedure suitably and which is then invoked by MATLAB, the data can be loaded into MATLAB as well.

Clearly the above is but one simple "standard" and all Fortran solution; some may call it a "poor man" approach.  For more extensive and/or sophisticated needs, other approaches can be used including JSON, XML, etc.

0 Kudos
Erez_K_1
Beginner
1,480 Views

FortranFan wrote:

@Erez,

Perhaps it will be helpful if you can provide some background about yourself, what are you to trying to do, and how far you want to "take it" as far "software engineering" for your work is concerned.  On one hand, you're asking very basic questions which are well-covered in many Fortran sources including books, on the other hand it's unclear you're even making use of material readily available at your fingertips such as Intel Fortran User and Reference Guide, but then there is need for systems integration such as making use of MATLAB which can be quite simple for those "in the know" but for some who don't "read up by themselves", it can be umpteen posts on online forums all over.  Given the lack of clarity of your situation, suggestions such as using JSON and XML may just the right thing you need or they may be "a sledgehammer to crack a nut".

Say your need is to do fairly simple stuff that invidiual coders often do (as opposed to a team of professional developers building some big, software) and you seek a Fortran-only situation.   In that case, look into Fortran standard NAMELIST feature: https://software.intel.com/en-us/node/580891

Per your original post, you indicate simulation parameters such as n_x and n_y and simulation data such as f.  In that event, you might find it easy to create an input file for your calculations in human-readable and understandable format such as this:

 

 

Hey, I am an undergraduate physics major working on a research project.  I am moving a code I collaborated on from MATLAB to Fortran to decrease the computational time.  I am a beginner/novice in MATLAB but I have never really coded, lucky  the code is not to complicated. 

The program is designed to solve a PDE, specifically the Vlasov-Poisson set of equations. The evolving function is some density distribution function with a known inital shape. 

I have a code which compiles, and I would like to input data to it (without compiling each time) and save a file with the 100 "pictures" of the  time evolution of the distribution function. The code is about 300 lines. Thanks for all the tips.  I will try to implement them.

I hope this explanation is sufficient and your efforts could be focused. 

Appreciate all the helpful replays and remarks. 

Best,

ERez

0 Kudos
FortranFan
Honored Contributor II
1,480 Views

Erez K. wrote:

.. I am an undergraduate physics major working on a research project.  ..

So are you a student now?  Or recently where one?  Assuming as such and depending on your immediate and long-term goals, you may want to consider following a more structured approach toward picking up Fortran, one that a current or a recent student will be used to, by reviewing closely the books mentioned in this Dr Fortran blog https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world.

0 Kudos
Erez_K_1
Beginner
1,480 Views

FortranFan,

I am a current student, graduating in a month or so. I am working on this solver for my senior TheSis. 

I am interested in "diving" deeper into Fortran in the coming year but  at this specific moment in time I just want to make this project work.

Best,

Erez

0 Kudos
Reply