Fortran

Guide To Learn

Tsunami simulator: Putting it all together

Finally, we get to put together the new function (from subsection 3.2.2) and subroutine (from subsection 3.3.3) in the main program of the tsunami simulator. In a nutshell, this program has the same functionality and behavior as the previous version from chapter 2. The key difference is that now we’ve abstracted away the code to set the initial conditions and to calculate the finite difference of an array, as you can see in the following listing.

Listing 3.19 The updated complete code of the tsunami simulator

program tsunami
 
  implicit none
 
  integer :: n
 
  integer, parameter :: grid_size = 100
  integer, parameter :: num_time_steps = 100
  real, parameter :: dt = 1, dx = 1, c = 1
 
  real :: h(grid_size)
 
  integer, parameter :: icenter = 25
  real, parameter :: decay = 0.02
 
  if (grid_size <= 0) stop 'grid_size must be > 0'         ❶
  if (dt <= 0) stop 'time step dt must be > 0'             ❶
  if (dx <= 0) stop 'grid spacing dx must be > 0'          ❶
  if (c <= 0) stop 'background flow speed c must be > 0'   ❶
 
  call set_gaussian(h, icenter, decay)                     ❷
 
  print *, 0, h
  time_loop: do n = 1, num_time_steps
    h = h - c * diff(h) / dx * dt                          ❸
    print *, n, h
  end do time_loop
 
contains
 
  pure function diff(x) result(dx)                         ❹
    real, intent(in) :: x(:)
    real :: dx(size(x))
    integer :: im
    im = size(x)
    dx(1) = x(1) - x(im)
    dx(2:im) = x(2:im) - x(1:im-1)
  end function diff
 
  pure subroutine set_gaussian(x, icenter, decay)          ❺
    real, intent(in out) :: x(:)
    integer, intent(in) :: icenter
    real, intent(in) :: decay
    integer :: i
    do concurrent(i = 1:size(x))
      x(i) = exp(-decay * (i - icenter)**2)
    end do
  end subroutine set_gaussian
 
end program tsunami

❶ Checks input values and aborts if invalid

❷ Calls the subroutine to initialize water height

❸ Computes the finite difference of water height on the fly by calling the diff function

❹ Function to compute the finite difference of an input array

❺ Subroutine to initialize the input array to a Gaussian shape

At this point, our simulator produces exactly the same results as its previous version from chapter 2, and this is intended! The goal of this chapter was to refactor our code from a purely imperative to a more procedural style. If you check out the code from GitHub, you can test the correctness of the output by comparing the output from the two versions. The following listing shows what you should use to compare that output.

Listing 3.20 Comparing tsunami simulator results

git clone https://github.com/modern-fortran/tsunami   ❶
cd tsunami
make                                                  ❷
src/ch02/tsunami > tsunami_v2.txt                     ❸
src/ch03/tsunami > tsunami_v3.txt                     ❹
diff tsunami_v2.txt tsunami_v3.txt                    ❺

❶ Gets the code from GitHub–do this only if you haven’t before.

❷ This builds the programs for each chapter; we’ll use only v2 and v3 here.

❸ Runs the v2 of the program and pipes the output into a file

❹ Ditto for v3

❺ Finds differences between the two outputs–there should be no output here.

This listing shows all the steps to get the code, compile it, run the chapter 2 and 3 versions of the tsunami simulator, and store the outputs of each version in their own file. It then compares the files to make sure they’re exactly the same.

Tsunami simulator: Putting it all together

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top