example1_burgers_1d_fv Program

Uses

  • program~~example1_burgers_1d_fv~~UsesGraph program~example1_burgers_1d_fv example1_burgers_1d_fv iso_fortran_env iso_fortran_env program~example1_burgers_1d_fv->iso_fortran_env module~hrweno_fluxes hrweno_fluxes program~example1_burgers_1d_fv->module~hrweno_fluxes module~hrweno_grids hrweno_grids program~example1_burgers_1d_fv->module~hrweno_grids module~hrweno_kinds hrweno_kinds program~example1_burgers_1d_fv->module~hrweno_kinds module~hrweno_tvdode hrweno_tvdode program~example1_burgers_1d_fv->module~hrweno_tvdode module~hrweno_weno hrweno_weno program~example1_burgers_1d_fv->module~hrweno_weno stdlib_strings stdlib_strings program~example1_burgers_1d_fv->stdlib_strings module~hrweno_fluxes->module~hrweno_kinds module~hrweno_grids->module~hrweno_kinds stdlib_optval stdlib_optval module~hrweno_grids->stdlib_optval module~hrweno_kinds->iso_fortran_env module~hrweno_tvdode->module~hrweno_kinds module~hrweno_tvdode->stdlib_optval module~hrweno_weno->module~hrweno_kinds

This program illustrates the application of modules 'hrweno' and 'tvdode' for solving a 1D hyperbolic equation (Burger's equation):

                    d/dt u(x,t) = - d/dx f(u(x,t))
                    with f(u,t) = (u**2)/2
                    and u(x,t=0) = ic(x)

The spatial variable 'x' is discretized according to a finite-volume approach and the time variable 't' is left continuous (method of lines), leading to:

                du(i,t)/dt = -1/dx(i)*( f(u(x(i+1/2),t)) - f(u(x(i-1/2),t)) )

                              ul=u(i-1/2)^+          ur=u(i+1/2)^-
               --|-----(i-1)------|---------(i)----------|------(i+1)-----|--
                               x(i-1/2)               x(i+1/2)
                                  |<---    dx(i)     --->|

In this particular example, we use the 3rd order 'rktvd' ode solver (we could equally well employ the 'mstvd' solver). The reconstruction is done with the 5th order WENO scheme; to try other orders, we can change the parameter 'k'.


Calls

program~~example1_burgers_1d_fv~~CallsGraph program~example1_burgers_1d_fv example1_burgers_1d_fv none~integrate rktvd%integrate program~example1_burgers_1d_fv->none~integrate none~linear grid1%linear program~example1_burgers_1d_fv->none~linear proc~ic ic program~example1_burgers_1d_fv->proc~ic proc~output output program~example1_burgers_1d_fv->proc~output fu fu none~integrate->fu optval optval none~integrate->optval none~linear->optval to_string to_string proc~output->to_string

Variables

Type Attributes Name Initial
integer, parameter :: nc = 100
real(kind=rk) :: u(nc)
real(kind=rk) :: dt
real(kind=rk) :: time
real(kind=rk) :: time_out
real(kind=rk) :: time_start
real(kind=rk) :: time_end
integer :: num_time_points
integer :: ii
type(grid1) :: gx
type(weno) :: myweno
type(rktvd) :: ode

Functions

pure function flux(v, x, t)

Flux function. Here we define the flux corresponding to Burger's equation.

Arguments

Type IntentOptional Attributes Name
real(kind=rk), intent(in) :: v

function v(x,t)

real(kind=rk), intent(in) :: x(:)

spatial variable

real(kind=rk), intent(in) :: t

time variable

Return Value real(kind=rk)

elemental function ic(x)

Initial condition. Here we used a limited linear profile.

Arguments

Type IntentOptional Attributes Name
real(kind=rk), intent(in) :: x

spatial variable

Return Value real(kind=rk)


Subroutines

pure subroutine rhs(t, v, vdot)

This subroutine computes the numerical approximation to the right hand side of:

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=rk), intent(in) :: t

time variable

real(kind=rk), intent(in) :: v(:)

vector(N) with v(x,t) values

real(kind=rk), intent(out) :: vdot(:)

vector(N) with v'(x,t) values

subroutine output(action)

Auxiliary routine to save results to file.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: action

parameter to select output action

Source Code

