Do Loop in a Loop - fortran

I am facing problem doing loop in a loop. I don't know why loop in a loop is not running.
Program Console2
IMPLICIT NONE
Integer n,LineID,AA,AAA,BBB,CCC,DDD,EEE,FFF,GGG,J
Real :: A,B,C,D,S,BB,CC,DD
Character (LEN=10) Line,NodeID
OPEN(UNIT=2,FILE="Chaq.txt",STATUS='unknown')
OPEN(UNIT=12,FILE="CoOrd.txt",STATUS='unknown')
OPEN(UNIT=4,FILE="OUTPUT.txt",STATUS='unknown')
Do n=1,10
Read (2,'(1x,a6,5x,i5,7x,i4,i8,i8,i8,i8)')NodeID,AAA,BBB,CCC,DDD,EEE,FFF
write (4,*)NodeID,DDD
Do J=1,10
READ (12,('(1x,a4,7x,I5,8x,f8.2,f8.2,f8.2)'))Line,AA,BB,CC,DD
write (4,*) Line,AA
End Do
End Do
End program Console2
Problem is for second loop it is not reading the values from second file: OUTPUT File:
CQUAD4 5950
GRID 3860
GRID 3861
GRID 3862
GRID 3863
GRID 3864
GRID 3865
GRID 3866
GRID 3867
GRID 3868
GRID 3869
CQUAD4 5949
Files Chaq.text: some lines
CQUAD4 6817 2 6053 5950 5951 6054
CQUAD4 6816 2 6052 5949 5950 6053
CQUAD4 6815 2 6051 5948 5949 6052
CQUAD4 6814 2 6050 5947 5948 6051
CQUAD4 6813 2 6192 5946 5947 6050
CoOrd.txt : Some Lines I shown
GRID 3860 -171.90469.00543-28.5831
GRID 3861 -186.50872.15994-28.5831
GRID 3862 -180.23572.08246-28.5831
GRID 3863 -184.573103.9741-28.5831
GRID 3864 -171.92971.30236-28.5831
GRID 3865 -191.05479.44247-28.5831
GRID 3866 -159.938100.6297-28.5831
GRID 3867 -169.58477.11039-28.5831
GRID 3868 -176.62391.22597-28.5831
GRID 3869 -185.83898.214 -28.5831

If you are wanting to read from the beginning of CoOrd.txt each time through the outer loop, then you need to rewind CoOrd.txt each time through the loop:
Integer ReadStat
...
Do n=1,10
Read (2, '(1x,a6,5x,i5,7x,i4,i8,i8,i8,i8)', IOSTAT=ReadStat) NodeID,AAA,BBB,CCC,DDD,EEE,FFF
If (ReadStat < 0) exit ! EOF reached
If (ReadStat > 0) stop ! An unknown error occurred
write (4,*)NodeID,DDD
rewind(12)
Do J=1,10
READ (12, ('(1x,a4,7x,I5,8x,f8.2,f8.2,f8.2)', IOSTAT=ReadStat))Line,AA,BB,CC,DD
If (ReadStat < 0) exit ! EOF reached
If (ReadStat > 0) stop ! An unknown error occurred
write (4,*) Line,AA
End Do
End Do

Related

How automatically double the number of intervals

