Skip to content

Finalization

This page describes the finalization and cleanup phase after the main computation.

The finalization phase handles:

  • Final output writing
  • Memory deallocation
  • Performance statistics
  • Cleanup of resources

Write final state:

subroutine finalize_simulation()
! Write final VTK file
call vtk_output%write_field('h', h)
call vtk_output%write_field('u', u)
call vtk_output%write_field('v', v)
call vtk_output%finalize()
! Close CSV files
call csv_output%close()
! Write summary
call write_summary()
end subroutine finalize_simulation

Display timing information:

subroutine print_performance()
if (rank == 0) then
print *, ''
print *, '========================================='
print *, 'Performance Statistics'
print *, '========================================='
print *, ''
! Total simulation time
print '(A,F10.2,A)', 'Total time: ', t_total%elapsed(), ' s'
print *, ''
! Breakdown by routine
print '(A,F10.2,A,F6.2,A)', ' Flux computation: ', &
t_flux%elapsed(), ' s (', &
100.0*t_flux%elapsed()/t_total%elapsed(), '%)'
print '(A,F10.2,A,F6.2,A)', ' Field update: ', &
t_update%elapsed(), ' s (', &
100.0*t_update%elapsed()/t_total%elapsed(), '%)'
print '(A,F10.2,A,F6.2,A)', ' Output writing: ', &
t_output%elapsed(), ' s (', &
100.0*t_output%elapsed()/t_total%elapsed(), '%)'
print *, ''
! Performance metrics
cell_updates = real(mesh%nc, rp) * real(iter, rp)
print '(A,ES12.3)', ' Cell updates/second: ', &
cell_updates / t_total%elapsed()
print *, ''
print *, '========================================='
end if
end subroutine print_performance

Free all allocated arrays:

subroutine deallocate_fields()
! Deallocate field arrays
if (allocated(h)) deallocate(h)
if (allocated(u)) deallocate(u)
if (allocated(v)) deallocate(v)
! Deallocate intermediate arrays
if (allocated(rhs_h)) deallocate(rhs_h)
if (allocated(rhs_u)) deallocate(rhs_u)
if (allocated(rhs_v)) deallocate(rhs_v)
! Deallocate mesh
call mesh%deallocate()
if (rank == 0) then
print *, 'Memory deallocated successfully'
end if
end subroutine deallocate_fields

Write simulation summary:

subroutine write_summary()
integer :: unit
if (rank == 0) then
open(newunit=unit, file='results/summary.txt', status='replace')
write(unit, '(A)') '====================================='
write(unit, '(A)') 'Tolosa-lib Shallow-Water Example'
write(unit, '(A)') '====================================='
write(unit, '(A)') ''
! Simulation parameters
write(unit, '(A)') 'Parameters:'
write(unit, '(A,I0)') ' Number of cells: ', mesh%nc
write(unit, '(A,I0)') ' Number of MPI processes: ', num_procs
write(unit, '(A,F8.2)') ' End time: ', t_end
write(unit, '(A,I0)') ' Iterations: ', iter
write(unit, '(A)') ''
! Physical parameters
write(unit, '(A)') 'Physical parameters:'
write(unit, '(A,F8.3)') ' Gravity: ', g
write(unit, '(A,F8.4)') ' Manning coefficient: ', manning
write(unit, '(A)') ''
! Numerical parameters
write(unit, '(A)') 'Numerical parameters:'
write(unit, '(A,F6.3)') ' CFL number: ', cfl
write(unit, '(A,F10.6)') ' Average dt: ', dt_avg
write(unit, '(A,A)') ' Scheme: ', trim(scheme_name)
write(unit, '(A)') ''
! Statistics
write(unit, '(A)') 'Field statistics at final time:'
write(unit, '(A,F10.4,A,F10.4)') ' h: min=', minval(h), ', max=', maxval(h)
write(unit, '(A,F10.4,A,F10.4)') ' u: min=', minval(u), ', max=', maxval(u)
write(unit, '(A,F10.4,A,F10.4)') ' v: min=', minval(v), ', max=', maxval(v)
write(unit, '(A)') ''
! Mass conservation
write(unit, '(A,ES12.4)') ' Initial mass: ', mass_init
write(unit, '(A,ES12.4)') ' Final mass: ', mass_final
write(unit, '(A,ES12.4)') ' Relative error: ', &
(mass_final - mass_init) / mass_init
close(unit)
print *, 'Summary written to results/summary.txt'
end if
end subroutine write_summary

Clean up Tolosa-lib:

! Finalize MPI
call mpi_finalize_tolosa()
! Finalize library
call tolosa_finalize()
subroutine finalize_all()
! Write final output
call write_final_output()
! Print performance statistics
call print_performance()
! Write summary file
call write_summary()
! Deallocate memory
call deallocate_fields()
! Finalize timers
call t_total%finalize()
call t_flux%finalize()
call t_update%finalize()
call t_output%finalize()
! Finalize MPI
call mpi_finalize_tolosa()
! Finalize library
call tolosa_finalize()
if (rank == 0) then
print *, ''
print *, 'Simulation completed successfully!'
end if
end subroutine finalize_all
=========================================
Performance Statistics
=========================================
Total time: 125.34 s
Flux computation: 98.45 s ( 78.54%)
Field update: 15.23 s ( 12.15%)
Output writing: 11.66 s ( 9.30%)
Cell updates/second: 7.98E+06
=========================================

Verify conservation properties:

function compute_total_mass() result(mass)
real(rp) :: mass
integer :: ic
mass = 0.0_rp
do ic = 1, mesh%nc
mass = mass + h(ic) * mesh%cell_vol(ic)
end do
! MPI reduction
call mpi_allreduce_sum(mass)
end function compute_total_mass
! Check for NaN or Inf
do ic = 1, mesh%nc
if (isnan(h(ic)) .or. h(ic) /= h(ic)) then
print *, 'ERROR: NaN detected in h at cell', ic
print *, 'Time:', t, 'Iteration:', iter
call tolosa_abort()
end if
end do

After finalization, the following files are created:

  • results/output_*.vtk - VTK files for visualization
  • results/gauges.csv - Time series at gauge locations
  • results/summary.txt - Simulation summary
  • results/performance.log - Detailed timing statistics