String trimming for output format - fortran

This is my code:
Program String_Triming
Implicit none
Open(15, File = 'Output.txt')
Write(15,'(A,1x,"j",1x,A)') Ispis(20.45),Ispis(20.45)
Write(15,'(A,1x,"j",1x,A)') Ispis(-20.45),Ispis(-20.45)
Close(15)
Contains
Function Ispis ( Deg ) result ( Str )
Real,intent(in)::Deg
Character(len=16):: Str
If ( Deg > 0 ) then
Write(Str,'(F0.3)') 1000.0 + Deg
Str = Str(2:)
Else
Write(Str,'(F8.3)') 1000.0 + abs(Deg)
Write(Str,'("-",A)') Str(3:)
End If
End Function Ispis
End program String_Triming
The content of Output.txt file is:
020.450 j 020.450
-20.450 j -20.450
The result I want to get from this code is:
020.450 j 020.450
-20.450 j -20.450
How do I get that result? Is there way to trim the length of Str to Len=8 which is the length of 020.450?

It's not quite clear what you want. If all you want is to remove the spaces from the output file, why not just run it through sed instead of writing a Fortran Program:
$ cat Output.txt
020.450 j 020.450
-20.450 j -20.450
$ sed -r 's/ +/ /g' Output.txt
020.450 j 020.450
-20.450 j -20.450
If you want to produce output like this in the first place, you could 'overwrite' the first three characters of str with an integer format. Something like this:
function Ispis(Deg) result(Str)
real, intent(in) :: Deg
character(len=7) :: Str
write(Str, '(F7.3)') Deg
if ( Deg < 0 ) then
write(Str(:3), '(I3.2)') int(Deg)
else
write(Str(:3), '(I3.3)') int(Deg)
end if
end function Ispis
note: the length of 020.450 is 7, not 8.

This is the solution for getting wanted result:
Program Main
Implicit none
Open(15,File='Output.txt')
Write(15,'(1x,a,1x,"j",1x,a,1x,"Juhu!")') Writing_01(67.45),Writing_01(-4.04)
Write(15,'(1x,a,1x,"j",1x,a,1x,"Juhu!")') Writing_02(67.45),Writing_02(-4.04)
Close(15)
Contains
Function Writing_01 ( Deg ) Result ( Str )
Real,intent(in) :: Deg
Character(:),allocatable :: Str
Character(len = 15 ) :: Str_temp
If ( int( Deg ) > 0 ) then
Write(Str_temp , '(F0.2)' ) 100000.0 + Deg
Str_temp = Str_temp(2:)
Else
Write(Str_temp, '(F0.2)' ) 100000.0 + abs(Deg)
Str_temp = "-"//Str_temp(3:)
Endif
Str = trim ( adjustl ( Str_temp ))
End Function Writing_01
Function Writing_02 ( Deg ) Result ( Str_temp )
Real,intent(in) :: Deg
Character(:),allocatable :: Str_temp
Character(len=1561) :: Form_02 , Res
If (int( Deg ) > 0 ) then
Form_02 = '(i5.5,f0.2)' ! allow a total of 4 leading zeros.
Else
Form_02 = '(i5.4,f0.2)' ! "-" sign takes up one space, so 3 leading zeros remain.
Endif
Write(Res , Form_02 ) int( Deg ), abs( Deg - int( Deg ) )
Str_temp = trim ( adjustl ( Res ))
End Function Writing_02
End program Main

Related

How to properly format exponential scientific notation for a double precision value? [duplicate]

