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

Data from two .txt files

mechprog
Beginner
1,072 Views
Hello,

I have data from two text files (see attached) and I will like find the average for numbers in file and one and the average for numbers in file 2 and then do the following calculation

(Average from file 1) - (Average from file 2)

This may sound very simple, however I am new to fortran and I have been unable to find a similar example in books or online.

I would really appreciate some help or a similar example.

Thanks
0 Kudos
12 Replies
andi_zuend
Beginner
1,072 Views

Hi mechprog,

For that task you will need to read the contents of the two files into Fortran arrays and then you can perform whatever operation you like on the data. Hence, use the OPEN command to read the data (see the Fortran help); here it is best to put it in allocatable arrays so that you can fit the size of the arrays to the number of lines in your input files in a flexible way (i.e., check for end-of-file (EOF) while reading the data from the files).

Best,

Andi

0 Kudos
Steven_L_Intel1
Employee
1,072 Views
You don't have to read into an array. Read values from one file, add them up, then divide the sum by the number of values read. Repeat for the other. Very simple scalar code - can probably be done in a dozen lines or so.
0 Kudos
Les_Neilson
Valued Contributor II
1,072 Views

declare your variables.
open file1
initialize sum1 to zero
initialize counter1 to zero
read file1 into value1 don't forget to handle end of file (and possibly an error situation).
add value1 to sum1
increment counter1
go back to read file1 ("read" to "go back" could be done using a do-enddo loop)

at end of file1:
calculate average1 from sum1 and counter1

repeat for file2, sum2, counter2 and average2

calculate difference between average1 and average2

Les

0 Kudos
mechprog
Beginner
1,072 Views

Thanks everyone,

I would also like to take the callfirst value in each of the files, I have tried doing this with the following code:

[fxfortran]      DOUBLE PRECISION U11(1)
c Read the U value
c     Open the data file and write
      open(UNIT=51,FILE='C:Num1.txt', STATUS='OLD')
c
      Do 15 N=1
        read(51,*) U11(1)
   15 Continue
c   20 Format(*)
      close(51)[/fxfortran]



At run time I receive the following error message
forrtl: severe (24): end-of-file during read, unit 51......

Thanks

0 Kudos
Steven_L_Intel1
Employee
1,072 Views
This reads like school homework. Is it? You will want to read your Fortran textbook about the END= and IOSTAT= specifiers in the READ statement.
0 Kudos
mechprog
Beginner
1,072 Views

Thanks Steve,

I can understand why it may seem like school work, I appreciate these must seem like such basic and simple questions. This work is for research.I am just finding using Fortran challenging at the moment and I am finding very very few groups for support. I have around 4 books which I use for reference and Intel Fortran Guides and manuals. I just feel that getting some help from experts in programming and Fortran will help me to learn from experts and professionals.

It seems to be getting very messy with all these files. Perhaps it may be that I could use modules or common blocks to store and call my data instead.

Is it ok to use modules to store and call data even though the rest of my code is in Fortran 77 syntax and Fixed format?

Thanks for your help and understanding, sorry if the level is not of the required for this forum.

0 Kudos
Steven_L_Intel1
Employee
1,072 Views
You are welcome to ask here and we're glad to help. It's just that we often get students coming here asking us to write their assignments for them and your program is exactly the sort I'd expect from an introductory Fortran programming class.

I don't understsand your comment about "all these files". You have only one program source file so far. As for modules, etc. - your "Fortran 77 syntax" is also Fortran 2008 syntax. Fixed format is still part of the standard, though it is "deprecated". You can use any modern Fortran feature the compiler supports in either source form.

There are two ways of detecting that you have come to the end of a data file. The old way is to use END= with a label of a statement to jump to when the end is reached. One can also use IOSTAT=, naming an integer variable, and you then test the variable to see if it is non-zero, indicating some sort of non-success condition. While IOSTAT is more "modern", using it also means you should, ideally, add code to distinguish between end-of-file (a negative value) and an error (positive value). Using END= allows you to let the system report errors while handling end-of-file fine.

Now let me comment on the code you posted, as it has some errors:

[fxfortran]      Do 15 N=1
        read(51,*) U11(1)
   15 Continue
c   20 Format(*)[/fxfortran]
The DO statement here is not the form you want, and what you have written is not valid. This form of DO requires an end value, such as:

DO 15 N=1,10

Since you don't know how many values you have, you can't do that. Also, the use of a labeled CONTINUE is not good modern practice - you should use the "block" form with END DO instead.

Next, you need to count the values and don't need an array. The count should be incremented each time you successfully read a value, and then you need to add it to the running sum, which you have not shown.

You have a commented out FORMAT statement - use of a * format in the READ is fine - that means "list-directed formatting" where the input form is flexible. This does not require a separate FORMAT and indeed a format of (*) is not valid.

Here is a rewrite of your code that would compute the average of values in one file. You can probably figure out how to extend this to your full program:

