Community
cancel
Showing results for
Search instead for
Did you mean:
Highlighted
Beginner
11 Views

Loading parameters from a file and saving data

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

Tags (1)
10 Replies
Highlighted
Black Belt
11 Views

integer :: nx, ny, mystat

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)


Highlighted
Valued Contributor II
11 Views

Just one comment to clarify a

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

Highlighted
New Contributor III
11 Views

Hi Erez,

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

Highlighted
Beginner
11 Views

Thanks for the great replay

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

Highlighted
New Contributor III
11 Views

Hi Erez,

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

Highlighted
Valued Contributor II
11 Views

Hi Erez,

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

Highlighted
Valued Contributor III
11 Views

Quote:Erez K. wrote:

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.

Highlighted
Beginner
11 Views

Quote:FortranFan wrote:

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

Highlighted
Valued Contributor III
11 Views

Quote:Erez K. wrote:

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

Highlighted
Beginner
11 Views

FortranFan,

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