# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2015-2020 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
"""
Module exports :class:`Zhang_Zhao2005SInter`,
               :class:`Zhang_Zhao2005SSlab`,
               :class:`Zhang_Zhao2005Crust`,
"""
import numpy as np
from openquake.hazardlib import const
from openquake.hazardlib.imt import LSD
from openquake.hazardlib.gsim.base import GMPE, CoeffsTable
    
def _SDinter_term(ctx):
    SD = 0.2485 * np.exp(-3.5387 + (1.438 * ctx.mag) - (
        0.0066 * (10 - ctx.mag) ** 3) - (
            1.785 * np.log(ctx.rrup + (1.097 * np.exp(0.617 * ctx.mag)))) +
                         (0.00648 * ctx.hypo_depth))
    return (1.856 * np.log10(SD))
    
def _SDslab_term(ctx):    
    SD = 0.2485 * np.exp(-3.5387 + (1.438 * ctx.mag) - (
        0.0066 * (10 - ctx.mag) ** 3) - (
            1.785 * np.log(ctx.rrup + (1.097 * np.exp(0.617 * ctx.mag)))
        ) + (0.00648 * ctx.hypo_depth) + 0.3643)
    return (1.856 * np.log10(SD))        
    
def _SDCrust_term(ctx, rake, mag):    
     # Reverse faulting
    if (rake >= 45.) & (rake <= 135.):
        C1 = -1.92
        C6 = 0.8285
    else:
        C1 = -2.17
        C6 = 0.8494
    
            
    if mag >= 6.5:
        SD = 0.06212 * np.exp(C1 + ctx.mag - (
            1.7 * (np.log(ctx.rrup + (0.3825 * np.exp(0.5882 * ctx.mag))))
        ) + C6 - (0.033 * (8.5 - ctx.mag) ** 2.5))
    else:
        SD = 0.06212 * np.exp(C1 + ctx.mag - (1.7 * (np.log(ctx.rrup + (
            2.1863 * np.exp(0.32 * ctx.mag))))) + C6 - (
                0.033 * (8.5 - ctx.mag) ** 2.5))
    return (1.856 * np.log10(SD))
def _compute_site_term(sites, c4, c5, c6, c7, c8):
   
    return (c4 * np.log10(sites.slope) +
            c5 * (sites.T_15) +
            c6 * np.log10(100 - sites.F_15) +
            (c7 * np.log10(sites.D50_15 + 0.1)) + c8)
[docs]class Zhang_Zhao2005SInter(GMPE):
    """
    Implements the GMPE of Zhang and Zhao. (2005) for Permanent ground
    deformation (m) from lateral spread 
    Zhang, J., & Zhao, J. X. (2005). Empirical models for estimating
    liquefaction-induced lateral spread displacement. Soil Dynamics and
    Earthquake Engineering, 25(6), 439-450.
    This model is based on Sadigh et al. (1997) and Young et al. (1997) models
    """
    #: This GMPE is based on subduction interface earthquakes 
    DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.SUBDUCTION_INTERFACE
    #: Supported intensity measure types are Permanent ground deformation (m)
    #: from lateral spread
    DEFINED_FOR_INTENSITY_MEASURE_TYPES = {LSD}
    #: Supported intensity measure component is the horizontal
    DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.HORIZONTAL
    #: Supported standard deviation types is total.
    DEFINED_FOR_STANDARD_DEVIATION_TYPES = {const.StdDev.TOTAL}
    #: Required site parameters
    REQUIRES_SITES_PARAMETERS = {
        'slope',
        'freeface_ratio',
        'T_15',
        'F_15',
        'D50_15'}
    #: Required rupture parameters are magnitude and hypocentral depth
    REQUIRES_RUPTURE_PARAMETERS = {'mag', 'hypo_depth'}
    #: Required distance measure is closest distance to rupture surface
    REQUIRES_DISTANCES = {'rrup'}
    #: GMPE not tested against independent implementation so raise
    #: not verified warning
    non_verified = True
            
