Output file contains extra zeros - file-io

I have a little problem with this simple Fortran program
PROGRAM Calc_U0
Implicit None
real, dimension(:,:), allocatable :: x,y
integer :: n=16589,m=9,nm=6,I,J,r
open (unit = 7, file = "U0.txt")
open (unit=99, file='slice06.txt', status='old', action='read')
allocate(x(n,m))
allocate(y(n,nm))
do I=1,n
read(99,*,END=71) x(I,:)
enddo
71 do I=1,n
print*,I
do J=1,n
if(I/=J) then
!! if(x(I,1)==x(J,1)) then
if(x(I,2)==x(J,2)) then
if(x(I,3)==-x(J,3)) then
y(I,1)=x(I,1)
y(I,2)=x(I,2)
y(I,3)=x(I,3)
y(I,4)=(x(I,7)+x(J,7))/2
y(I,5)=(x(I,8)+x(J,8))/2
y(I,6)=(x(I,9)+x(J,9))/2
write(7,*) (y(I,r),r=1,6)
endif
endif
!!endif
endif
enddo
enddo
END PROGRAM Calc_U0
Everything seems to work fine, until I look at file U0.txt. This file contains my result plus other rows of zeros (millions), with a size of 6.4 GB. But I do not understand where the bug is, because if I read less than 8000 rows this problem disappear. I'm on Linux with gfortran compiler.

It doesn't matter how many rows you read; your loops still go from 1 through 16589. Perhaps you should change n in those loops to be the actual number of rows you read.

Related

Read(u=UNIT,*) reads just half the file in fortran

so I'm trying to make a Fortran subroutine that reads a matrix (or a tensor I guess) of size 125x125x125 from a file that I create in another subroutine, but for some reason it doesn't work. I have successfully done it using almost the same program but for a different size of matrix (70x200x70) and for some reason when I change the size of the arrays and a couple of other things to fit the new data, the program reads just half the data file and throws an error that says At line 133 of file Busqueda.f90 (unit = 2, file = 'test2.txt') Fortran runtime error: End of file. So my working code is:
Subroutine DataSorting(datasort,indexsort,datosden,datostemp)
use globals
implicit None
real*8, dimension(70,200,70) :: datosdentemp
real*8, dimension(70,200,70), intent(out) :: datostemp, datosden
real*8, dimension(980000), intent(out) :: datasort
integer,dimension(3,980000),intent(out) :: indexsort
integer, dimension(3) :: Result
integer :: i
rewind(2)
read(2,*) datosden
datosdentemp = datosden
rewind(3)
read(3,*) datostemp
do i = 1, 10
Result = MAXLOC(datosdentemp)
datasort(i) = datosden(Result(1),Result(2),Result(3))
indexsort(1,i) = Result(1)
indexsort(2,i) = Result(2)
indexsort(3,i) = Result(3)
datosdentemp(Result(1),Result(2),Result(3)) = 0
end do
End Subroutine DataSorting
And the code that dont work is:
Subroutine DataSorting(datasort,indexsort,datosden,datostemp)
use globals
implicit None
real*8, dimension(125,125,125) :: datosdentemp
real*8, dimension(125,125,125), intent(out) :: datostemp, datosden
real*8, dimension(1953125), intent(out) :: datasort
integer,dimension(3,1953125),intent(out) :: indexsort
integer, dimension(3) :: Result
integer :: i
rewind(2)
read(2,*) datosden
datosdentemp = datosden
rewind(3)
read(3,*) datostemp
do i = 1, 10
Result = MAXLOC(datosdentemp)
datasort(i) = datosden(Result(1),Result(2),Result(3))
indexsort(1,i) = Result(1)
indexsort(2,i) = Result(2)
indexsort(3,i) = Result(3)
datosdentemp(Result(1),Result(2),Result(3)) = 0
end do
End Subroutine DataSorting
The files from where I'm reading the data just have the data arranged in 125 columns and 15625 rows in the case of the non-working program, and in 70 columns and 14000 rows for the working one, and the files are just that, I mean they are really structured that way in both cases. I was using scratch files for the files 2 and 3, and change them to '.txt' files to see if there was a problem with the input file, but no. Then I build a new file and did the reading with a do-loop, to see if that was the problem, but no, but at least that helped me to realize that the code was reading exactly half of 15625, but i don't know why this is happening, I'm new to fortran, my thesis advisor told me to do this code in Fortran 'cause the amount of data that have to handle will make my Julia code way to slow, so honestly any help will be much appreciated.