I want to double a number till 256, and when the program gets 256 make stop but the program that I created not giving me a double from 1 till 256
`````````````````````````````````````````````````````````````````
Fortran code
program exercise1
implicit none
real, external :: f
real :: h,a,b,prod,integration,summ,p
integer :: i,j,n
print*, 'Welcome, This program using Composite trapezoid method to calculate the integer'
print*, ' -------- '
prod=1
summ=0
print*,'Number of intervals ',' The integer value'
do i=1,258
n=(prod*i*i) ! Getting number of interval till 256
a=-1 ! The Lower limit of the integration
b=1 ! The Upper limit of the integration
h=(b-a)/n ! Calculate the delta X
p=(h/2.)*(f(a)+f(b)) ! Here as we have the whole equation is (h/2)*[f(a)+f(b)+2*sum(Xi) ! So we calculate the first part (h/2)*[f(a)+f(b) and then calculate the anoter part
summ=summ+h*f(a+i*h) !h/2 *2* sum[f(Xi)
integration = p+summ !Here the sum the both parts
if(n == 256) then !put a limit for the number of interval
Stop
end if
print*,n,' -', integration
enddo
end
real function f(x) !the function of the integer
f=sin(x+1)
end`
``````````````````````
the output
``````````````````
1 2.72789216
4 2.46665454
9 2.47777867
16 2.49350500
25 2.50419927
36 2.51126313
49 2.51606560
64 2.51944780
81 2.52190781
100 2.52374840
121 2.52515912
144 2.52626276
169 2.52714205
196 2.52785373
225 2.52843738
I think you want powers of: 2**i not squares: i**2. For example:
do i = 0,8
print*, 2**i
enddo
gives
1
2
4
8
16
32
64
128
256
I was originally voting to close as a typo, but your code maybe indeed does something different.
Your codes makes n to be a sequence if integer squares. 1^2, 2^2, 3^2 ... 16^2=256
But you wanted doubling the number, in that case just multiply n by 2.
n = 1
do i = 1, 10
do what you need
print *, n
n = n * 2
end do

Extract values from .dat file with fortran, with lines and especific variables

