1

I am trying to write a procedure which takes in a predefined function procedure and performs the gaussian quadrature integration over some domain. I would like to integrate not only individual functions (say f(x)) but also products of 2 and 3 functions (f(x)*g(x))

I have successfully written the procedure which performs the Gaussian integration and have tested it to work with predefined function procedures. However, it does not work when I pass as input a product of two procedures. When I pass int = integral(S*phi,E_min,E_max,1) (see below for the integral procedure) the error that I get is Function ‘s’ requires an argument list

To solve this I attempted to write a procedure which takes in 3 function procedures and outputs the product of them. The way I have done that is the following

real(dp) function prod(func1,func2,func3)

    interface
       function func1(E,on)
         use f90_kind
         real(dp),intent(in)::E
         logical,intent(in)::on
         real(dp)::func1
       end function func1

       function func2(E,on)
         use f90_kind
         real(dp),intent(in)::E
         logical,intent(in)::on
         real(dp)::func2
       end function func2

       function func3(E,on)
         use f90_kind
         real(dp),intent(in)::E
         logical,intent(in)::on
         real(dp)::func3
       end function func3
    end interface

    prod = func1(E,on) * func2(E,on) * func3(E,on)

    end function prod

Which results in Type mismatch in argument ‘e’ at (1); passed REAL(4) to REAL(8). And this is where I get stuck. How do I make my integration procedure function take in as input any product of two or more predefined function procedures?

Here is the Gaussian integration function procedure

  real(dp) function integral(func,a,b,int_pts)

    interface
       function func(E,on)
         use f90_kind
         real(dp), intent(in) :: E
         logical,intent(in)   :: on
         real(dp)             :: func 
       end function func
    end interface

    real(dp),intent(in) :: a,b
    integer, intent(in) :: int_pts
    integer  :: idx1, idx2
    real(dp) :: dx,F1,F2,S,I,up_lim,low_lim
    logical  :: on

    real(dp),allocatable,dimension(:) :: point,weight
    integer, parameter :: nqp = 7
    allocate(point(nqp))
    allocate(weight(nqp))
    call legendre_set(point,weight)

    dx = (b-a)/int_pts
    I = 0.0_dp
    on = .false.

    do idx1 = 1,int_pts

       low_lim = a + (idx1-1)*dx
       up_lim  = a + idx1*dx
       F1 = (up_lim - low_lim)/2.0_dp
       F2 = (up_lim + low_lim)/2.0_dp
       S = 0.0_dp
       do idx2 = 1,nqp
          S = S + weight(idx2) * func(F1*point(idx2)+F2,on)
          !print *,"idx2 is",idx2,"func is",func(F1*point(idx2)+F2,on)
       enddo
       I = I + S * F1
       !print *,"Sum is",S
    enddo

    integral = I 

  end function integral

which works fine when I call it with integral(S,E_min,E_max,1), where S is one such predefined function.

Thanks

Tiberiu
  • 15
  • 3
  • Inside function `prod` you don't declare the type of the variable `e`. It's either implicitly typed `real(4)` or is explicitly typed that by some other means (such as host association). The functions `func1`, `func2` and `func(3)` are expecting the argument to be of type `real(8)`. – francescalus Aug 13 '19 at 08:47

1 Answers1

0

"When I pass int = integral(S*phi,E_min,E_max,1) (see below for the integral procedure) the error that I get is Function ‘s’ requires an argument list"

You cannot multiply a function, only a function result. Also, there are no lambda expressions in Fortran. You have to construct the actual function you want to integrate and pass it to the integration procedure.

You can (but don't have to) do it as an internal function.

int = integral(new_function,E_min,E_max,1)

contains

  function new_function(E,on)
         real(dp), intent(in) :: E
         logical,intent(in)   :: on
         real(dp)             :: new_function
     new_function = S(E, on) *phi

end ...

See the related Fortran minimization of a function with additional arguments Passing external function of multiple variables as a function of one variable in Fortran