Type that is a real OR an array of reals

Viewed 70

I have the following problem:

I have a module containing some fortran function, which takes 2 (mathematical) functions as its input. The way I do this at the moment is by defining an interface for the input functions. My module looks like this:

module myModule
   implicit none
   save 
   
       abstract interface
        subroutine functype1(x,f) 
            import dp 
            real(kind=dp), dimension(:),intent(in) :: x
            real(kind=dp), dimension(:),intent(out):: f
        end subroutine

        subroutine functype2(x,M)
            import dp 
            real(kind=dp), dimension(:),intent(in) :: x 
            real(kind=dp), dimension(:,:),intent(out):: M
        end subroutine
    end interface

contains 

      function taylorExpansion(func,funcdiff)
          procedure(functype1) :: func ! The mathematical function f
          procedure(functype2) :: funcdiff ! The function evaluating the derivative/gradient of f
          
          ! ...
          ! (further implementation)
          ! ...
      end function

The problem is now that I want functype1 to be kind of general: sometimes the input is just a real, sometimes it's an array of reals. Is it possible to do this smoothly? (At the moment I'm forced to pass an array of size 1 to func1 instead of a real, which is quite clumsy)

Another way to formulate this is: is it possible to make a type which is a real OR an array of reals? This way both calls would be possible:

program testprog
     use myModule
     implicit none
     save 
     
     call taylorExpansion(xsquared,xdiff) ! functype1 can accept reals
     call taylorExpansion(vectornorm,vectornormdiff) ! functype1 can also accept vectors
contains 
     subroutine xsquared(x,fx)
          real(kind=dp) :: x
          real(kind=dp) :: fx
          fx = x**2
     end subroutine 

     subroutine twox(x,fx)
          real(kind=dp) :: x
          real(kind=dp) :: fx 
          fx = 2*x
     end subroutine 

     subroutine vectornorm(x,fx)
          real(kind=dp), dimension(:) :: x
          real(kind=dp) :: fx=0.0
          integer i
          
          do i = 1,size(x)
              fx = fx + x(i)**2
          end do
      end subroutine

     subroutine vectornormdiff(x,fx)
          real(kind=dp), dimension(:) :: x
          real(kind=dp), dimension(:) :: fx
          integer i
          
          do = 1,size(x)
             fx(i) = 2*x(i)
          end do
      end subroutine

end program



0 Answers
Related