Using Function Block in Fortran - Newton Raphson - fortran

I am trying apply the function block for Newton Raphson and am a bit lost. My script is suppose to ask the user for an initial X as i've hardcoded the equation. My output file seems to just be stating zero's instead of the proper output listing it's convergence. I'm assuming i'm calling my write statement wrong or too early? Any help is appreciated.
On a side note...is it possible to also ask the user for both the equation and init value as in other languages?
program main
implicit none
real :: x0, xn, err
write(*,*) "Please enter an initial guess X0."
read(*,*) x0
write(*,*) "x = ", xn, " error = ", err
end program main
real function f(x0)
real :: x0, xn,
do
xn = x0 - ( (x0**3 - (x0) - 1) / ( ( 3*(x0**2) )-1) )
err = 100*abs( (xn-x0)/x0 )
x0 = xn
if (err < 0.000001)exit
return
end do
end function

In your code you never call function f, so how do you expect your program to work?
Even if you did call f, the variables xn and err that you declare and set in function f are local to that function, and they will not change the values of x0 and xn in the main program. Use a subroutine to pass multiple values back to the main program.

As #Fortranner stated, you need to call the function. You will find your Fortran programming easier if you place your subroutines and functions in a module and use that module from the calling program. For an example of this organization, see Computing the cross product of two vectors in Fortran 90.
Re "is it possible to also ask the user for both the equation and init value"? That is a very general question. If your equation is always a polynomial, you could easily ask the user for the values of the coefficients. Or you could have a list of equations to select from. But entering a totally arbitrary equation at run-time is something like asking to write a scripting language in Fortran -- definitely non-trivial.
I suggest that while developing a program that you use all available warning and checking options of your compiler. For example, using such options gfortran points out that you don't define the return value of f in function f. Which is a hint that the communication between the main program and function has problem(s).

Related

How to verify in Fortran whether an iterative formula of a non-linear system will converge

How to verify in Fortran whether an iterative formula of a non-linear system will converge to the root near (x,y)?
It was easy for a programming language which support symbolic computations. But how to do that in Fortran? Like getting partial derivative of the component functions and check whether they bounded near the root. But I couldn't do that in fortran or haven't the idea how to do that. It will be a great help for me if anyone give me some idea for the following non-linear system now or if possible for a general case.
I want to use Fixed point iteration method for this case
Main system:
x^2+y=7
x-y^2=4
Iterative form (given):
X(n+1)=\sqrt(7-Y(n)),
Y(n+1)=-\sqrt(X(n)-4),
(x0,y0)=(4.4,1.0)
Theorem (which I follow)
The issue is, I need to check the boundedness of the partial derivatives of \sqrt(7-Y) and -\sqrt(X-4) on some region around (x0,y0)=(4.4,1.0). I can write the partial derivative function in fortran but how to evaluate so many values and check it is bounded around the (4.4,1.0).
Update
One possibly right solution would be to get arrays of values around (4.4,1.0) like (4.4-h,1.0-h)*(4.4+h,1.0+h) and evaluate the defined partial derivative function and approximate their boundedness. I haven't encounter such problem in Fortran, so any suggestion on that also can help me a lot.
If you just want to check the boundedness of a function on a grid, you can do something like
program verify_convergence
implicit none
integer, parameter :: dp = selected_real_kind(15, 307)
real(dp) :: centre_point(2)
real(dp) :: step_size(2)
integer :: no_steps(2)
real(dp) :: point(2)
real(dp) :: derivative(2)
real(dp) :: threshold
integer :: i,j
real(dp) :: x,y
! Set fixed parameters
centre_point = [4.4_dp, 1.0_dp]
step_size = [0.1_dp, 0.1_dp]
no_steps = [10, 10]
threshold = 0.1_dp
! Loop over a 2-D grid of points around the centre point
do i=-no_steps(1),no_steps(1)
do j=-no_steps(2),no_steps(2)
! Generate the point, calculate the derivative at that point,
! and stop with a message if the derivative is not bounded.
point = centre_point + [i*step_size(1), j*step_size(2)]
derivative = calculate_derivative(point)
if (any(abs(derivative)>threshold)) then
write(*,*) 'Derivative not bounded'
stop
endif
enddo
enddo
write(*,*) 'Derivative bounded'
contains
! Takes a co-ordinate, and returns the derivative.
! Replace this with whatever function you actually need.
function calculate_derivative(point) result(output)
real(dp), intent(in) :: point(2)
real(dp) :: output(2)
output = [sqrt(7-point(2)), -sqrt(point(1)-4)]
end function
end program
I know the function calculate_derivative doesn't do what you want it to, but I'm not sure what function you actually want from your question. Just replace this function as required.
The main question is different: How can you calculate the solution of the mathematical problem without the help of any software? If you know that, we can program it in fortran or any language.
In particular, and assuming that n=0,1,2,3... to solve your problem you need to know X(0) and Y(0). With this you calculate
X(1)=\sqrt(7-Y(0)),
Y(1)=-\sqrt(X(0)-4)
Now you know X(1) and Y(1), then you can calculate
X(2)=\sqrt(7-Y(1)),
Y(2)=-\sqrt(X(1)-4)
etc.
If your system of equations converge to something, until some iterations (for example, n=10, 20, 100) you going the check that. But because the nature of fortran, it will not give you the solution in a symbolic way, it is not its goal.