Use of selected_real_kind in a module [duplicate]

So I am doing 2 modules which are linking to the main program. The first one has all the variables defined in it and the second one is with the functions.
Module1:
module zmienne
implicit none
integer, parameter :: ngauss = 8
integer, parameter :: out_unit=1000
integer, parameter :: out_unit1=1001
integer, parameter :: out_unit2=1002, out_unit3=1003
real(10), parameter :: error=0.000001
real(10):: total_calka, division,tot_old,blad
real(10),parameter:: intrange=7.0
real(10),dimension(ngauss),parameter::xx=(/-0.9602898565d0,&
-0.7966664774d0,-0.5255324099d0,-0.1834346425d0,&
0.1834346425d0,0.5255324099d0,0.7966664774d0,0.9602898565d0/)
real(10),Dimension(ngauss),parameter::ww=(/0.1012285363d0,&
0.2223810345d0,0.3137066459d0,0.3626837834d0,&
0.3626837834d0,0.3137066459d0,0.2223810345d0,0.1012285363d0/)
real(10) :: r, u, r6, tempred, f, r2, r1, calka,beta
real(10) :: inte
real :: start, finish
integer:: i,j,irange
real(10),dimension(ngauss)::x,w,integrand
end module zmienne
Module2
module in
implicit none
contains
real(10) function inte(y,beta,r2,r1)
real(kind=10)::r,beta,r6,r2,r1,u,y
r=(r2-r1)*y+r1
r6=(1.0/r)**6
u=beta*r6*(r6-1.0d0)
if (u>100.d0) then
inte=-1.0d0
else
inte=exp(-u)-1.d0
endif
inte=r*r*inte
end function
end module in
And while im calling them like that:
use zmienne; use in
I am getting following error:
Name 'inte' at (1) is an ambiguous reference to 'inte' from module 'zmienne'
I've deleted "inte" in the module1 but now I am getting following error:
irange=inte(intrange/division)
1
Error: Missing actual argument for argument 'beta' at (1)
The main program code is:
program wykres
use zmienne; use in
implicit none
open(unit=out_unit, file='wykresik.dat', action='write', status='replace')
open(unit=out_unit1, file='wykresik1.dat', action='write')
open(unit=out_unit2, file='wykresik2.dat', action='write')
open(out_unit3, file='wykresik3.dat', action='write')
! the gaussian points (xx) and weights (ww) are for the [-1,1] interval
! for [0,1] interval we have (vector instr.)
x=0.5d0*(xx+1.0d0)
w=0.5d0*ww
! plots
tempred = 1.0
call cpu_time(start)
do i=1,1000
r=float(i)*0.01
r6=(1.0/r)**6
u=beta*r6*(r6-1.0)
f=exp(-u/tempred)-1.0
write(out_unit,*) r, u
write(out_unit1,*)r, f
write(out_unit2,*)r, r*r*f
end do
call cpu_time(finish)
print '("Time = ",f6.3," seconds.")',finish-start
! end of plots
! integration 1
calka=0.0
r1=0.0
r2=0.5
do i=1,ngauss
r=(r2-r1)*x(i)+r1
r6=(1.0/r)**6
u=beta*r6*(r6-1.0d0)
! check for underflows
if (u>100.d0) then
f=-1.0d0
else
f=exp(-u)-1.d0
endif
! the array integrand is introduced in order to perform vector calculations below
integrand(i)=r*r*f
calka=calka+integrand(i)*w(i)
enddo
calka=calka*(r2-r1)
write(*,*)calka
! end of integration
! integration 2
calka=0.0
do i=1,ngauss
integrand(i)=inte(x(i),beta,r2,r1)
calka=calka+integrand(i)*w(i)
enddo
calka=calka*(r2-r1)
! end of integration 2
write(*,*)calka
! vector integration and analytical result
write(*,*)sum(integrand*w*(r2-r1)),-(0.5**3)/3.0
!**************************************************************
! tot_calka - the sum of integrals all integration ranges
! dividion the initial length of the integration intervals
! tot_old - we will compare the results fro two consecutive divisions.
! at the beginning we assume any big number
! blad - the difference between two consecutive integrations,
! at the beginning we assume any big number
! error - assumed precission, parameter, it is necassary for
! performing do-while loop
total_calka=0.0
division=0.5
tot_old=10000.0
blad=10000.0
do while (blad>error)
! intrange - the upper integration limit, it should be estimated
! analysing the plot of the Mayer function. Here - 7.
! irange = the number of subintegrals we have to calculate
irange=inte(intrange/division)
total_calka=-(0.5**3)/3.0
! the analytical result for the integration range [0,0.5]
! the loop over all the intervals, for each of them we calculate
! lower and upper limits, r1 and r2
do j=1,irange
r1=0.5+(j-1)*division
r2=r1+division
calka=0.0
! the integral for a given interval
do i=1,ngauss
integrand(i)=inte(x(i),beta,r2,r1)
calka=calka+integrand(i)*w(i)
enddo
total_calka=total_calka+calka*(r2-r1)
enddo
! aux. output: number of subintervals, old and new integrals
write(*,*) irange,division,tot_old,total_calka
division=division/2.0
blad=abs(tot_old-total_calka)
tot_old=total_calka
! and the final error
write(*,*) blad
enddo
open(1,file='calka.dat', access='append')
! the secod viarial coefficient=CONSTANT*total_calka,
! CONSTANT is omitted here
write(1,*)tempred,total_calka
close(1)
end program wykres
The inte is declared in both modules.
Upd. The inte(y,beta,r2,r1) function is defined in the module in, and is used in the main program. This function requires four arguments, but this call
irange=inte(intrange/division)
provides only one argument. I'm not sure if this function should be used in this case. Try to use long meaningful names for variables and functions to avoid similar issues.

