0

I was trying to create a program that requires me to use matrices as input for functions and subroutines and also requires me to take matrix as subroutine output in Fortran. But, I've encountered multiple errors while doing so. I am not able to understand the source of these errors and hence how to fix them. I'm confident of the logic but I seem to be making errors in dealing with the matrices.

Program to solve system of linear equations(Gauss elimination with partial pivoting)

Code:

program solving_equations
implicit none

real, allocatable :: a(:,:),interchanged(:,:)
real, allocatable :: x(:)
real addition,multiplying_term,alpha,maximum
integer i,j,row,rth_ele,f_maxfinder,k,n,s,inte

read(*,*)n
allocate(  a( n,(n+1) )  )
allocate( x(n) )
allocate(  interchanged( n,(n+1) )  )

do i=1,n
read(*,*)( a(i,j),j=1,(n+1) )
end do

do rth_ele= 1,(n-1) 
  row=f_maxfinder( a , n , rth_ele )

  if (row==rth_ele) then
  continue

  else
 call interchanger(a,rth_ele,row,n,interchanged)
 a = interchanged
  
  end if      
        
        do i= (rth_ele+1) , n
        ! once i is fixed, multiplying term is fixed too
        multiplying_term=( a(i,rth_ele)/a(rth_ele,rth_ele) )
            
            do j=1,(n+1)
            a(i,j)=a(i,j)-a(rth_ele,j)*multiplying_term
            end do
       end do   
end do      

x(n)=a(n,n+1)/a(n,n)
do i=(n-1),1,-1
addition=0.0
    
    do s=n , (i+1) , -1
    addition=addition+a(i,s)*x(s)
    end do

x(i)= (   ( a(i,n+1)- addition  )/a(i,i)  )
end do

do i=1,n
print*,x(i)
end do

endprogram solving_equations

!=================

function f_maxfinder(a,n,rth_ele)
integer inte,f_maxfinder
real maximum
maximum=a(rth_ele,rth_ele)

do inte=n,nint(rth_ele+1),-1
  if(  a(inte,rth_ele) > maximum  ) then
  maximum = a(inte,rth_ele)
  f_maxfinder=inte
  
  else
  continue
  
  end if
end do
end  


subroutine interchanger( a,rth_ele,row,n,interchanged )
integer i
real alpha
real, allocatable :: interchanged(:,:)
allocate(  interchanged( n,(n+1) )  )

do i=1,n+1
alpha=a(row,i)
a(row,i)=a(rth_ele,i)
a(rth_ele,i)=alpha
end do

do i=1,n
do j=1,(n+1)
interchanged(i,j)=a(i,j)
end do
end do

end

Errors:

   row=f_maxfinder( a , n , rth_ele )
                   1
Warning: Rank mismatch in argument 'a' at (1) (scalar and rank-2)

 a(row,i)=a(rth_ele,i)

Error: The function result on the lhs of the assignment at (1) must have the pointer attribute.

 a(rth_ele,i)=alpha

Error: The function result on the lhs of the assignment at (1) must have the pointer attribute.

  call interchanger(a,rth_ele,row,n,interchanged)
                  1
Error: Explicit interface required for 'interchanger' at (1): allocatable argument

Thanks!

2 Answers 2

