Fortran error when calculating cosx - fortran

I was assigned the following problem:
Make a Fortran program which will be able to read a degree[0-360] checking validity range(not type) and it will be able to calculate and print the cos(x) from the following equation, where x is in radians:
cos(x)=1-x^2/2! + x^4/4!-x^6/6!+x^8/8!-...
As a convergence criteria assume 10^(-5) using the absolute error between two successive repeats (I suppose it means do's).
For the calculation of the ! the greatest possible kind of integer should be used. Finally the total number of repeats should be printed on screen.
So my code is this:
program ex6_pr2
implicit none
!Variables and Constants
integer::i
real*8::fact,fact2 !fact=factorial
real,parameter::pi=3.14159265
double precision::degree,radiants,cosradiants,s,oldcosradiants,difference !degree,radiants=angle
print*,'This program reads and calculates an angle`s co-sinus'
print*,'Please input the degrees of the angle'
read*,degree
do while(degree<0 .or. degree>360) !number range
read*,degree
print*,'Error input degree'
cycle
end do
radiants=(degree*pi/180)
fact=1
fact2=1
s=0
cosradiants=0
!repeat structure
do i=2,200,1
fact=fact*i
fact2=fact2*(i+2)
oldcosradiants=cosradiants
cosradiants=(-(radiants)**i/fact)+(((radiants)**(i+2))/fact2)
difference=cosradiants-oldcosradiants
s=s+cosradiants
if(abs(difference)<1e-5) exit
end do
!Printing results
print*,s+1.
end program
I get right results for angles such as 45 degrees (or pi/4) and wrong for other for example 90 degrees or 180.
I have checked my factorials where I believe the error is hidden (at least for me).
Well I created another code which seems unable to run due to the following error:FUNCTION name,(RESULT of PROJECT2_EX6~FACT),used where not expected,perhaps missing '()'
program project2_ex6
implicit none
integer(kind=3)::degrees,i,sign
integer::n
double precision::x,err_limit,s_old,s
real,parameter::pi=3.14159265359
print*,'This program calculates the cos(x)'
print*,"Enter the angle's degrees"
read*,degrees
do
if(degrees<0.or.degrees>360) then
print*,'Degrees must be between 0-360'
else
x=pi*degrees/180
exit
end if
end do
sign=1
sign=sign*(-1)
err_limit=1e-5
n=0
s=0
s_old=0
do
do i=1,n
end do
s=(((-1.)**n/(fact(2.*n)))*x**(2.*n))*sign
s=s+s_old
n=n+1
if(abs(s-s_old)<1e-5) then
exit
else
s_old=s
cycle
end if
end do
print*,s,i,n
contains
real function fact(i)
double precision::fact
integer::i
if(i>=1) then
fact=i*fact(i-1)
else
fact=1
end if
return
end function
end program

Although it is your homework, I will help you here. The first thing which is wrong is ýour factorial which you need to replace with
fact = 1
do j = 1,i
fact = fact*j
enddo
second it is easier if you let your do loop do the job so run it as
do i=4,200,2
and predefine cosradians outside the do loob with
cosradiants = 1-radiants**2/2
additionally you need to take into account the changing sign which you can do in the loop using
sign = sign*(-1)
and starting it off with sign = 1 before the loop
in the loop its then
cosradiants= cosradiants+sign*radiants**i/fact
If you have included these things it should work (at least with my code it does)

Related

How can I count the number of columns in a file?

I am trying to code a program that allows me to count the number of columns in a file (in the example below datos.txt). However, gfortran tells me there is an error:
"Expected variable in read statement".
How can I solve this? In the example, I used 100 as the maximum number of columns possible. The real value is 5.
What I have tried is this:
program contarcolumnas
implicit double precision (a-h,o-z)
implicit integer*8 (i-n)
open (50, file="datos.txt")
m=1
dimension matrizfichero(1,100)
do i=1,1
read(50,*)(matrizfichero(i,j),j=1,m)
if (iostat /= 0) then
m=m+1
else
print*,m
end if
end do
close(50)
end program contarcolumnas

Fortran code won't write to file

I am working on a program to calculate minimum nozzle length in supersonic nozzles (Method of Characteristics). I can't seem to figure out why my code won't write to my output file (the lines "write (6,1000)....). My code is below:
program tester
c----------------------------------------------------------------------c
implicit real (a-h,o-z)
integer count
real kminus(0:100),kplus(0:100),theta(0:100),nu(0:100),mach(0:100)
+ ,mu(0:100)
open (5,file='tester.in')
open (6,file='tester.out')
read (5,*) me
read (5,*) maxturn
read (5,*) nchar
read (5,*) theta0
close(5)
c.....set count to 0 and calculate dtheta
count=0
dtheta=(maxturn-theta0)/nchar
c.....first characteristic
do 10 an=1,nchar+1
count=count+1
c........these are already known
theta(count)=theta0+dtheta*(an-1)
nu(count)=theta(count)
c........trivial, but we will "calculate" them anyways
kminus(count)=2*theta(count)
kplus(count)=0
c........we feed it nu(count) and get m out
call pm_hall_approx(nu(count),m)
mach(count)=m
c........does not work with sqrt(...) for some reason
mu(count)=atan((1/(mach(count)**2)-1)**0.5)
write (6,1000) count,kminus(count),kplus(count),theta(count)
+ ,nu(count),mach(count),mu(count)
10 continue
c.....the other characteristics
do 30 bn=1,nchar
do 20 cn=1,(nchar+1-bn)
count=count+1
c...........these are given
kminus(count)=kminus(cn+bn)
kplus(count)=-1*kplus(bn+1)
c...........if this is the last point, copy the previous values
if (cn.eq.(nchar+1-bn)) then
kminus(count)=kminus(count-1)
kplus(count)=kplus(count-1)
endif
c...........calculate theta and nu
theta(count)=0.5*(kminus(count)+kplus(count))
nu(count)=0.5*(kminus(count)-kplus(count))
c...........calculate m
call pm_hall_approx(nu(count),m)
mach(count)=m
mu(count)=atan((1/(mach(count)**2)-1)**0.5)
write (6,1000) count,kminus(count),kplus(count),theta(count)
+ ,nu(count),mach(count),mu(count)
20 continue
30 continue
close(6)
stop
1000 format (11(1pe12.4))
end
c======================================================================c
include 'pm_hall_approx.f'
And my subroutine is given here:
subroutine pm_hall_approx(nu,mach)
c----------------------------------------------------------------------c
c Given a Mach number, use the Hall Approximation to calculate the
c Prandtl-Meyer Function.
c----------------------------------------------------------------------c
implicit real (a-h,o-z)
c.....set constants
parameter (a=1.3604,b=0.0962,c=-0.5127,d=-0.6722,e=-0.3278)
parameter (numax=2.2769)
y=nu/numax
mach=(1+a*y+b*y*y+c*y*y*y)/(1+d*y+e*y*y)
return
end
And here are the contents of tester.in
2.4 = mache
5.0 = maxturn
7 = nchar
0.375 = theta0
In fortran, unit number 6 is reserved for screen. Never use that as the unit number. Try changing it to some other number like write(7,1000) and then it should work.

Getting Invalid Float in Fortran and I'm not sure why

So I'm getting an invalid float error that's causing my code to crash from the following subroutine. The subroutine sums together my distribution function over angle and energy (so I just have a distribution in radius), then I compute my average optical depth, and then I look for the radial zone where that optical depth crosses 2/3. The code is designed to be run over multiple time steps, and in this particular simulation it had run through 49 time steps and then crashed on the 50th, which is confusing me even more.
subroutine SAPass(state, step)
use state_vector_module
use boltztran_memory_module, only: fe, trmfpe
use boltztran_parameter_module
use units_module
implicit none
real, dimension(102) :: Fse
real, dimension(102,8) :: taue
real, dimension(102) :: Te
inetger :: cycsav = -1
integer :: nsze
call opdep(trmfpe, taue)
Fse = 0.
do i=1,102
do j=1,4
do k=1,8
Fse(i) = Fse(i) + fe(i,j,k)
end do
end do
end do
do i=1,102
do j=1,4
do k=1,8
if (Fse(i).eq.0.) then
Te(i) = 0.
else
Te(i) = Te(i) + (fe(i,j,k)*taue(i,k))/Fse(i)
end if
end do
end do
end do
write(*,*) Te !debug check to look for where the error is happening
nsze = 1
do i=1,101
if(Te(i).eq.(2./3.)) then ! This is the line the invalid float error is reported on.
nsze = i
else if((Te(i).gt.(2./3.)).and.(Te(i+1).lt.(2./3.))) then
nsze = i
end if
end do
if(step.eq.cycsav) then
continue
else
cycsav = istep
call tauwrite(taue,step,1)
open(17,name="NSZones.dat",status="unknown",position="append")
write(17,i5) nsze
close(17)
end if
On time step 50 the code crashes and I get the following error:
forrtl: error (65): floating invalid
And it references the specified line in the code. When I look at the print outs for Te during time step 50 the entry for i=4 is a 'NaN' and I can't figure out what in the code could be causing this to become a NaN. The distribution function numbers all look normal for that time step and zone.
You use
Fse(i).eq.0.
Te(i).eq.(2./3.)
It is a very bad idea to compare two floating point numbers for equality. You are probably dividing by an almost-zero in
Te(i) = Te(i) + (fe(i,j,k)*taue(i,k))/Fse(i)
and that results in an error.
It is impossible to say more, because we can't see what fe is and which values it has nor which values taue has.

Fortran program made to calculate cos using taylor series prints wrong results,possible error with my factorial [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I've been trying to create a program that can calculate the cos of a radiant using Taylor series. I contemplate the error, for example:
cos(45)=1.4 must be this : s=(((-1.)**n/(fact*2.*n))*x**(2.*n))*sign.
The code:
program project2_ex6
implicit none
!Reference to variables
!-------------------------------------------------------
integer(kind=3)::degrees,i,sign !sign=a random name in order to use it to change the 's' sign consecutively
integer::n
double precision::x,err_limit,s_old,s,fact !x=angle in radiants,err_limit=the absolute error between two results,fact=factorial
real,parameter::pi=3.14159265359
!------------------------------------------------------
print*,'This program calculates the cos(x)'
print*,"Enter the angle's degrees"
read*,degrees
!Checking validity of degrees
!----------------------------------------------------
do
if(degrees<0.or.degrees>360) then
print*,'Degrees must be between 0-360'
else
x=pi*degrees/180
exit
end if
end do
sign=1
sign=sign*(-1)
err_limit=1e-5
n=0
s=0
s_old=0
fact=1
!Commencing do loop
!-----------------------------------------------------------
do
do i=1,n
fact=fact*i
end do
if(n==0) then
s=1
else
s=(((-1.)**n/(fact*2.*n))*x**(2.*n))*sign
s=s+s_old
end if
n=n+1
if(abs(s-s_old)<err_limit) then
exit
else
s_old=s
cycle
end if
end do
!Printing results
!-----------------------------------------------------------------
print*,s,i,n
end program
I found four mistakes:-
(1) fact should be set to 1 inside the main DO loop
(2) fact should be multiplied by itself 2n times in the inner DO loop
(3) In the main calculation of s, the denominator should be fact, not fact*2*n
(4) In the main calculation of s, don't need to multiply by sign (or if you do, it should be +1)
This now gives 0.7071... for 45 degrees.
program project2_ex6
implicit none
!Reference to variables
!-------------------------------------------------------
integer::degrees,i,sign !sign=a random name in order to use it to change the 's' sign consecutively
integer::n
double precision::x,err_limit,s_old,s,fact !x=angle in radiants,err_limit=the absolute error between two results,fact=factorial
real,parameter::pi=3.14159265359
!------------------------------------------------------
print*,'This program calculates the cos(x)'
print*,"Enter the angle's degrees"
read*,degrees
!Checking validity of degrees
!----------------------------------------------------
do
if(degrees<0.or.degrees>360) then
print*,'Degrees must be between 0-360'
else
x=pi*degrees/180
exit
end if
end do
sign=1
!
! Sign should be +1 or omitted
!
!- sign=sign*(-1)
err_limit=1e-5
n=0
s=0
s_old=0
!Commencing do loop
!-----------------------------------------------------------
do
!
! Initialise fact inside do loop
!
fact=1
!
! Change n to 2n
!
do i=1,2*n
fact=fact*i
end do
if(n==0) then
s=1
else
!
!Change fact*2*n to fact
!
s=(((-1.)**n/(fact))*x**(2.*n))*sign
s=s+s_old
end if
n=n+1
if(abs(s-s_old)<err_limit) then
exit
else
s_old=s
cycle
end if
end do
!Printing results
!-----------------------------------------------------------------
print*,s,i,n
end program

"Error: The shapes of the array expressions do not conform"

This is my program to solve a problem of three dimensional cylindrical fin. But when i run this program in Fortran 6.2 this error shows up:
Error: The shapes of the array expressions do not conform. [T]"
Now i don't understand why this is happening. I need quick assistance. Anyone please help me.
PROGRAM CYLINDRICAL FIN
DIMENSION T(500,500,500), OLDT(500,500,500),ERR(500,500,500)
DIMENSION R(500),Y(500),Z(500)
REAL CC,H,DR,DY,DZ,A,D,RY,YZ,ZR,B,E,TA,RL,YL,ZL
+P,AC,QF,MF,Q,EF,EFF,QMAX,AS,LC,QT,QF1,QF2
INTEGER I,J,K,M,N,L,M1,N1,L1,M2,M4,M34,N2,N4,N34,L2,L4,L34
RL=0.5
YL=6.283
ZL=0.04
M=100
N=40
L=20
M2=((M/2)+1)
M4=((M/4)+1)
M34=((3*M/4)+1)
N2=((N/2)+1)
N4=((N/4)+1)
N34=((3*N/4)+1)
L2=((L/2)+1)
L4=((L/4)+1)
L34=((3*L/4)+1)
DR=RL/M
DY=YL/N
DZ=ZL/L
CC=400.0
H=10.0
TA=25
M1=M-1
N1=N-1
L1=L-1
************VARIABLES************
A=DR*DY*DZ
D=DR+DY+DZ
RY=DR*DY
YZ=DY*DZ
ZR=DZ*DR
E=RY+YZ+ZR
************VARIABLES FOR EFFICIENCY AND EFFECTIVENESS (CROSS-SECTION AREA,PERIMETER,M,SURFACE AREA OF FIN)************
AC=3.1416*DR**2
P=2*(3.1416*DR+DZ)
MF=((H*P)/(CC*AC))**(0.5)
AS=2*3.1416*DR*DZ+3.1416*DR**2
************************************** distance discritization ******************
R(1)=0.0
Y(1)=0.0
Z(1)=0.0
R(M+1)=RL
Y(N+1)=YL
Z(L+1)=ZL
DO I=2,M
R(I)=R(I-1)+DR
END DO
DO J=2,N
Y(J)=Y(J-1)+DY
END DO
DO K=2,L
Z(K)=Z(K-1)+DZ
END DO
DO I=1,M
DO J=1,N
DO K=1,L
T(I,J,K)=0.0
END DO
END DO
END DO
DO I=1,M
DO J=1,N
T(I,J,1)=400
END DO
END DO
ITER=0.0
READ(*,*) LAST
31 CONTINUE
ITER=ITER+1
*************************************** FORMULAS**********************************
DO I=2,M1
DO J=2,N1
DO K=2,L1
T(I,J,K)=((R*DR*T(I+1,J,K)*(YZ)**2.0)-((T(I+1,J,K)+T(I-1,J,K))*
+(R*YZ)**2.0)-((T(I,J+1,K)+T(I,J-1,K))*(ZR**2.0))-((T(I,J,K+1)+
+T(I,J,K-1))*(R*RY)**2.0))/((R*DR*(YZ)**2.0)-(2.0*(R*YZ)**2.0)-
+(2.0*(ZR)**2.0)-(2.0*(R*RY)**2.0))
END DO
END DO
END DO
*************************************** END OF ITERATIONG FORMULAS****************
DO I=1,M
DO J=1,N
DO K=1,L
OLDT(I,J,K)=T(I,J,K)
END DO
END DO
END DO
DO I=1,M
DO J=1,N
DO K=1,L
ERR(I,J,K)=T(I,J,K)-OLDT(I,J,K)
END DO
END DO
END DO
EMAX=0.0
EMAX=MAX(EMAX,ERR(I,J,K))
WRITE(*,*) ITER, EMAX
IF (ITER.LT.LAST) GOTO 31
WRITE(*,*) DR,A,B,E
END PROGRAM CYLINDRICAL FIN
In your long formula you have R without index. But R is a vector so that's why you get the error.
DO I=1,M
DO J=1,N
T(I,J,1)=400
END DO
END DO
can be written more swiftly as
T(1:M,1:N,1) = 400
also 400 is an integer so you better use 400.
I quickly converted the program to free-format and compiled it with gfortran. The problem line is:
T(I,J,K)=((R*DR*T(I+1,J,K)*(YZ)**2.0)-((T(I+1,J,K)+T(I-1,J,K))* &
(R*YZ)**2.0)-((T(I,J+1,K)+T(I,J-1,K))*(ZR**2.0))-((T(I,J,K+1)+ &
T(I,J,K-1))*(R*RY)**2.0))/((R*DR*(YZ)**2.0)-(2.0*(R*YZ)**2.0)- &
(2.0*(ZR)**2.0)-(2.0*(R*RY)**2.0))
The gfortran error message is:
"Error: Incompatible ranks 0 and 1 in assignment at (1)"
with the (1) designation the "T" on the LHS. Obviously the T(I,J,K) is a scaler of rank 0. Somewhere on the RHS you have an array of rank 1 -- identified by Azrael3000 as "R".
P.S. I recommend using "implicit none" and typing all of your variables. Implicit typing is pernicious, e.g., it allows typos in variable names to be accepted by the compiler.
Your problem comes from the array operation you are trying to perform.
If you simplify the line:
T(I,J,K)=((R*DR*T(I+1,J,K)*(YZ)**2.0)-((T(I+1,J,K)+T(I-1,J,K))*
+(R*YZ)**2.0)-((T(I,J+1,K)+T(I,J-1,K))*(ZR**2.0))-((T(I,J,K+1)+
+T(I,J,K-1))*(R*RY)**2.0))/((R*DR*(YZ)**2.0)-(2.0*(R*YZ)**2.0)-
+(2.0*(ZR)**2.0)-(2.0*(R*RY)**2.0))
You can end up with this other line that also shows the same error:
T(I,J,K)= T(I,J,K-1)*R
The shapes of the array expressions do not conform. [T]
So you can see that your problem comes from trying to assign an array R to a scalar T(I,J,K).