[docs]    def compute(self, ctx: np.recarray, imts, mean, sig, tau, phi):
        for m, imt in enumerate(imts):
            ctx = ctx.copy()
            zslope = ctx.slope == 0.0
            ctx.slope[zslope] = ctx.freeface_ratio[zslope]
            c = np.zeros((5, len(ctx.sids)))  # slope coeffs updated
            for i in range(5):
                # where the slope is zero use the freeface coeffs
                c[i, zslope] = self.COEFFS_FREEFACE[imt][f'c{i+4}']
                c[i, ~zslope] = self.COEFFS_SLOPE[imt][f'c{i+4}']
            mean[m] = (
                _SDinter_term(ctx) +                 
                _compute_site_term(ctx, c[0], c[1], c[2], c[3], c[4]))
            mean[m] = np.log(10.0 ** mean[m])
            sig[m] = np.log(10.0 ** self.COEFFS_SLOPE[imt]["sigma"]) 
    COEFFS_SLOPE = CoeffsTable(table="""\
    IMT              c4       c5     c6       c7      c8   sigma
    LSD           0.356   0.0606  3.204  -1.0248  -4.292    0.22
    """)
    COEFFS_FREEFACE = CoeffsTable(table="""\
    IMT              c4       c5     c6       c7      c8   sigma
    LSD           0.456   0.0552  3.204  -1.0248  -4.743    0.22
    """) 
[docs]class Zhang_Zhao2005SSlab(Zhang_Zhao2005SInter):
    """
    Implements the GMPE of Zhang and Zhao. (2005) for Permanent ground
    deformation (m) from lateral spread
    Zhang, J., & Zhao, J. X. (2005). Empirical models for estimating
    liquefaction-induced lateral spread displacement. Soil Dynamics and
    Earthquake Engineering, 25(6), 439-450. This model is based on Sadigh et
    al. (1997) and Young et al. (1997) models
    """
    #: This GMPE is based on subduction intraslab earthquakes
    DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.SUBDUCTION_INTRASLAB
[docs]    def compute(self, ctx: np.recarray, imts, mean, sig, tau, phi):
        for m, imt in enumerate(imts):
            ctx = ctx.copy()
            zslope = ctx.slope == 0.0
            ctx.slope[zslope] = ctx.freeface_ratio[zslope]
            c = np.zeros((5, len(ctx.sids)))  # slope coeffs updated
            for i in range(5):
                # where the slope is zero use the freeface coeffs
                c[i, zslope] = self.COEFFS_FREEFACE[imt][f'c{i+4}']
                c[i, ~zslope] = self.COEFFS_SLOPE[imt][f'c{i+4}']
            mean[m] = (
                _SDslab_term(ctx) +                 
                _compute_site_term(ctx, c[0], c[1], c[2], c[3], c[4]))
            mean[m] = np.log(10.0 ** mean[m])
            sig[m] = np.log(10.0 ** self.COEFFS_SLOPE[imt]["sigma"])  
    
[docs]class Zhang_Zhao2005Crust(Zhang_Zhao2005SInter):
    """
    Implements the GMPE of Zhang and Zhao. (2005) for Permanent ground
    deformation (m) from lateral spread 
    Zhang, J., & Zhao, J. X. (2005). Empirical models for estimating
    liquefaction-induced lateral spread displacement. Soil Dynamics and
    Earthquake Engineering, 25(6), 439-450.
    This model is based on Sadigh et al. (1997) and Young et al. (1997) models
    """
    #: This GMPE is based on crustal earthquakes 
    DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.ACTIVE_SHALLOW_CRUST
    #: Required rupture parameters are magnitude 
    REQUIRES_RUPTURE_PARAMETERS = {'mag', 'rake'}
            
[docs]    def compute(self, ctx: np.recarray, imts, mean, sig, tau, phi):
        for m, imt in enumerate(imts):
            ctx = ctx.copy()
            zslope = ctx.slope == 0.0
            ctx.slope[zslope] = ctx.freeface_ratio[zslope]
            c = np.zeros((5, len(ctx.sids)))  # slope coeffs updated
            for i in range(5):
                # where the slope is zero use the freeface coeffs
                c[i, zslope] = self.COEFFS_FREEFACE[imt][f'c{i+4}']
                c[i, ~zslope] = self.COEFFS_SLOPE[imt][f'c{i+4}']
            mean[m] = (
                _SDCrust_term(ctx, ctx.rake[m], ctx.mag[m]) +   
                _compute_site_term(ctx,  c[0], c[1], c[2], c[3], c[4]))
               
            mean[m] = np.log(10.0 ** mean[m])
            sig[m] = np.log(10.0 ** self.COEFFS_SLOPE[imt]["sigma"])