
"""Script for running a tsunami inundation scenario for Cairns, QLD Australia.

Source data such as elevation and boundary data is assumed to be available in
directories specified by project.py
The output sww file is stored in directory named after the scenario, i.e
slide or fixed_wave.

The scenario is defined by a triangular mesh created from project.polygon,
the elevation data and a tsunami wave generated by a submarine mass failure.

Ole Nielsen and Duncan Gray, GA - 2005 and Jane Sexton and
Nick Bartzis, GA - 2006
"""

#------------------------------------------------------------------------------
# Import necessary modules
#------------------------------------------------------------------------------

# Standard modules
import os
import time
import sys

# Related major packages
from anuga.shallow_water import Domain
from anuga.shallow_water import Reflective_boundary
from anuga.shallow_water import Dirichlet_boundary
from anuga.shallow_water import Time_boundary
from anuga.shallow_water import File_boundary
from anuga.pmesh.mesh_interface import create_mesh_from_regions
from anuga.shallow_water.data_manager import convert_dem_from_ascii2netcdf
from anuga.shallow_water.data_manager import dem2pts
from anuga.fit_interpolate.search_functions import search_times, \
     reset_search_times
from anuga.fit_interpolate.general_fit_interpolate import \
     get_build_quadtree_time

# Application specific imports
import project                 # Definition of file names and polygons


#------------------------------------------------------------------------------
# Define scenario as either slide or fixed_wave.
#------------------------------------------------------------------------------
scenario = 'slide' 
#scenario = 'fixed_wave'

if os.access(scenario, os.F_OK) == 0:
    os.mkdir(scenario)
basename = scenario + 'source'


#------------------------------------------------------------------------------
# Preparation of topographic data
# Convert ASC 2 DEM 2 PTS using source data and store result in source data
#------------------------------------------------------------------------------

# Filenames
dem_name = 'cairns' 
meshname = 'cairns.msh'

# Create DEM from asc data
convert_dem_from_ascii2netcdf(dem_name, use_cache=True, verbose=True)

# Create pts file for onshore DEM
dem2pts(dem_name, use_cache=True, verbose=True)


#------------------------------------------------------------------------------
# Create the triangular mesh based on overall clipping polygon with a tagged
# boundary and interior regions defined in project.py along with
# resolutions (maximal area of per triangle) for each polygon
#------------------------------------------------------------------------------

remainder_res = 10000000
islands_res = 100000
cairns_res = 100000
shallow_res = 500000
interior_regions = [[project.poly_cairns, cairns_res],
                    [project.poly_island0, islands_res],
                    [project.poly_island1, islands_res],
                    [project.poly_island2, islands_res],
                    [project.poly_island3, islands_res],
                    [project.poly_shallow, shallow_res]]

create_mesh_from_regions(project.bounding_polygon,
                         boundary_tags={'top': [0],
                                        'ocean_east': [1],
                                        'bottom': [2],
                                        'onshore': [3]},
                         maximum_triangle_area=remainder_res,
                         filename=meshname,
                         interior_regions=interior_regions,
                         use_cache=True,
                         verbose=True)


#------------------------------------------------------------------------------
# Setup computational domain
#------------------------------------------------------------------------------

from anuga.abstract_2d_finite_volumes.pmesh2domain import pmesh_to_domain_instance
from anuga.caching import cache

##domain = cache(Domain(meshname, use_cache=True, verbose=True)

domain = cache(pmesh_to_domain_instance,
               (meshname, Domain),
               dependencies = [meshname])

print 'Number of triangles = ', len(domain)
print 'The extent is ', domain.get_extent()
print domain.statistics()

domain.set_name(basename) 
domain.set_datadir(scenario)
domain.set_quantities_to_be_stored(['stage', 'xmomentum', 'ymomentum'])
domain.set_minimum_storable_height(0.01)

#print 'domain.tight_slope_limiters', domain.tight_slope_limiters
domain.tight_slope_limiters = 0
print 'domain.tight_slope_limiters', domain.tight_slope_limiters



domain.points_file_block_line_size = 50000

#------------------------------------------------------------------------------
# Setup initial conditions
#------------------------------------------------------------------------------

tide = 0.0
domain.set_quantity('stage', tide)
domain.set_quantity('friction', 0.0)


t0 = time.time()
domain.set_quantity('elevation', 
                    filename=dem_name + '.pts',
                    use_cache=False,
                    verbose=True,
                    alpha=0.1)

print 'Fitting the elevation data took %.2f seconds' %(time.time()-t0)

search_one_cell_time, search_more_cells_time = search_times()
reset_search_times()
print "search_one_cell_time",search_one_cell_time
print "search_more_cells_time", search_more_cells_time
print "build_quadtree_time", get_build_quadtree_time()
import sys; sys.exit() 
#------------------------------------------------------------------------------
# Setup information for slide scenario (to be applied 1 min into simulation
#------------------------------------------------------------------------------

if scenario == 'slide':
    # Function for submarine slide
    from anuga.shallow_water.smf import slide_tsunami  
    tsunami_source = slide_tsunami(length=35000.0,
                                   depth=project.slide_depth,
                                   slope=6.0,
                                   thickness=500.0, 
                                   x0=project.slide_origin[0], 
                                   y0=project.slide_origin[1], 
                                   alpha=0.0, 
                                   domain=domain,
                                   verbose=True)


#------------------------------------------------------------------------------
# Setup boundary conditions
#------------------------------------------------------------------------------

print 'Available boundary tags', domain.get_boundary_tags()

Br = Reflective_boundary(domain)
Bd = Dirichlet_boundary([tide,0,0])

# 60 min square wave starting at 1 min, 50m high
if scenario == 'fixed_wave':
    Bw = Transmissive_Momentum_Set_Stage_boundary(domain = domain,
                          f=lambda t: [(60<t<3660)*50, 0, 0])
    domain.set_boundary({'ocean_east': Bw,
                         'bottom': Bd,
                         'onshore': Bd,
                         'top': Bd})

# boundary conditions for slide scenario
if scenario == 'slide':
    domain.set_boundary({'ocean_east': Bd,
                         'bottom': Bd,
                         'onshore': Bd,
                         'top': Bd})
    

#------------------------------------------------------------------------------
# Evolve system through time
#------------------------------------------------------------------------------

t0 = time.time()

from Numeric import allclose
from anuga.abstract_2d_finite_volumes.quantity import Quantity

if scenario == 'slide':
    
    for t in domain.evolve(yieldstep = 10, finaltime = 60): 
        domain.write_time()
        domain.write_boundary_statistics(tags = 'ocean_east')     
        
    # add slide
    thisstagestep = domain.get_quantity('stage')
    if allclose(t, 60):
        slide = Quantity(domain)
        slide.set_values(tsunami_source)
        domain.set_quantity('stage', slide + thisstagestep)

    for t in domain.evolve(yieldstep = 10, finaltime = 5000, 
                           skip_initial_step = True):
        domain.write_time()
        domain.write_boundary_statistics(tags = 'ocean_east')

if scenario == 'fixed_wave':

    # save every two mins leading up to wave approaching land
    for t in domain.evolve(yieldstep = 120, finaltime = 5000): 
        domain.write_time()
        domain.write_boundary_statistics(tags = 'ocean_east')     

    # save every 30 secs as wave starts inundating ashore
    for t in domain.evolve(yieldstep = 10, finaltime = 10000, 
                           skip_initial_step = True):
        domain.write_time()
        domain.write_boundary_statistics(tags = 'ocean_east')
            
print 'That took %.2f seconds' %(time.time()-t0)
