pbepack_quadratures.f90 Source File


This file depends on

sourcefile~~pbepack_quadratures.f90~~EfferentGraph sourcefile~pbepack_quadratures.f90 pbepack_quadratures.f90 sourcefile~pbepack_kinds.f90 pbepack_kinds.F90 sourcefile~pbepack_quadratures.f90->sourcefile~pbepack_kinds.f90 sourcefile~pbepack_lib.f90 pbepack_lib.f90 sourcefile~pbepack_quadratures.f90->sourcefile~pbepack_lib.f90 sourcefile~pbepack_lib.f90->sourcefile~pbepack_kinds.f90

Files dependent on this one

sourcefile~~pbepack_quadratures.f90~~AfferentGraph sourcefile~pbepack_quadratures.f90 pbepack_quadratures.f90 sourcefile~pbepack.f90 pbepack.f90 sourcefile~pbepack.f90->sourcefile~pbepack_quadratures.f90 sourcefile~pbepack_pbe.f90 pbepack_pbe.f90 sourcefile~pbepack.f90->sourcefile~pbepack_pbe.f90 sourcefile~pbepack_pbe.f90->sourcefile~pbepack_quadratures.f90

Source Code

module pbepack_quadratures
   use pbepack_kinds, only: rk
   use pbepack_lib, only: optval
   use hrweno_grids, only: grid1
   implicit none
   private

   public :: quadgrid1, evalmoment

   abstract interface
      pure real(rk) function fx(x)
      !! Interface integrand
         import rk
         real(rk), intent(in) :: x
            !! argument
      end function
   end interface

contains

   pure function quadgrid1(fnc, grid, average) result(res)
   !! Cell-integral or cell-average of \( f(x) \) over grid, using Simpson's 1/3 rule.
   !! ```
   !!   f(x) ^
   !!        |                * * * *
   !!        |          * * *++++++++++ *
   !!        |        *                  *
   !!        |     ++*++++++               *
   !!        |     *                    ++++*+++++
   !!        |                                 * *
   !!       -|----|----.----|-----.----|----.-----|---->
   !!               x_{i-i}      x_i      x_{i+1}
   !! ```
      procedure(fx) :: fnc
         !! function \( f(x) \) to integrate/average over grid cells
      type(grid1), intent(in) :: grid
         !! `grid1` object
      logical, intent(in), optional :: average
         !! flag to compute cell-average instead of cell-integral
      real(rk) :: res(grid%ncells)

      real(rk) :: fedges(0:grid%ncells), fcenter(grid%ncells)
      integer :: i

      associate (nc => grid%ncells)

         ! Evaluate f(x) at grid edges
         do concurrent(i=0:nc)
            fedges(i) = fnc(grid%edges(i))
         end do

         ! Evaluate f(x) at grid centers
         do concurrent(i=1:nc)
            fcenter(i) = fnc(grid%center(i))
         end do

         ! Cell-average using Simpson's 1/3 rule
         res = (4*fcenter + fedges(0:nc - 1) + fedges(1:nc))/6

         ! Convert cell-average to cell-integral
         if (.not. (optval(average, .false.))) then
            res = res*grid%width
         end if

      end associate

   end function quadgrid1

   pure real(rk) function evalmoment(u, grid, order, normalize) result(res)
   !! \(m\)-th order moment of \( u(x,t) \):
   !! $$
   !! M_m(t) = \int _0^\infty x^m u(x,t)dx = {\sum_i \bar{u_i}(t) \Delta x_i x_i^m}
   !! $$
      real(rk), intent(in) :: u(:)
         !! cell-average number density, \( \bar{u_i} \)
      type(grid1), intent(in) :: grid
         !! `grid1` object
      integer, intent(in) :: order
         !! order of the moment
      logical, intent(in), optional :: normalize
         !! if `true`, the result will be normalized by the 0-th moment

      ! Check `order`
      if (order < 0) then
         error stop "Invalid 'order'. Valid range: order >=0."
      end if

      ! Compute moment
      res = sum(u*grid%width*grid%center**order)

      ! Normalize if required
      if (optval(normalize, .false.)) then
         res = res/sum(u*grid%width)
      end if

   end function evalmoment

end module pbepack_quadratures