I need take te values of NPNOD, NELEM, and the others. and take the values of the next matrix
$DIMENSIONES DEL PROBLEMA
DIMENSIONES : NPNOD= 27 , NELEM= 8 , NMATS= 1 , \
NNODE= 8 , NDIME= 3 , \
NCARG= 1 , NGDLN= 3, NPROP= 5, \
NGAUS= 1 , NTIPO= 1 , IWRIT= 1 ,\
INDSO= 10 , NPRES= 9
$---------------------------------------------------------
GEOMETRIA
$ CONECTIVIDADES ELEMENTALES
$ ELEM. MATER. SECUENCIA DE CONECTIVIDADES
1 1 8 6 12 20 18 15 23 25
2 1 19 8 20 24 26 18 25 27
3 1 5 2 6 8 14 11 15 18
4 1 17 5 8 19 21 14 18 26
5 1 7 4 9 13 8 6 12 20
6 1 16 7 13 22 19 8 20 24
7 1 3 1 4 7 5 2 6 8
8 1 10 3 7 16 17 5 8 19
To read a mixture of Characters and numbers in fortran is done best by first reading the whole line into a character string and then to read the respective numerical values from this string. The details will depend a lot on the flexibility you need to have to deal with changing input formats. The more you can rely on the assumption that an input file will always be of identical structure the easier things get.
You did not specify in your question the details of the 10 numbers in the rows numbered 1 to 8. Lets assume that the first number is the row of the matrix , the second number the number of the current matrix and the remaining eight numbers are the elements. Lets further assume that the elements in one row of the matrix will always be listed in one single input line.
character(len=5), dimension(10) :: fields
character(len=80) :: string
character(len=1024) :: grand
integer, dimension(10) :: values
fields(1) = 'NPNOD' ! and so on ...
read(unit=ird, '(a)', iostat=ios) string ! read line 'DIMENSIONES...'
read(unit=ird, '(a)', iostat=ios) string ! read dummy string
grand(1:80) = string ! place into grand total
read(unit=ird, '(a)', iostat=ios) string ! read dummy string
grand(81:160) = string ! append to grand total
...! repeat for three more lines
grand(len_trim(grand)+1:len_trim(grand)+1) = ',' ! Append a final comma
do i=1,10 ! Loop over all field names
ilen = len_trim(field(i)) ! store length of field name, may vary?
ipos = index(grand, field(i)) ! Find start of field name
icom = index(grand(ipos+ilen+1:len(grand), ',') ! locate trailing comma
read(grand(ipos+ilen+1:ipos+ilen+icom-1),*) values(i) ! Read numerical value
enddo
read(unit=ird, '(a)', iostat=ios) string ! read dummy string
read(unit=ird, '(a)', iostat=ios) string ! read dummy string
read(unit=ird, '(a)', iostat=ios) string ! read dummy string
do i= 1, values(2) ! if NELEM is in fields(2)
read(ird, *) irow, imat, (array(i,j),j=1, values(2)) ! read leading two no's and elements
enddo
You still have to define the integer variables, ird, ilen, ipos, icom, irow, imat, ios, i, j, the matrix array or the many matrices you need to read.
Upon a read the value of the status variable ios should be inspected...
Essentially I do:
define a character variable field with all the names 'NPNOD' ...
read and concatenate the lines 'dimensiones' until 'INDSO' into the string "grand"
Loop over all field and
detect position of the field name and the position of the trailing comma
read from the grand string the subsection that contains only the numerical value
Loop over the rows with matrix elements to read the two first numbers and the matrix elements.
As I appended a final comma, that is missing in the line 'INDSO...', the loop over the field names does not have to bother with the special case of 'NPRES', which does not have a trailing comma in the original input file.
Your actual code should
check if there are never more than 10 fields
is 80 character the maximum length of any individual input line
will 1024 characters be neough for the concatenated list.

Allocated matrix and input file

I have an input data file storing two columns (first column contains the names of the variables and the second column contains their values). I am trying to read this input file through my FORTRAN script and to print on the screen the variables I've just created.
Here are the input file, the script, as well as the terminal output displayed on the terminal at the execution:
input file:
a 7 2 4
b 150
vec1 1 2 3
vec2 4 5 6
c 56
script
program main
implicit none
character(16) :: cinput
integer :: a0,a1,a2,b0,c0,i,j
integer,dimension(:,:),allocatable :: gfd
open(9, file='inputdata.dat')
read(9,*) cinput,a0,a1,a2
read(9,*) cinput,b0
allocate(gfd(3,2))
read(9,*) cinput,gfd(:,1)
read(9,*) cinput,gfd(:,2)
read(9,*) cinput,c0
close(9)
write(*,*) 'a0=', a0,'a1=', a1,'a2=', a2,'b0=', b0,'c0=', c0
do j=1,2
do i=1,3
write(*,*) gfd(i,j)
enddo
enddo
end program main
Output on the terminal
a0 = 7, a1 = 2, a2 = 4, b0 = 150, c0 = 56
1
2
3
4
5
6
Now, this is good, but would there be a way to assign the values to the variable "gfd" without having to specify the size of the array in "allocate"? I could then modify the input file with a longer/smaller array, without having to modify the script when I allocate the variable "gfd".
Thank you for your support if you can help me!
ms518
EDIT: thanks for your answer, this procedure is working and it is now possible to work with various array sizes in the input file without having to modify the fortran script. Below are the modifications in inputfile, script and the result obtained.
input file:
size 5 2
a 7 2 4
b 150
vec1 1 2 3 4 5
vec2 6 7 8 9 10
c 56
script
program main
implicit none
character(16) :: cinput
integer :: a0,a1,a2,b0,c0,i,j, rows, cols
integer,dimension(:,:),allocatable :: gfd
open(9, file='inputdata.dat')
read(9,*) cinput,rows,cols
read(9,*) cinput,a0,a1,a2
read(9,*) cinput,b0
allocate(gfd(rows,cols))
read(9,*) cinput,gfd(:,1)
read(9,*) cinput,gfd(:,2)
read(9,*) cinput,c0
close(9)
write(*,*) 'a0=', a0,'a1=', a1,'a2=', a2,'b0=', b0,'c0=', c0
do j=1,cols
do i=1,rows
write(*,*) gfd(i,j)
enddo
enddo
end program main
Output on the terminal
a0 = 7, a1 = 2, a2 = 4, b0 = 150, c0 = 56
1
2
3
4
5
6
7
8
9
10
The best way to specify the size of the array would be to include its dimensions in the input file, read them, allocate the array, then read the array.
If you need assistance programming this, modify your question. You could, if you want, post your revised code to answer your own question.

-fortran : reading numbers from a text file

I have a text file of numbers containing several columns and several lines. I have tried several ways including arrays but in the best result I could get only 3 columns of the whole. Any ideas how I can read all the data in Fortran 77?
open(unit=1, file='f', status='old')
do i = 1, 100
read(1, *) x(i), y(i), z(i)
write(6, * ) x(i), y(i), z(i)
enddo
or even 2 dimensional arrays:
do i = 1, 100
do j = 1, 50
read(1, *) x(i, j)
write(6, *) x(i, j)
enddo
enddo
or changing the open(..., access='direct')
none of them worked out since i have a file like this:
1 2 4.5 77 89 4 3 2...
2 4 4 5 6 73 5 3.4 ...
1 2 4 5 67 8 99...
...
The data does not seem to have any particular structure.
You can use list-directed input for this:
program main
real a(100)
read (*,*) a
print *,a
end
I would advise you against using any unit number smaller than 10 in your code for your own purposes.

Random sampling in fortran

I have the following data
X Y INFTIME
1 1 0
1 2 4
1 3 4
1 4 3
2 1 3
2 2 1
2 3 3
2 4 4
3 1 2
3 2 2
3 3 0
3 4 2
4 1 4
4 2 3
4 3 3
4 4 0
X and Y represent he X and Y components in the square grid of 4 by 4.
Here I want to sample randomly 10% from the population which are infected i.e, whose INFTIME is non zero. I did not get any idea of coding so could not start it.
Any suggestions and idea will be great for me.
Thanks
EDIT:
DO T = 1,10
DO i = 1, 625
IF(INFTIME(i)/=0 .AND. INFTIME(i) .LE. T)THEN
CALL RANDOM_NUMBER(u(i))
u(i) = 1+aint(u(i)*25)
CALL RANDOM_NUMBER(v(i))
v(i) = 1+aint(v(i)*25)
CALL RANDOM_NUMBER(w(i))
w(i) = 1+aint(w(i)*10)
ENDIF
ENDDO
ENDDO
do p = 1,625
WRITE(*,*) u(p),v(p),w(p)
enddo
This is my code what I tried but it only gives the random numbers, not the connection to the data. I used the data of 25 by 25 grids i.e, 625 individuals and time of infection 1 to 10
Follow what ja72 said. You have three 1D arrays of the same size (16). All you need to do is pick a number between 1 and 16, check to see if INFTIME is zero and accept the value as needed, then repeat until you've taken 10% of the samples (which would be 1.6 values, so I presume you'd just take 2? Or do you have more data than this 4x4 you presented?)
Edit You need to call the random number generator before the if statement:
do t=1,10
do i=1,625
ind = 1+int(624*rand(seed))
if(inftime(ind).neq.0 .and. inftime(ind).le.t) then
stuff
endif
enddo
enddo
The call ind=1+int(625*rand(seed)) will pick a random integer between 1 (when rand(seed)=0) and 625 (when rand(seed)=1). Then you can do what you need if the if statement is satisfied.
EDIT: program epimatrix
IMPLICIT NONE
INTEGER ::l, i,T,K
REAL, DIMENSION(1:625):: X,y,inftime
INTEGER::seed,my_cnt
INTEGER,DIMENSION(8) :: time1
CALL DATE_AND_TIME(values=time1)
seed = 1000*time1(7)+time1(8)
call srand(seed)
OPEN(10, FILE = 'epidemicSIR.txt', FORM = 'FORMATTED')
DO l = 1,625
READ(10,*,END = 200) X(l), Y(l), INFTIME(l)
! WRITE(*,*) X(l),Y(l), INFTIME(l)
! if you know how it was formatted, you should use
! read(10,20) X(l), Y(l), INFTIME(l)
! where 20 is the format
ENDDO
200 CONTINUE
CLOSE(10)
DO T = 1,10
my_cnt=0
write(*,*) "T=",T
DO while (my_cnt.le.63)
K = 1+int(624*rand())
IF(INFTIME(K)/=0 .AND. INFTIME(K) .LE. T)THEN
write(*,*) X(k),Y(k),INFTIME(k)
my_cnt=my_cnt+1
ENDIF
enddo
write(*,*) " "
ENDDO
end program
EDIT 2
I've adjusted the program to fix some of the issues. I've tried keeping my edits in lowercase so that you can see the difference. The do-while loop allows the code to continue running until the condition my_cnt.le.63 has been met (which means you have 63 lines of X, Y, inftime per T). I've added a line to output T and another line to add a space so that the data might be more clear when looking at the output.
This should take care of all the issues you've been running into. If not, I'll keep checking this page.