program example1_burgers_1d_fv
!!   This program illustrates the application of modules 'hrweno' and 'tvdode' for solving a 1D
!! hyperbolic equation (Burger's equation):
!!```
!!                    d/dt u(x,t) = - d/dx f(u(x,t))
!!                    with f(u,t) = (u**2)/2
!!                    and u(x,t=0) = ic(x)
!!```
!!   The spatial variable 'x' is discretized according to a finite-volume approach and the time
!! variable 't' is left continuous (method of lines), leading to:
!!```
!!                du(i,t)/dt = -1/dx(i)*( f(u(x(i+1/2),t)) - f(u(x(i-1/2),t)) )
!!
!!                              ul=u(i-1/2)^+          ur=u(i+1/2)^-
!!               --|-----(i-1)------|---------(i)----------|------(i+1)-----|--
!!                               x(i-1/2)               x(i+1/2)
!!                                  |<---    dx(i)     --->|
!!```
!!  In this particular example, we use the 3rd order 'rktvd' ode solver (we could equally well
!! employ the 'mstvd' solver). The reconstruction is done with the 5th order WENO scheme; to
!! try other orders, we can change the parameter 'k'.
   use, intrinsic :: iso_fortran_env, only: stderr => error_unit, stdout => output_unit
   use hrweno_kinds, only: rk
   use hrweno_tvdode, only: rktvd
   use hrweno_weno, only: weno
   use hrweno_fluxes, only: godunov, lax_friedrichs
   use hrweno_grids, only: grid1
   use stdlib_strings, only: to_string
   implicit none

   integer, parameter :: nc = 100
   real(rk) :: u(nc)
   real(rk) :: dt, time, time_out, time_start, time_end
   integer :: num_time_points, ii
   type(grid1) :: gx
   type(weno) :: myweno
   type(rktvd) :: ode

   ! Define the spatial grid
   ! In this example, we use a linear grid, but any smooth grid can be used
   call gx%linear(xmin=-5._rk, xmax=5._rk, ncells=nc)

   ! Init weno object
   myweno = weno(ncells=nc, k=3, eps=1e-6_rk)

   ! Open file where results will be stored
   call output(1)

   ! Initial condition u(x,t=0)
   u = ic(gx%center)

   ! Call ODE time solver
   ode = rktvd(rhs, nc, order=3)

   time_start = 0._rk
   time_end = 12._rk
   dt = 1e-2_rk

   time = time_start
   num_time_points = 100
   do ii = 0, num_time_points
      time_out = time_end*ii/num_time_points
      call ode%integrate(u, time, time_out, dt)
      call output(2)
   end do

   ! End of simulation
   call output(3)

contains

   pure subroutine rhs(t, v, vdot)
   !! This subroutine computes the *numerical approximation* to the right hand side of:
   !!```
   !!                du(i,t)/dt = -1/dx(i)*( f(u(x(i+1/2),t)) - f(u(x(i-1/2),t)) )
   !!```
   !!   There are two main steps. First, we use the WENO scheme to obtain the reconstructed
   !! values of 'u' at the left and right cell boundaries. Note that, in general, because of
   !! discontinuities, \( u_{i+1/2}^+ \neq u_{(i+1)+1/2}^- \). Second, we use a suitable flux
   !! method (e.g., Godunov, Lax-Friedrichs) to compute the flux from the reconstructed
   !! 'u' values.
      real(rk), intent(in) :: t
         !! time variable
      real(rk), intent(in) :: v(:)
         !! vector(N) with v(x,t) values
      real(rk), intent(out) :: vdot(:)
         !! vector(N) with v'(x,t) values

      real(rk) :: fedges(0:nc), vl(nc), vr(nc)
      integer :: i

      ! Get reconstructed values at cell boundaries
      call myweno%reconstruct(v, vl, vr)

      ! Fluxes at interior cell boundaries
      ! One can use the Lax-Friedrichs or the Godunov method
      do concurrent(i=1:nc - 1)
         !fedges(i) = lax_friedrichs(flux, vr(i), vl(i+1), gx%r(i), t, alpha = 1._rk)
         fedges(i) = godunov(flux, vr(i), vl(i + 1), [gx%right(i)], t)
      end do

      ! Apply problem-specific flux constraints at domain boundaries
      fedges(0) = fedges(1)
      fedges(nc) = fedges(nc - 1)

      ! Evaluate du/dt
      vdot = -(fedges(1:) - fedges(:nc - 1))/gx%width

   end subroutine rhs

   pure real(rk) function flux(v, x, t)
   !! Flux function. Here we define the flux corresponding to Burger's equation.
      real(rk), intent(in) :: v
         !! function v(x,t)
      real(rk), intent(in) :: x(:)
         !! spatial variable
      real(rk), intent(in) :: t
         !! time variable

      flux = (v**2)/2

   end function flux

   elemental real(rk) function ic(x)
   !! Initial condition. Here we used a limited linear profile.
      real(rk), intent(in) :: x
         !! spatial variable
      real(rk), parameter :: xa = -4._rk, xb = 2._rk, va = 1._rk, vb = -0.5_rk

      ic = va + (vb - va)/(xb - xa)*(x - xa)
      ic = max(min(ic, va), vb)

   end function ic

   subroutine output(action)
   !! Auxiliary routine to save results to file.
      integer, intent(in) :: action
         !! parameter to select output action
      character(*), parameter :: folder = ".\output\example1\"
      real(rk), save :: cpu_start = 0._rk, cpu_end = 0._rk
      integer, save :: funit_x = 0, funit_u = 0
      integer :: i

      select case (action)

         ! Open files and write headers and grid
      case (1)

         write (stdout, '(1x, a)') "Running example1 ..."
         call cpu_time(cpu_start)

         ! Write grid
         open (newunit=funit_x, file=folder//"x.txt", status="replace", &
               action="write", position="rewind")

         write (funit_x, '(a5, 2(1x, a15))') "i", "x(i)", "dx(i)"
         do i = 1, nc
            write (funit_x, '(i5, 2(1x, es15.5))') i, gx%center(i), gx%width(i)
         end do

         ! Write header u
         open (newunit=funit_u, file=folder//"u.txt", status="replace", &
               action="write", position="rewind")

         write (funit_u, '(a16)', advance="no") "t"
         do i = 1, nc
            write (funit_u, '(1x, a16)', advance="no") "u("//to_string(i)//")"
         end do
         write (funit_u, *) ""

         ! Write values u(x,t)
      case (2)
         write (funit_u, '(es16.5e3)', advance="no") time
         do i = 1, nc
            write (funit_u, '(1x, es16.5e3)', advance="no") u(i)
         end do
         write (funit_u, *) ""

         ! Close files
      case (3)
         close (funit_x)
         close (funit_u)
         call cpu_time(cpu_end)
         write (stdout, '(1x, a, 1x, f6.1)') "Elapsed time (ms) :", 1e3_rk*(cpu_end - cpu_start)

      end select

   end subroutine output

end program example1_burgers_1d_fv