[plain]IMPLICIT NONE
REAL(SELECTED_REAL_KIND(10)) :: SUM, X, AVG
INTEGER NVALS,IOS

OPEN (UNIT=1,FILE='C:NUM1.TXT',STATUS='OLD')

SUM = 0.0
NVALS = 0
DO
  READ (1,*,IOSTAT=IOS) X
  IF (IOS /= 0) EXIT
  NVALS = NVALS + 1
  SUM = SUM + X
  END DO
AVG = SUM / NVALS
PRINT *, AVG
END[/plain]
I've used the following language features:
  • Used IMPLICIT NONE because I recommend you always use this
  • Used free-form source
  • Declared the real variables using the standard SELECTED_REAL_KIND intrinsic, asking for a type with at least 10 decimal digits of precision.
  • Used scalars as you don't need arrays
  • Used the "infinite loop" form of DO that doesn't end until something in the loop breaks out
  • Used IOSTAT to get the status of reading the single value, exiting the loop if the read did not succeed. /= is the same as .NE.

I used all caps here but you can use mixed or lowercase if you want.

I hope this helps.


0 Kudos
mechprog
Beginner
1,072 Views
Thank you Very much for everyones help and support, this really has helped me to improve my skills with Fortran and help to solve my engineering problem.

I could not find any information on the standard and best practice for having two subroutines in one file and to ensure that this is read correctly. The second subroutine will need to call from some information which has been coded in the first subroutine.

Would this following method be correct?

[fxfortran]Subroutine One(args)

... CODING

Return
End Subroutine One

Subroutine Two(args)

... CODING

Return
End Subroutine Two

END[/fxfortran]

I would like to ensure I am using good andcorrect methodology and practice for doing this and future projects. The reason I ask, is because I am not 100% confident that the compiler is recognising the second subroutine in the file.

Thank-you
0 Kudos
mecej4
Honored Contributor III
1,072 Views
Subroutines are independent, and whether you have more than one in the same file is almost immaterial.

>The second subroutine will need to call from some information which has been coded in the first subroutine.

That is close to meaningless, and the skeleton code that you showed does not display any connection between the two subroutines. You can call subroutines. You cannot call information. If you do not call a subroutine, the code in that subroutine will not be executed, and a compilation system is allowed to eliminate "dead" code.

> I could not find any information on the standard and best practice

Look again.
0 Kudos
bmchenry
New Contributor II
1,072 Views
you can include all subroutines in one file, or use a separate file for each subroutine.
it doesn't matter.
i would recommend having separate files for each subroutine so then then changing a subroutine you are editinga file.
likewise when compiling after a change to a subroutine the compiler only has to recompile the routine that has been changed rather than all the subroutines (if they are all in a single file)
0 Kudos
Arjen_Markus
Honored Contributor I
1,072 Views
As mecej4 points out, your terminology is a bit awkward. Let me try and clarify this:

Suppose you have a subroutine suba that calls a second subroutine:

subroutine suba( ... )
... declarations ...

call subb( ... proper argument list ...)
end subroutine suba

And subb simply performs some computation.

Then:
- If the interface to subb is explicit, the compiler can check the argument list by which you
call subb in subroutine suba.
- The interface for a routine is always explicit if you put it in a module. There are other ways
in which you can make it explicit, but it is good practice to put your subroutines and other
Fortran code in modules as much as possible - then you do not have to worry about these
matters.
- If the interface for routine subb is unknown at the moment the compiler compiles suba,
it will assume that the argument list is correct and that it contains no other features than
those compatible with FORTRAN 77. If that assumption is in any way incorrect, you are
bound to get problems. Hence the use of modules.
- Whether the code for these routines is in one and the same file or not, does not really
matter to the compiler. It does matter to the linker, but that is a different story.

(I agree that these very practical issues are not dealt with in much detail, as they have
little to do with the language perse. I do not know of a good tutorial for it either. They
probably do exist, though.)

Regards,

Arjen
0 Kudos
Les_Neilson
Valued Contributor II
1,072 Views
Further to what others have suggested.
If you mean that the two (or more) subroutines need to share data then another technique you may want to consider is using modules. Put related data and subroutines in one module file.
For example

module mymod1
implicit none

! My data goes here
integer
real
character
etc.

contains
! Data processing routines
subroutine suba
! does stuff with some of my data
end subroutine suba

subroutine subb
! does different stuff wiht my data
end subroutine subb

! Data Get/Set routines
subroutine getavalue(x)
! assigns something from my data to x
end subroutine getavalue

subroutine setavalue(y)
! assigns y to some variable in my data
end subroutine setavalue

etc.
end module mymod1

then in some other routine / main program

subroutine foo
using mymod1
! do stuff
call setavalue(u)
call suba
call getavalue(v)
end subroutine foo

There are numerous advantages to using modules not least of which is providing interface checking for you (have you got the right data types in the calls for instance)

HTH
Les
0 Kudos
Reply