This question already has answers here:
Fortran assignment on declaration and SAVE attribute gotcha
(2 answers)
Does Fortran preserve the value of internal variables through function and subroutine calls?
(3 answers)
Closed last year.
I am overriding the concatenation operator to allow real values to be concatenated with strings.
function concatenateRealSigFigsWithString( floatIn, str ) result(cat)
! Arguments
character( len=* ), intent(in) :: str
real(8), intent(in) :: floatIn(2)
! Returns
character( len=: ), allocatable :: cat
! Variables
logical :: remove_decimal = .False.
real(8) :: float
character( len=16 ) :: float_as_str, fmt
integer :: sigfig, i
float = floatIn(1)
sigfig = int(floatIn(2))
do i = sigfig, 1, -1
if (float < 10.0_8**i .and. float > 10.0_8**(i-1) ) then
fmt = '(F' // sigfig + 1 // '.' // sigfig - i // ')'
if (i == sigfig) remove_decimal = .True.
end if
end do
if ( float < 1 ) then
fmt = '(F' // sigfig + 2 // '.' // sigfig // ')'
end if
if (float < 0.1 ) then
fmt = '(ES' // sigfig + 5 // '.' // sigfig - 1 // ')'
end if
if ( float > 10.0_8**sigfig ) then
fmt = '(ES' // sigfig+6 // '.' // sigfig-1 // ')'
end if
write(float_as_str,fmt) float
if (remove_decimal) float_as_str = float_as_str(1:len_trim(float_as_str)-1)
cat = trim(float_as_str) // str
! cat = fmt
end function concatenateRealSigFigsWithString
The real value is a actually a list. The first element is the number and the second is the significant figures. Values between 0 and 10^(sigfig) are given in decimal form. Otherwise, the value is given in scientific form. The concatenation works for all values except those greater than 10^(sigfig). So the focus of the issue here is in the line fmt = '(ES' // sigfig+6 // '.' // sigfig-1 // ')'. For example, a value of 300,000 that should be written to 3 significant figures is formatted as 3.00E+0.
I can't figure out why the exponent is only showing one digit instead of 2, since it should be 3.00E+05.
I have tried specifying the width of exponent like fmt = '(ES' // sigfig+6 // '.' // sigfig-1 // 'E2)' but that just gives me 3.00E+00. I also tried expanding the width in case I did my math wrong and the exponent was getting cut off, but all that did was increase leading white space.
Any idea why the exponent is not showing the true value. Here is the code I used to test it.
program test
interface operator(//)
procedure :: concatenateRealSigFigsWithString, concatenateStringWithInteger
end interface
real(8) :: sigfig = 3
print *, [2.337e-7_8, sigfig] // " slugs"
print *, [2.337e-6_8, sigfig] // " slugs"
print *, [2.337e-5_8, sigfig] // " slugs"
print *, [2.337e-4_8, sigfig] // " slugs"
print *, [2.337e-3_8, sigfig] // " slugs"
print *, [2.337e-2_8, sigfig] // " slugs"
print *, [2.337e-1_8, sigfig] // " slugs"
print *, [2.337e0_8, sigfig] // " slugs"
print *, [2.337e01_8, sigfig] // " slugs"
print *, [2.337e02_8, sigfig] // " slugs"
print *, [2.337e03_8, sigfig] // " slugs"
print *, [2.337e4_8, sigfig] // " slugs"
print *, [2.337e5_8, sigfig] // " slugs"
print *, [2.337e6_8, sigfig] // " slugs"
print *, [2.337e7_8, sigfig] // " slugs"
print *, [2.337e8_8, sigfig] // " slugs"
print *, [2.337e9_8, sigfig] // " slugs"
print *, [2.337e10_8, sigfig] // " slugs"
contains
function concatenateStringWithInteger(str,int) result(cat)
! Arguments
character( len=* ), intent(in) :: str
integer, intent(in) :: int
! Returns
character( len=: ), allocatable :: cat
! Variables
character( len=9 ) :: int_as_str
write(int_as_str,'(I0)') int
cat = str // trim(int_as_str)
end function concatenateStringWithInteger
function concatenateRealSigFigsWithString( floatIn, str ) result(cat)
! Arguments
character( len=* ), intent(in) :: str
real(8), intent(in) :: floatIn(2)
! Returns
character( len=: ), allocatable :: cat
! Variables
logical :: remove_decimal = .False.
real(8) :: float
character( len=16 ) :: float_as_str, fmt
integer :: sigfig, i
float = floatIn(1)
sigfig = int(floatIn(2))
do i = sigfig, 1, -1
if (float < 10.0_8**i .and. float > 10.0_8**(i-1) ) then
fmt = '(F' // sigfig + 1 // '.' // sigfig - i // ')'
if (i == sigfig) remove_decimal = .True.
end if
end do
if ( float < 1 ) then
fmt = '(F' // sigfig + 2 // '.' // sigfig // ')'
end if
if (float < 0.1 ) then
fmt = '(ES' // sigfig + 5 // '.' // sigfig - 1 // ')'
end if
if ( float > 10.0_8**sigfig ) then
fmt = '(ES' // sigfig+6 // '.' // sigfig-1 // ')'
end if
write(float_as_str,fmt) float
if (remove_decimal) float_as_str = float_as_str(1:len_trim(float_as_str)-1)
cat = trim(float_as_str) // str
! cat = fmt
end function concatenateRealSigFigsWithString
end program test

Calling a subroutine, crashes the program, matrix passing

I was writing code to use Fortran Eispack routines (compute eigenvalues and eigenvectors, just to check if the values would be different from the ones I got from Matlab), but every time it calls the qzhes subroutine the program hangs.
I load matrixes from files.
Tried commenting the call, and it works without an issue.
I just learned Fortran, and with the help of the internet I wrote this code (which compiles and run):
program qz
IMPLICIT NONE
INTEGER:: divm, i, divg
INTEGER(kind=4) :: dimen
LOGICAL :: matz
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: ma
REAL(kind = 8), DIMENSION(:), ALLOCATABLE:: tabm
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: ga
REAL(kind = 8), DIMENSION(:), ALLOCATABLE:: tabg
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: zet
divm = 1
divg = 2
dimen = 20
matz = .TRUE.
ALLOCATE(ma(1:dimen,1:dimen))
ALLOCATE(tabm(1:dimen))
ALLOCATE(ga(1:dimen,1:dimen))
ALLOCATE(tabg(1:dimen))
OPEN(divm, FILE='Em.txt')
DO i=1,dimen
READ (divm,*) tabm
ma(1:dimen,i)=tabm
END DO
CLOSE(divm)
OPEN(divg, FILE='Gje.txt')
DO i=1,dimen
READ (divg,*) tabg
ga(1:dimen,i)=tabg
END DO
CLOSE(divg)
call qzhes(dimen, ma, ga, matz, zet)
OPEN(divm, FILE='Em2.txt')
DO i=1,dimen
tabm = ma(1:dimen,i)
WRITE (divm,*) tabm
END DO
CLOSE(divm)
OPEN(divg, FILE='Gje2.txt')
DO i=1,dimen
tabg = ga(1:dimen,i)
WRITE (divg,*) tabg
END DO
CLOSE(divg)
end program qz
...//EISPACK subrotines//...
Matrixes:
Gje.txt:https://drive.google.com/file/d/0BxH3QOkswLy_c2hmTGpGVUI3NzQ/view?usp=sharing
Em.txt:https://drive.google.com/file/d/0BxH3QOkswLy_OEtJUGQwN3ZXX2M/view?usp=sharing
Edit:
subroutine qzhes ( n, a, b, matz, z )
!*****************************************************************************80
!
!! QZHES carries out transformations for a generalized eigenvalue problem.
!
! Discussion:
!
! This subroutine is the first step of the QZ algorithm
! for solving generalized matrix eigenvalue problems.
!
! This subroutine accepts a pair of real general matrices and
! reduces one of them to upper Hessenberg form and the other
! to upper triangular form using orthogonal transformations.
! it is usually followed by QZIT, QZVAL and, possibly, QZVEC.
!
! Licensing:
!
! This code is distributed under the GNU LGPL license.
!
! Modified:
!
! 18 October 2009
!
! Author:
!
! Original FORTRAN77 version by Smith, Boyle, Dongarra, Garbow, Ikebe,
! Klema, Moler.
! FORTRAN90 version by John Burkardt.
!
! Reference:
!
! James Wilkinson, Christian Reinsch,
! Handbook for Automatic Computation,
! Volume II, Linear Algebra, Part 2,
! Springer, 1971,
! ISBN: 0387054146,
! LC: QA251.W67.
!
! Brian Smith, James Boyle, Jack Dongarra, Burton Garbow,
! Yasuhiko Ikebe, Virginia Klema, Cleve Moler,
! Matrix Eigensystem Routines, EISPACK Guide,
! Lecture Notes in Computer Science, Volume 6,
! Springer Verlag, 1976,
! ISBN13: 978-3540075462,
! LC: QA193.M37.
!
! Parameters:
!
! Input, integer ( kind = 4 ) N, the order of the matrices.
!
! Input/output, real ( kind = 8 ) A(N,N). On input, the first real general
! matrix. On output, A has been reduced to upper Hessenberg form. The
! elements below the first subdiagonal have been set to zero.
!
! Input/output, real ( kind = 8 ) B(N,N). On input, a real general matrix.
! On output, B has been reduced to upper triangular form. The elements
! below the main diagonal have been set to zero.
!
! Input, logical MATZ, should be TRUE if the right hand transformations
! are to be accumulated for later use in computing eigenvectors.
!
! Output, real ( kind = 8 ) Z(N,N), contains the product of the right hand
! transformations if MATZ is TRUE.
!
implicit none
integer ( kind = 4 ) n
real ( kind = 8 ) a(n,n)
real ( kind = 8 ) b(n,n)
integer ( kind = 4 ) i
integer ( kind = 4 ) j
integer ( kind = 4 ) k
integer ( kind = 4 ) l
integer ( kind = 4 ) l1
integer ( kind = 4 ) lb
logical matz
integer ( kind = 4 ) nk1
integer ( kind = 4 ) nm1
real ( kind = 8 ) r
real ( kind = 8 ) rho
real ( kind = 8 ) s
real ( kind = 8 ) t
real ( kind = 8 ) u1
real ( kind = 8 ) u2
real ( kind = 8 ) v1
real ( kind = 8 ) v2
real ( kind = 8 ) z(n,n)
!
! Set Z to the identity matrix.
!
if ( matz ) then
z(1:n,1:n) = 0.0D+00
do i = 1, n
z(i,i) = 1.0D+00
end do
end if
!
! Reduce B to upper triangular form.
!
if ( n <= 1 ) then
return
end if
nm1 = n - 1
do l = 1, n - 1
l1 = l + 1
s = sum ( abs ( b(l+1:n,l) ) )
if ( s /= 0.0D+00 ) then
s = s + abs ( b(l,l) )
b(l:n,l) = b(l:n,l) / s
r = sqrt ( sum ( b(l:n,l)**2 ) )
r = sign ( r, b(l,l) )
b(l,l) = b(l,l) + r
rho = r * b(l,l)
do j = l + 1, n
t = dot_product ( b(l:n,l), b(l:n,j) )
b(l:n,j) = b(l:n,j) - t * b(l:n,l) / rho
end do
do j = 1, n
t = dot_product ( b(l:n,l), a(l:n,j) )
a(l:n,j) = a(l:n,j) - t * b(l:n,l) / rho
end do
b(l,l) = - s * r
b(l+1:n,l) = 0.0D+00
end if
end do
!
! Reduce A to upper Hessenberg form, while keeping B triangular.
!
if ( n == 2 ) then
return
end if
do k = 1, n - 2
nk1 = nm1 - k
do lb = 1, nk1
l = n - lb
l1 = l + 1
!
! Zero A(l+1,k).
!
s = abs ( a(l,k) ) + abs ( a(l1,k) )
if ( s /= 0.0D+00 ) then
u1 = a(l,k) / s
u2 = a(l1,k) / s
r = sign ( sqrt ( u1**2 + u2**2 ), u1 )
v1 = - ( u1 + r) / r
v2 = - u2 / r
u2 = v2 / v1
do j = k, n
t = a(l,j) + u2 * a(l1,j)
a(l,j) = a(l,j) + t * v1
a(l1,j) = a(l1,j) + t * v2
end do
a(l1,k) = 0.0D+00
do j = l, n
t = b(l,j) + u2 * b(l1,j)
b(l,j) = b(l,j) + t * v1
b(l1,j) = b(l1,j) + t * v2
end do
!
! Zero B(l+1,l).
!
s = abs ( b(l1,l1) ) + abs ( b(l1,l) )
if ( s /= 0.0 ) then
u1 = b(l1,l1) / s
u2 = b(l1,l) / s
r = sign ( sqrt ( u1**2 + u2**2 ), u1 )
v1 = -( u1 + r ) / r
v2 = -u2 / r
u2 = v2 / v1
do i = 1, l1
t = b(i,l1) + u2 * b(i,l)
b(i,l1) = b(i,l1) + t * v1
b(i,l) = b(i,l) + t * v2
end do
b(l1,l) = 0.0D+00
do i = 1, n
t = a(i,l1) + u2 * a(i,l)
a(i,l1) = a(i,l1) + t * v1
a(i,l) = a(i,l) + t * v2
end do
if ( matz ) then
do i = 1, n
t = z(i,l1) + u2 * z(i,l)
z(i,l1) = z(i,l1) + t * v1
z(i,l) = z(i,l) + t * v2
end do
end if
end if
end if
end do
end do
return
end
I would expand the allocation Process
integer :: status1, status2, status3, status4, status5
! check the allocation, returnvalue 0 means ok
ALLOCATE(ma(1:dimen,1:dimen), stat=status1)
ALLOCATE(tabm(1:dimen), stat=status2)
ALLOCATE(ga(1:dimen,1:dimen), stat=status3)
ALLOCATE(tabg(1:dimen), stat=status4)
ALLOCATE(zet(1:dimen,1:dimen), stat=status5)
And at the end of the Program deallocate all arrays, because, you maybe have no memoryleak now, but if you put this program into a subroutine and use it several time with big matricies during a programrun, the program could leak some serious memory.
....
DO i=1,dimen
tabg = ga(1:dimen,i)
WRITE (divg,*) tabg
END DO
CLOSE(divg)
DEALLOCATE(ma, stat=status1)
DEALLOCATE(tabm, stat=status2)
DEALLOCATE(ga, stat=status3)
DEALLOCATE(tabg, stat=status4)
DEALLOCATE(zet, stat=status5)
You can check again with the status integer, if the deallocation was ok, returnvalue again 0.

Error: Syntax error in argument list at (1)

implicit none
character*20 fflname, oflname, oflname2
integer i, length, rn, s(100)
real*8 phase_shift
parameter ( length = 32768, phase_shift = 0.02 )
real*8 num, real_coeff, imag_coeff
real*8 amplitude(length), phase(length)
& ,imag_coeff_ps(length), real_coeff_ps(length)
oflname = "wvlt_coeff.data"
oflname2 = "selection.data"
fflname = "wvlt_coeff_ps.data"
open(12, file = oflname)
do i=1, length
read(12, *) num, real_coeff, imag_coeff
real_coeff_ps(i) = real_coeff
imag_coeff_ps(i) = imag_coeff
enddo
close(12)
open(13, file = oflname2)
do i=1, 100
read(13, *) rn
s(i) = rn
enddo
close(13)
do i=1, 100
amplitude(i) = sqrt( real_coeff(s(i))**2 + imag_coeff(s(i))**2 )
phase(i) = atan( imag_coeff(s(i))/real_coeff(s(i)) ) + phase_shift
real_coeff_ps(s(i)) = amplitude(i) * cos( phase(i) )
imag_coeff_ps(s(i)) = amplitude(i) * sin( phase(i) )
enddo
open(15, file = fflname)
do i=1, length
write(15, *) i, real_coeff_ps(i), imag_coeff_ps(i)
enddo
close(15)
stop
end
Errors:
hyxie#ubuntu:~$ gfortran '/home/hyxie/Documents/20161012/phase_shift2.f'
/home/hyxie/Documents/20161012/phase_shift2.f:35:40:
amplitude(i) = sqrt( real_coeff(s(i))**2 + imag_coeff(s(i))**2 )
1
Error: Syntax error in argument list at (1)
/home/hyxie/Documents/20161012/phase_shift2.f:36:36:
phase(i) = atan( imag_coeff(s(i))/real_coeff(s(i)) ) + phase_shift
1
Error: Syntax error in argument list at (1)
What is wrong with my coding?
real_coeff and image_coeff are not arrays, but you are accessing them as if they were. This results in a syntax error. Perhaps you intended to use real_coeff_ps and image_coeff_ps instead.

How to read a mixed text file and extract numbers only

I need to read the output of one of my simulators and store the values. the file name is forces.dat and contains a similar thing as the following:
# Forces
# CofR : (4.750000e-01 3.500000e-02 2.000000e-02)
# Time forces(pressure viscous porous) moment(pressure viscous porous)
2.633022e-02 ((6.268858e-02 -1.468850e+01 1.542745e-20) (1.000906e-03 8.405854e-06 -5.657665e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-8.779466e-18 8.442993e-19 -3.225599e-03) (-2.082489e-18 4.435609e-18 -1.572485e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
8.095238e-02 ((1.781333e-01 -1.468455e+01 -3.545427e-19) (2.362118e-03 2.014609e-05 1.691584e-16) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-3.344781e-18 -5.448339e-19 2.227502e-02) (5.092628e-18 -3.538718e-18 -1.203074e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
1.600000e-01 ((3.204471e-01 -1.467482e+01 -4.599174e-18) (6.936764e-03 1.303800e-04 4.836650e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-1.123589e-17 -4.344967e-19 5.591623e-02) (1.532415e-18 -1.345592e-18 -9.550750e-04) (0.000000e+00 0.000000e+00 0.000000e+00))
I want to know how should I write a Fortran subroutine to ignore the first 3 lines and then read the number of next lines and then the values of each line.
You can use this snippet which will keep a track of line numbers. Based on your requirement and nature of file, you can get the values of respective lines and can do the required.
string CurrentLine;
int LastLineNumber;
void NextLine()
{
// using will make sure the file is closed
using(System.IO.StreamReader file = new System.IO.StreamReader ("c:\\forces.dat"))
{
// Skip lines
for (int i=0;i<LastLineNumber;++i)
file.ReadLine();
// Store your line
CurrentLine = file.ReadLine();
LastLineNumber++;
}
}
In the above code, inside for loop you can put in your logic of file processing based on the lines you want to read.
Although I think it is easier to preprocess the file by some command-line tool (e.g. sed -e 's/(/ /g' -e 's/)/ /g' input.dat), we can also use Fortran directly by reading each line into a long character string and removing all the unnecessary parentheses:
program main
implicit none
integer, parameter :: mxline = 5000 !! choose appropriately
integer i, ios, finp, nl
character(500) str
real, save :: time( mxline )
real, dimension( 3, mxline ), save :: &
frc_pres, frc_visc, frc_poro, &
mom_pres, mom_visc, mom_poro
finp = 10
open( finp, file="input.dat", status="old" )
nl = 0
do
read( finp, "(a)", iostat=ios ) str
if ( ios /= 0 ) exit
str = trim( adjustL( str ) )
!! Skip comment or blank lines.
if ( str(1:1) == "#" .or. str == "" ) cycle
!! Replace parentheses with space.
do i = 1, len_trim( str )
if ( str(i:i) == "(" .or. str(i:i) == ")" ) str(i:i) = " "
enddo
!! Read data from the string.
nl = nl + 1
read( str, * ) time( nl ), &
frc_pres( :, nl ), frc_visc( :, nl ), frc_poro( :, nl ), &
mom_pres( :, nl ), mom_visc( :, nl ), mom_poro( :, nl )
enddo
close( finp )
!! Check.
do i = 1, nl
print *
print *, "time = ", time( i )
print *, "frc_pres = ", frc_pres( :, i )
print *, "frc_visc = ", frc_visc( :, i )
print *, "frc_poro = ", frc_poro( :, i )
print *, "mom_pres = ", mom_pres( :, i )
print *, "mom_visc = ", mom_visc( :, i )
print *, "mom_poro = ", mom_poro( :, i )
enddo
end program
If the data values can become very large (say, 1.0e100), please consider using double-precision reals so as not to loose necessary precision.

unexpected gfortran compiling error [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Recently, I started to lean fortran programming. I have seen the following code at youtube without any error it is compiled. But I have got some errors.
I appreciate any help
program
implicit none
real, parameter :: pi=4*atan(1.0)
integer, parameter :: n = 100
real :: dimension(1:n) :: x, y
real :: a=0.0, b = 2*pi
real :: increment
integer :: i
increment = (b-a)/(real(n)-1)
x(1)=0.0
do i =2,n
x(i) = x(i-1) + increment
end do
y = sin(x)
print *, x(1:5)
print *, y(1:5)
end program
real :: dimension(1:n) :: x, y is a syntax error. Replace the first :: with a comma. You may need to give a name on the program statement.
You also have mixed-mode arithmetic in line
increment = (b-a)/(real(n)-1)
It will probably compile, and it may not even affect the program, but you should never, never have mixed-mode arithmetic in any programming language as it can cause strange, hard to find bugs.
It should look like this:
increment = (b-a)/(real(n)-1.0)
Here are the results of a working example which addresses the concerns of #High Performance Mark.
host system = (redacted)
compiler version = GCC version 5.1.0
compiler options = -fPIC -mmacosx-version-min=10.9.4 -mtune=core2 -Og -Wall -Wextra -Wconversion -Wpedantic -fmax-errors=5
execution command = ./a.out
Compare mesh points
1.57017982 1.57080817 1.57143652
1.57016802 1.57079625 1.57142460
Compare function values at these mesh points
1622.04211 -84420.7344 -1562.01758
1591.57471 13245402.0 -1591.65527
There is a bad programming practice in the demo you found: moving through the mesh by adding steps (+ increment) instead of counting them (k * increment). The problem is widespread and appears with severe consequences (https://www.ima.umn.edu/~arnold/disasters/patriot.html).
For demonstration on your code, the size of the mesh was boosted to 10K points. Also the sample function changed from cos x to tan x and we examine points near the singularity at pi/2 = 1.57079633. While the novitiate may find the discrepancies in mesh values trivial, the difference in function values is significant.
(Mesh errors can be reduced by using increments which have exact binary representation like 2^(-13) = 1 / 8192.)
The code is shown here. The compilation command is gfortran -Wall -Wextra -Wconversion -Og -pedantic -fmax-errors=5 demo.f95. The run command is ./a.out.
program demo
use iso_fortran_env
implicit none
real, parameter :: pi = acos ( -1.0 )
integer, parameter :: n = 10001
real, dimension ( 1 : n ) :: x, y, z
real :: a = 0.0, b = 2 * pi
real :: increment
integer :: k, quarter, status
character ( len = * ), parameter :: c_options = compiler_options( )
character ( len = * ), parameter :: c_version = compiler_version( )
character ( len = 255 ) :: host = " ", cmd = " "
! queries
call hostnm ( host, status )
call get_command ( cmd )
! write identifiers
write ( *, '( /, "host system = ", g0 )' ) trim ( host )
write ( *, '( "compiler version = ", g0 )' ) c_version
write ( *, '( "compiler options = ", g0 )' ) trim ( c_options )
write ( *, '( "execution command = ", g0, / )' ) trim ( cmd )
increment = ( b - a ) / ( n - 1 )
quarter = n / 4
! mesh accumulates errors
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = x ( k - 1 ) + increment
end do
y = tan ( x )
print *, 'Compare mesh points'
print *, x ( quarter : quarter + 2 )
! better mesh
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = ( k - 1 ) * increment
end do
z = tan ( x )
print *, x ( quarter : quarter + 2 )
print *, 'Compare function values at these mesh points'
print *, y ( quarter : quarter + 2 )
print *, z ( quarter : quarter + 2 )
end program demo