Newton-Raphson Method Using Fortran 90

I developed the code below for finding the roots of the given polynomial. It works fine, but I need to adapt it to find all roots and not simply stop when it converges. How do I go about doing this? I thought about creating an outer do loop for values of x, but I'm uncertain whether this is the right approach. Any help is appreciated, thanks in advance.
PROGRAM nr
integer :: i
real :: x, f, df
write(*,*) "x=?"
read (*,*) x
write (*,*) '# Initial value: x=',x
do i=1,100
f= x**4 - 26*(x**3) + 131*(x**2) - 226*x + 120
df = 4*(x**3) - 3.0*26*(x**2) + 2.0*131*x - 226
write (*,*) i,x,f,df
x = x-f/df
end do
write (*,*) '#x = ',x
END PROGRAM
A possible algorithm to find all roots of the polynomial P consists in:
Start from some X0 and find a root R, using Newton's algorithm.
Divide P by (X-R): the division is exact (up to numerical error) since R is a root. (this step is called deflation)
Restart from the beginning if the quotient has degree > 1.
There are some subtleties:
If your polynomial has real coefficients and X0 is real, you will only find a real root, if there is any. To find complex roots, you then have to start from a complex X0, and of course use complex arithmetic.
Not all values of X0 will guarantee convergence, as Newton-Raphson is a local method. See Newton-Kantorovitch theorem and basins of attraction of the Newton method.
If there are multiple roots, convergence there is much slower. There are ways to adapt Newton's method to deal with this.
Numerical errors introduced in the deflation step add up and usually leads to poor accuracy of the subsequent roots. This is especially a problem for polynomials of high degree (how much high really depends). In extreme cases, the computed roots can be quite far from the exact roots. Furthermore, some polynomials are more "difficult" than others: see for instance Wilkinson's polynomial.
There are ways to find information on the roots (bound on the absolute values, circles enclosing the roots...), this can help to pick a good X0 in the algorithm: see Geometrical properties of polynomial roots. If you are only looking for real roots of a real polynomials, you first find bounds, then use Sturm's theorem to find intervals enclosing the roots. Another approach in the real case is to first find the roots of the derivative P' (and to find its roots, first find roots of P'', etc.), as the roots of P' separate the roots of P (except for multiple roots).
Another suggested reading: Roots of polynomials. Note that there are much better algorithms than Newton+deflation. There are also algorithms designed to find all the roots.
However, if you are only interested in this specific polynomial, I suggest to first have a look at the problem, as it's much easier than the general case: WolframAlpha.
Here, starting with integer values of X0 is going to work quite well...
Anyway, I give you below what I think is a better Newton-Raphson code, using Fortran-90 function declaration and a "while" rather than a blind "do". Best, Fabio M. S. Lima
PROGRAM Newton2
! Newton-Raphson method in Fortran-90
implicit none
integer i,imax
real x,xnew,tol
parameter (imax = 30)
parameter (tol = 0.00001)
print*, '*** Initial value: '
read*,x
xnew = 0.5 !Just to begin the loop below
i=0
do while ((abs(xnew-x)>tol) .and. (i<imax))
i=i+1
x = xnew
xnew = x -f(x)/f1(x)
print*, i,xnew,f(xnew)
end do
if (i>imax-2) then
print*,'# Error: Newton-Raphson has not converged after ',i,' iterations!'
else
print*,'* After ',i,' iterations, we found a root at ',xnew
endif
contains
function f(z)
real z,f
f = z**4 -26.0*(z**3) +131.0*(z**2) -226.0*z +120.0
end function f
function f1(z)
real z,f1
f1 = 4.0*(z**3) -3.0*26.0*(z**2) +2.0*131.0*z -226.0
end function f1
END PROGRAM Newton2

Syntax Error/Two main programs Fortran

I'm trying to compile this program for monte carlo importance sampling, but i'm running into a couple issues:
1 - Error: Syntax error in data declaration at (1), referring to the following line, where the (1) is placed right after and beneath the word "function".
real function f(x)
2 - Error: Two main PROGRAMS at (1) and (2), referring to these two lines
program importance1
and
t=0.0
.
The sample code follows. There are more lines of code in the program, but I don't think there are any problems so I've just posted this first segment.
program importance1
implicit none
real mean_value,t,ta,rr
real x,xtrials,s_square_old,s_square_new,std_dev,std_error,frac_stand_dev
integer k
real :: alpha=0.90
integer :: trials=50
xtrials=trials
real function f(x)
f=exp(x)
return
end
real function g(x)
g=(alpha/(exp(alpha)-1.))*exp(alpha*x)
return
end
t=0.0
s_square_old=0.0
Not sure where you got the idea to do that, but it looks like you are defining functions in the middle of your code, which is the wrong place. In Fortran, the functions go in a separate MODULE or at the end of the program under a CONTAINS block:
program importance1
implicit none
real :: mean_value,t,ta,rr
real :: x,xtrials,s_square_old,s_square_new,std_dev,std_error,frac_stand_dev
integer :: k
real :: alpha=0.90
integer :: trials=50
xtrials=trials
t=0.0
s_square_old=0.0
contains
real function f(x)
real :: x
f=exp(x)
end function
real function g(x)
real :: x
g=(alpha/(exp(alpha)-1.))*exp(alpha*x)
end function
end program

