#!/usr/bin/env python2.7
# -*- coding: UTF-8 -*-
#
# Copyright (C) 2010-2011 Yung-Yu Chen <yyc@solvcon.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

"""
Supersonic flow over a cylinder.  Solver has CUDA enabled.  Note the spatial
domain includes only the fore flow for the bow shock.  You can further increase
the steps.

The arrangement blnt can be run by simply executing ./go run.
"""

from solvcon.kerpak import gasdyn

def blnt_base(casename=None, meshname=None, 
    gamma=None, density=None, pressure=None, M=None,
    psteps=None, ssteps=None, **kw
):
    """
    Fundamental configuration of the simulation and return the case object.

    @return: the created Case object.
    @rtype: solvcon.case.BlockCase
    """
    import os
    from numpy import sqrt
    from solvcon.conf import env
    from solvcon.boundcond import bctregy
    from solvcon.solver import ALMOST_ZERO
    from solvcon import hook, anchor
    from solvcon.kerpak import cuse
    # set flow properties (fp).
    fpb = {
        'gamma': gamma, 'rho': density, 'v2': 0.0, 'v3': 0.0, 'p': pressure,
    }
    fpb['v1'] = M*sqrt(gamma*fpb['p']/fpb['rho'])
    fpi = fpb.copy()
    # set up BCs.
    bcmap = {
        'cylinder': (bctregy.GasdynWall, {},),
        'farfield': (bctregy.GasdynInlet, fpb,),
        'outflow': (bctregy.CuseNonrefl, {},),
    }
    # set up case.
    basedir = os.path.abspath(os.path.join(os.getcwd(), 'result'))
    cse = gasdyn.GasdynCase(basedir=basedir, rootdir=env.projdir,
        basefn=casename, meshfn=os.path.join(env.find_scdata_mesh(), meshname),
        bcmap=bcmap, **kw)
    # anchors for solvers.
    for key in 'Runtime', 'March', 'Tpool':
        cse.runhooks.append(getattr(anchor, key+'StatAnchor'))
    # informative.
    cse.runhooks.append(hook.BlockInfoHook)
    cse.runhooks.append(hook.ProgressHook,
        psteps=psteps, linewidth=ssteps/psteps)
    cse.runhooks.append(cuse.CflHook, fullstop=False, psteps=ssteps,
        cflmax=10.0, linewidth=ssteps/psteps)
    cse.runhooks.append(cuse.ConvergeHook, psteps=ssteps)
    cse.runhooks.append(hook.SplitMarker)
    cse.runhooks.append(hook.GroupMarker)
    # initializer.
    cse.runhooks.append(anchor.FillAnchor, keys=('soln',), value=ALMOST_ZERO)
    cse.runhooks.append(anchor.FillAnchor, keys=('dsoln',), value=0)
    cse.runhooks.append(gasdyn.UniformIAnchor, **fpi)
    # post processing.
    cse.runhooks.append(gasdyn.GasdynOAnchor, rsteps=ssteps)
    cse.runhooks.append(hook.PMarchSave, anames=[
        ('soln', False, -4),
        ('rho', True, 0),
        ('p', True, 0),
        ('T', True, 0),
        ('ke', True, 0),
        ('M', True, 0),
        ('sch', True, 0),
        ('v', True, 0.5),
    ], fpdtype='float64', psteps=ssteps)
    return cse

def blnt_skel(casename, **kw):
    return blnt_base(casename=casename, meshname='hyperblunt_t100mm.neu.gz',
        gamma=1.4, density=1.0, pressure=1.0, rkillfn='', ncuth=128,
        steps_run=2000, ssteps=500, psteps=10, **kw)

@gasdyn.GasdynCase.register_arrangement
def blnt(casename, **kw):
    return blnt_skel(casename=casename, M=3.0, time_increment=9.e-3, **kw)

@gasdyn.GasdynCase.register_arrangement
def blnt_m5(casename, **kw):
    return blnt_skel(casename=casename, M=5.0, time_increment=6.e-3,
        taumin=0.5, **kw)

@gasdyn.GasdynCase.register_arrangement
def blnt_m10(casename, **kw):
    return blnt_skel(casename=casename, M=5.0, time_increment=3.e-3,
        taumin=1.0, **kw)

@gasdyn.GasdynCase.register_arrangement
def blnt_m20(casename, **kw):
    return blnt_skel(casename=casename, M=20.0, time_increment=1.6e-3,
        taumin=1.0, **kw)

if __name__ == '__main__':
    import solvcon
    solvcon.go()