3
  1. You're missing a declaration of a as an array in f_maxfinder. implicit none is your friend - be sure to use it all the time.
  2. interchanger has a dummy argument interchanged that is an allocatable, assumed-shape array. This requires that an explicit interface to interchanger be visible in the caller. (See my post https://stevelionel.com/drfortran/2012/01/05/doctor-fortran-gets-explicit-again/ for more on this.

The interface issue could be solved by putting the subroutines in a module and adding a use of the module in the main program.

By the way, there's no need to make a allocatable in f_maxfinder, as you are not allocating or deallocating it. It is still an assumed-shape array so the explicit interface is still required.

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a working example taking into account @SteveLionel's advice and the following comments:

  1. Always use implicit none, at least once in the main program and don't forget to pass the -warn flag to the compiler.
  2. Either use a module for functions and subroutines, then add use <module> to the main program, or simply use contains and include them inside the main program as I did below.
  3. The interchanged array is already alcated in the main program, you don't need to re-allocate it in the interchanger subroutine, just pass it as an assumed-shape array.
  4. Remove unused variables; alpha, maximum, k, inte.
  5. Define a in f_maxfinder function.
  6. Function type is better written in front of the function name for readability; see your definition of f_maxfinder and don't declare the function again in main program, unless you're using an explicit interface.
  7. The nint procedure accepts real input, you don't need it here.
  8. Finally add any missing variable declarations in your function/subroutine.
program solving_equations
    implicit none

    real, allocatable :: a(:,:), interchanged(:,:), x(:)
    real :: addition, multiplying_term
    integer :: i, j, row, rth_ele, n, s

    read (*,*) n
    allocate ( a( n,(n+1) ) )
    allocate ( x( n ) )
    allocate ( interchanged( n,(n+1) ) )

    do i = 1,n
        do j = 1,(n+1)
            read (*,*) a(i,j)
        end do
    end do

    do rth_ele = 1,(n-1)
        row = f_maxfinder( a , n , rth_ele )

        if (row == rth_ele) then
            continue
        else
            call interchanger(a, rth_ele, row, n, interchanged)
            a = interchanged
        end if

        do i = (rth_ele+1) , n
            ! once i is fixed, multiplying term is fixed too
            multiplying_term = a(i,rth_ele) / a(rth_ele,rth_ele)
            do j = 1,(n+1)
                a(i,j) = a(i,j) - a(rth_ele,j) * multiplying_term
            end do
        end do
    end do

    x(n) = a(n,n+1) / a(n,n)
    do i = (n-1),1,-1
        addition = 0.0
        do s = n,(i+1),-1
            addition = addition + a(i,s) * x(s)
        end do
        x(i)= (a(i,n+1) - addition) / a(i,i) 
    end do

    do i = 1,n
        print *, x(i)
    end do

contains

integer function f_maxfinder(a, n, rth_ele)
    integer :: n, rth_ele, inte
    real :: maximum, a(:,:)
    maximum = a(rth_ele,rth_ele)

    do inte = n,rth_ele+1,-1
        if (a(inte,rth_ele) > maximum) then
            maximum = a(inte,rth_ele)
            f_maxfinder = inte
        else
            continue
        end if
    end do
end

subroutine interchanger( a, rth_ele, row, n, interchanged )
    integer :: i, rth_ele, row, n
    real :: alpha, a(:,:), interchanged(:,:)

    do i = 1,n+1
        alpha = a(row,i)
        a(row,i) = a(rth_ele,i)
        a(rth_ele,i) = alpha
    end do

    do i = 1,n
        do j = 1,(n+1)
            interchanged(i,j) = a(i,j)
        end do
    end do
end

end program solving_equations

Entering a sample 3-by-4 array, you get the following output (check the results, you know your algorithm):

3

4
3
6
3
7
4
6
7
4
4
2
0
   2.05263186
  -2.15789509
  0.210526198

Process returned 0 (0x0)   execution time : 1.051 s
Press any key to continue.

5 Comments

I got how your method works, the use of contains links the two sections. But, if I try to do without it and declare everything while taking every required argument in the function f_maxfinder and the subroutine interchanger, I am still getting the following errors: Explicit interface required for 'f_maxfinder' at (1): assumed-shape argument (1 is the line where I declare f_interchanger as integer in main prog) & Explicit interface required for 'interchanger' at (1): assumed-shape argument (1 is the line where I call the subroutine interchanger in the main program)
Best is to use module subprograms. Second best use contained subprograms. In modern code don't use external subprograms, they are much more prone to errors compared to contained or module subprograms. The errors you are getting from the compiler tell you why.
@IanBush Then, I guess I'm best off using the contains statement at the end of main program, before the subroutines and write the endprogram statement at the very end after subroutines
I do not fully agree with number 6. function() result() is more appealing and clear.
@user14812745 -- See number 2 above and the comment by Ian Bush, It is always advisable to write modules (this is especially true if you intend to reuse the functions/subroutines of the module and it will enable the compiler to perform the necessary checks without writing explicit interfaces) or include the subroutines and functions directly before the end of the main program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.