Fortran: reading input

I am trying to run a really large FORTRAN model, so I can't give all the code that's involved but I hope I can give enough information for this to make sense.
The code compiled fine (using Intel 2016.0.109 compiler, OpenMPI 1.10.2 and HDF5 1.8.17).
When I try to run it though, it tells me that two of my inputs (called NZG and NZS) are set to -999, hence it fails.
> >>>> opspec_grid error! in your namelist!
> ---> Reason: Too few soil layers. Set it to at least 2. Your nzg is currently set to -999...
> ---> Reason: Too few maximum # of snow layers. Set it to at least 1. Your nzs is currently set to -999.
However, in the input file, they are really specified as
NL%NZG = 9
NL%NZS = 1
I went through all the modules that somehow have something to do with these variables and cannot find anywhere where this should go off the rails.
So I am starting to think now that maybe there is something wrong with the way the values are read in. The input file is a text file. The variables are specified as integers in the module that reads them in, FYI.
Should I check for special characters or something? I know Fortran can be picky with inputs...
EDIT: Below the code sequence tracing back the error
1) The main module opens the namelist
write (unit=*,fmt='(a)') 'Reading namelist information'
call read_nl(trim(name_name))
read_nl is
subroutine read_nl(namelist_name)
use ename_coms, only : nl & ! intent(inout)
, init_ename_vars ! ! subroutine
implicit none
!----- Arguments. ----------------------------------------------------------------------!
character(len=*), intent(in) :: namelist_name
!----- Local variables. ----------------------------------------------------------------!
logical :: fexists
!----- Name lists. ---------------------------------------------------------------------!
namelist /ED_NL/ nl
!---------------------------------------------------------------------------------------!
!----- Open the namelist file. ---------------------------------------------------------!
inquire (file=trim(namelist_name),exist=fexists)
if (.not. fexists) then
call fatal_error('The namelist file '//trim(namelist_name)//' is missing.' &
,'read_nl','ed_load_namelist.f90')
end if
!----- Initialise the name list with absurd, undefined values. -------------------------!
call init_ename_vars(nl)
!----- Read grid point and options information from the namelist. ----------------------!
open (unit=10, status='OLD', file=namelist_name)
read (unit=10, nml=ED_NL)
close(unit=10)
return
end subroutine read_nl
2) Then there are specifics about how (what variables) to read from the namelist (the input)
write (unit=*,fmt='(a)') 'Copying namelist'
call copy_nl('ALL_CASES')
if (runtype == 'HISTORY') then
call copy_nl('HISTORY')
else
call copy_nl('NOT_HISTORY')
end if
My simulation is 'NOT_HISTORY': copy_nl('ALL_CASES') is specified so it reads a number of the namelist variables, including the variable 'runtype' - which is then used in that if-else statement.
3) Then copy_nl('NOT_HISTORY') is the following, this is where nzg and nzs are defined.
subroutine copy_nl(copy_type)
use grid_coms , only : time & ! intent(out)
, centlon & ! intent(out)
, centlat & ! intent(out)
, deltax & ! intent(out)
, deltay & ! intent(out)
, nnxp & ! intent(out)
, nnyp & ! intent(out)
, nstratx & ! intent(out)
, nstraty & ! intent(out)
, polelat & ! intent(out)
, polelon & ! intent(out)
, ngrids & ! intent(out)
, timmax & ! intent(out)
, time & ! intent(out)
, nzg & ! intent(out)
, nzs ! ! intent(out)
implicit none
!----- Arguments. ----------------------------------------------------------------------!
character(len=*), intent(in) :: copy_type
!----- Internal variables. -------------------------------------------------------------!
integer :: ifm
!---------------------------------------------------------------------------------------!
!---------------------------------------------------------------------------------------!
! Here we decide which variables we should copy based on the input variable. !
!---------------------------------------------------------------------------------------!
select case (trim(copy_type))
case ('NOT_HISTORY')
itimea = nl%itimea
idatea = nl%idatea
imontha = nl%imontha
iyeara = nl%iyeara
nzg = nl%nzg
nzs = nl%nzs
slz(1:nzgmax) = nl%slz(1:nzgmax)
current_time%year = iyeara
current_time%month = imontha
current_time%date = idatea
current_time%time = real(int(real(itimea) * 0.01)) * hr_sec &
+ (real(itimea) * 0.01 - real(int(real(itimea)*0.01))) &
* 100.0 * min_sec
time = 0.0d0
NOTE that I have not put all the modules and variables in use, otherwise this post would become insanely long.
FYI the module grid_coms specifies the type the variable is. See below the relevant part (the whole module is a list of variables, nothing else)
module grid_coms
integer :: nzg ! Number of soil levels
integer :: nzs ! Number of snow/surface water levels
end module grid_coms
4) Back to the main module, this then calls ed_opspec_grid to check that the variables make sense, and this is where things go wrong. Again, with use the variables are initialized at the start, I'm leaving that out here.
subroutine ed_opspec_grid
!---------------------------------------------------------------------------------------!
! Check whether soil layers are reasonable, i.e, enough layers, sorted from the !
! deepest to the shallowest. !
!---------------------------------------------------------------------------------------!
if (nzg < 2) then
write (reason,'(a,1x,i4,a)') &
'Too few soil layers. Set it to at least 2. Your nzg is currently set to' &
,nzg,'...'
call opspec_fatal(reason,'opspec_grid')
ifaterr=ifaterr+1
elseif (nzg > nzgmax) then
write (reason,'(2(a,1x,i5,a))') &
'The number of soil layers cannot be greater than ',nzgmax,'.' &
,' Your nzg is currently set to',nzg,'.'
call opspec_fatal(reason,'opspec_grid')
ifaterr=ifaterr+1
end if
do k=1,nzg
if (slz(k) > -.001) then
write (reason,'(a,1x,i4,1x,a,1x,es14.7,a)') &
'Your soil level #',k,'is not enough below ground. It is currently set to' &
,slz(k),', make it deeper than -0.001...'
call opspec_fatal(reason,'opspec_grid')
ifaterr=ifaterr+1
end if
end do
do k=1,nzg-1
if (slz(k)-slz(k+1) > .001) then
write (reason,'(2(a,1x,i4,1x),a,2x,a,1x,es14.7,1x,a,1x,es14.7,a)') &
'Soil layers #',k,'and',k+1,'are not enough apart (i.e. > 0.001).' &
,'They are currently set as ',slz(k),'and',slz(k+1),'...'
call opspec_fatal(reason,'opspec_grid')
ifaterr=ifaterr+1
end if
end do
end subroutine ed_opspec_grid
NOTE that this is not the first check in this subroutine. Other variables are checked before this part (I left those out), but this is the first error message. Which makes me think that maybe part of the input is read okay and some is not.
Finally, let me stress again that this is a very large project, I really cannot show all the code, which is why I framed the question very simply: are there any (text) input requirements for Fortran that I might have missed (special characters, returns, maybe different for different systems?).
Plus, this code is used by a lot of researchers, on different platforms, so I doubt it very much there is something wrong with the code itself... (but let me know if I'm wrong).
You are not giving us enough data to pinpoint the issue, so I'll just tell you two of the issues that I have come across using namelists:
If you read several (even different) namelists from the same file, the order counts: If in the file namelist a preceeds namelist b, but the code reads b first, then it won't find a unless you rewind the file.
If the namelist in the data file does not include one or more values, these values will simply stay the same. It is quite likely that in the code these variables are set to -999 specifically so that their absence would be noted. So double-check that the data file is correct. Look for stray / characters that might end the namelist prematurely
All in all, in order to correctly assess what's happening, we'd need at least 3 things:
The declaration block, including all the variables that form part of this namelist, and the namelist /.../ ...,...,... specification
The part of the namelist file that declares this specific namelist, and
Whether any other namelists are also in the same file and whether they're before or after this namelist (both in the file, and in the code)

Print and write in one line?

Is it possible to print something in the screen and, at the same time, that what is being printed is also written in a file?
Right now, I have something like this:
print *, root1, root2
open(unit=10,file='result.txt'
write(10,*), root1, root2
close(10)
I feel like I'm wasting lines and making the code longer that it should be. I actually want to print/write much more lines that these, so that's why I'm looking for a cleaner way to do it.
Writing to standard output and writing to file are two different things, so you will always need separate instructions. But you don't have to open and close the file for every line you write.
Honestly, I don't think it's that much more of an effort:
open(unit=10, file='result.txt', status='replace', form='formatted')
....
write( *, *) "Here comes the data"
write(10, *) "Here comes the data"
....
write( *, *) root1, root2
write(10, *) root1, root2
....
close(10)
this is only one line more than what you would have to do anyway per write statement.
If you really think that you have too many write statements in your code, here are a few ideas that you might try:
If you are running on a Linux or Unix system (including MacOS), you can write a program that only writes to standard out, and pipe the output into a file, like this:
$ ./my_program | tee result.txt
This will both output the data to the screen, and write it into the file result.txt
Or you could write the output to a file in the program, and 'follow' the file externally:
$ ./my_program &
$ tail -f result.txt
I just had another idea: If you really often have the issue that you need to write data to both the screen and the file, you can place that into a subroutine:
program my_program
implicit none
real :: root1, root2, root3
....
open(10, 'result.txt', status='replace', form='formatted')
....
call write_output((/ root1, root2 /))
....
call write_output((/ root1, root2, root3 /))
....
call write_output((/ root1, root2 /))
....
close(10)
....
contains
subroutine write_output(a)
real, dimension(:), intent(in) :: a
write( *, *) a
write(10, *) a
end subroutine write_output
end program my_program
I am passing the values to be written here as an array because that gives you more flexibility in the number of variables that you might want to print. On the other hand, you can only use this subroutine to write real values, for others (integer, character, etc) or combinations thereof you'd need to still have two write statements, or write other specific 'write to both' routines.

Why doesn't io:write() write to the output file?

I'm writing a short script in Lua to replicate Search/Replace functionality. The goal is to enter a search term and a replacement term, and it will comb through all the files of a given extension (not input-determined yet) and replace the Search term with the Replacement term.
Everything seems to do what it's supposed to, except the files are not actually written to. My Lua interpreter (compiled by myself in Pelles-C) does not throw any errors or exit abnormally; the script completes as if it worked.
At first I didn't have i:flush(), but I added it after reading that it is supposed to save any written data to the file (see LUA docs). It didn't change anything, and files are still not written to.
I think it might have something to do with how I'm opening the file to edit it, since the "w" option works (but overwrites everything in my test files).
Source:
io.write("Enter your search term:")
term = io.read()
io.write("Enter your replace term:")
replacement = io.read()
io.stdin:read()
t = {}
for z in io.popen('dir /b /a-d'):lines() do
if string.match(string.lower(z), "%.txt$") then
print(z)
table.insert(t, z)
end
end
print("Second loop")
for _, w in pairs(t) do
print(w)
i = io.open(w, "r+")
print(i)
--i:seek("set", 6)
--i:write("cheese")
--i:flush()
for y in i:lines() do
print(y)
p, count = string.gsub(y, term, replacement, 1)
print(p)
i:write(p)
i:flush()
io.stdin:read()
end
i:close()
end
This is the output I get (which is what I want to happen), but in reality isn't being written to the file:
There was one time where it wrote output to a file, but it only output to one file and after that write my script crashed with the message: No error. The line number was at the for y in i:lines() do line, but I don't know why it broke there. I've noticed file:lines() will break if the file itself has nothing in it and give an odd/gibberish error, but there are things in my text files.
Edit1
I tried do this in my for loop:
for y in i:lines() do
print(y)
p, count = string.gsub(y, term, replacement, 1)
print(p)
i:write(p)
i:seek("set", 3) --New
i:write("TESTESTTEST") --New
i:flush()
io.stdin:read()
end
in order to see if I could force it to write regular text. It does but then it crashes with No error and still doesn't write the replacement string (just TESTESTTEST). I don't know what the problem could be.
I guess, one can't write to file while traversing its lines
for y in i:lines() do
i:write(p)
i:flush()
end