Writing a complex matrix to a file in Fortran - fortran

How does one write a complex (n×n) matrix in Fortran to a file?
For example:
DO I=1,N
write(14,'(100g15.5)') ( M(i,j), j=1,n )
ENDDO
In this example one gets 2n×n elements written to the file i.e. the real and imaginary.
Instead of two element, Re(a11) Im(a11), How can I write it as one element Re(a11)+iIm(a11)?

Use intrinsic functions REAL and AIMAG to write individual real and imaginary components of a complex number:
CHARACTER(LEN=3),DIMENSION(n,n) :: imag_unit = '+i*'
WHERE(AIMAG(M)<0.)imag_unit = '-i*'
DO I=1,N
write(14,'(100(g15.5,a,g15.5,2x))') ( REAL(M(i,j)),imag_unit(i,j),&
ABS(AIMAG(M(i,j))), j=1,n )
ENDDO
Explanation: This code defines a matrix of character strings that have value '+i' when imaginary part is positive, and '-i' where imaginary part is negative. Because the negative imaginary part is accounted for in the formatting ('-i'), we take absolute value of the imaginary part. Edit the format descriptor accordingly so that the program you use to read the output file will be able to read it.

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.

Free-dimensional array as input in subroutine

I am trying to write a subroutine that can take as input a one-dimensional array OR a two-dimensional array. How can I declare that the input of the subroutine can be either be a vector or a matrix?
If I do this:
SUBROUTINE TEST1(x)
REAL, INTENT(IN) :: x(:)
<do something>
END SUBROUTINE TEST1
I clearly cannot pass a matrix as an input in the subroutine. A non-elegant solution could be to pass the matrix in vectorized form and then re-arrange it in matrix form inside the subroutine (I would need a couple of extra inputs, of course). Is there a better way of doing this?
creating a generic interface seems a pretty clean way to do it. (per comment, but I though worth writing up )
module gen
interface test1
module procedure t1,t2
end interface
contains
subroutine t1(y)
real y(:)
write(*,*)'shape is',shape(y)
y=2*y
end subroutine
subroutine t2(y)
real y(:,:)
write(*,*)'shape is',shape(y)
y=2*y
end subroutine
end module
use gen
real m(4),n(3,3)
m=4
n=3
call test1(m)
call test1(n)
end
With Intel you can also use MAP/UNION, so you can pass the 1d as a one 1d, and also pass the 2D as it's MAP/UNION 1D version.
You may want to use RESHAPE, but usually it is not needed, depending on what you are doing.
Your comment of "clearly cannot pass in a matrix" seems counter to what I know. If it is 2D, and always 2D, then there is no issue whatsoever. You can pass any rank in.

How to write in Fortran the equivalent of MATLAB's diff function?

I'd like to write a function/subroutine in Fortran90 which does the same as MATLAB's diff function, that is, it receives a multidimensional array A and an integer dim and calculates differences between adjacent elements of A along the array dimension specified by dim.
First of all, should it be a function or a subroutine? And why?
How to deal with the dimensions of A? For instance, if A is sized (a,b,c), the output should be sized (a,b-1,c) if dim is 2; and
I think the length along each dimensions is not a problem. But I don't know to handle the number of dimensions.
EDIT:
I got the point about the intrinsic function eoshift, that is, I could eoshift the matrix A along the dimension dim and then subtract it from the original one. Doing so, unfortunately, the output matrix would be iso-sized to A, whereas it should have the extent along the dimension dim diminished by 1. In this sense, I don't know how to declare an array based on a given shape (REAL, DIMENSION(shape(A)) :: B doesn't work). Actually, I don't now how to declare a variable of unknown rank in a function/subroutine.
In the end I chose to follow the path proposed by #Vladimir F (am I right?)
MODULE module1
IMPLICIT NONE
INTERFACE lininterpmid1D
MODULE PROCEDURE midpoint_1D
MODULE PROCEDURE midpoint_2D
MODULE PROCEDURE midpoint_3D
MODULE PROCEDURE midpoint_4D
MODULE PROCEDURE midpoint_5D
MODULE PROCEDURE midpoint_6D
MODULE PROCEDURE midpoint_7D
END INTERFACE lininterpmid1D
PRIVATE
PUBLIC :: lininterpmid1D
CONTAINS
... ! here are the 7 functions of the interface
END MODULE module1

Fortran 90 read file

I am getting my hands wet with Fortran, and am wanting to read a txt file into a an array. I feel like I have tried everything. The txt file is comma seperated 11 rows with 1 number on each row.
Here is my code
program test
real:: obs1,i,jj,count,x_1
real,allocatable:: x(:)
open(1,file='data1.txt',status='old',action='read')
read(1,*) obs1
allocate(x(obs1))
do i=1, obs1
read(1,*) x_1
x(i)=x_1
end do
do jj=1, obs1
print*,x(jj)
end do
end program test
this is the error I am receiving:
The highest data type rank permitted is INTEGER(KIND=8)
This statement
allocate(x(obs1))
contains an error, though I'm not sure it's the one that matches the error message you report. obs1 is a real variable, but array dimensions (and indices) have to be integers. Change the declaration of obs1 to
integer :: obs1
Your compiler ought to complain about using a real variable in the do loop control too, do i=1, obs1. Again, use an integer.
As an aside, since you are new to Fortran, learn to use implicit none in every scope within your programs. SO will provide many questions and answers to explain what it means and why it is important, so will any of your favourite Fortran tutorials.

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