FORTRAN 95: OPTIONAL statement does not work (using FTN95 and Plato)

I am having a problem with the OPTIONAL statement in functions and subroutines with Fortran 95. Currently I am using Silverfrost's Plato and their FTN95 compiler (in "Release Win32" mode). After trying to implement the OPTIONAL statement in a more complex program I am writing, I created a very simple program to test it. Here is the code:
program TEST
implicit none
integer :: a=1, b=2
call Z(a,b)
call Z(a)
call Z(b)
end program TEST
subroutine Z(x,y)
implicit none
integer :: x
integer, optional :: y
if (present(y)) then
write(*,*) x, y
else
write(*,*) x
endif
end subroutine Z
I expected the following result displayed on the screen:
1 2
1
2
Well, the code compiles, although I get a warning (673) that "SUBROUTINE Z has been called with too few arguments". After executing it, I get on my screen:
1 2
and then an "Access violation" error message. Can somebody understand what is wrong here?
Thanks a lot!
Gilberto
Try putting the subroutine in a module, like so:
module testoptional
contains
subroutine Z(x,y)
implicit none
integer :: x
integer, optional :: y
if (present(y)) then
write(*,*) x, y
else
write(*,*) x
endif
end subroutine Z
end module testoptional
program TEST
use testoptional
implicit none
integer :: a=1, b=2
call Z(a,b)
call Z(a)
call Z(b)
end program TEST
Compiling and running then gives the expected result using gfortran and ifort.
The problem is in how the main program knows (or guesses) the interface to Z(x,y). In the code you provide, although the main program and the subroutine are in the same file, there's nothing explicitly telling the main program the interface - the calling sequence, including argument counts, types, etc - of Z. The first call is to Z(a,b), so it infers there's a subroutine out there somewhere that takes two parameters; then it tries calling it with one parameter, which fails.
Putting the subroutine in a module, then using the module (you could also use contains for a contained subroutine, or explicitly/manually providing the main program the interface using an interface block) then gives the main program the information it needs about the calling sequence - e.g., that there's an optional argument - and things work correctly.
Procedures with optional arguments must have explicit interfaces, so try giving one to Z. (E.g. just use the subroutine from a short module.)
I don't have this specific compiler on hand, but I've gotten an error when using the Cray compiler for cases like this.

Fortran, static library creating and simplifying (newbie here)

I'm somewhat new to Fortran, but I'm starting to collect a lot of functions and subroutines in modules that I use over and over again. I've been trying to build my own library so that I could call some of these functions and subroutines from new source code that I write. So far I've been able to get the subroutines to work, but not the functions. I just don't know how to call the function from with in the code.
Here's an example. The following function takes in an integer and returns the Identity matrix.
module test
contains
function IDENTITY(rows) !RETURNS THE IDENTITY MATRIX
real, dimension(rows,rows) :: IDENTITY
integer, intent(in) :: rows
integer :: i, j
!f2py intent(in) rows
!f2py intent(out) IDENTITY
!f2py depend(rows) IDENTITY
IDENTITY = ZEROS(rows,rows)
do i = 1, rows
do j = 1, rows
if (i == j) then
IDENTITY(i,j) = 1
endif
enddo
enddo
end function IDENTITY
end module
Now I compile this into an object file then archive it into a library. I then write a small program in which I'd like to use this function--and here's the problem I want to avoid. I've figured I have to put a \use\ statement in my source so that it will use the module. Then I've got to include the path to the .mod when compiling. But eventually, I'm going to have a whole section full of use statements. I'd like to avoid having to do all those things and just make everything nice and neat. Is there a way? Any help would be great,
Thank You
You can put many subroutines and functions into the contains section of one module. You don't need a separate module for each. It makes sense to organize your code by creating modules/files for related procedures (subroutines and functions).
Libraries are a good strategy that I used to use. In this era
I usually don't bother with the library. Compilers are so fast that I just compile the files with the modules needed by the program. It depends on how big your code is.
You invoke a subroutine with a call statement. You invoke a function by using it in an expression such as an assigment statement:
x = sin (y)
matrix = identity (n)
P.S. Instead of:
do i = 1, rows
do j = 1, rows
if (i == j) then
IDENTITY(i,j) = 1
endif
enddo
enddo
why not:
do i = 1, rows
IDENTITY(i,i) = 1
enddo
Do you have a function ZEROS to zero your matrix? The language will do that with an assigment statement:
IDENTITY = 0.0