package org.opensha2.gmm; import static java.lang.Math.exp; import static java.lang.Math.log; import static java.lang.Math.min; import static java.lang.Math.pow; import static org.opensha2.gmm.GmmInput.Field.MW; import static org.opensha2.gmm.GmmInput.Field.RRUP; import static org.opensha2.gmm.GmmInput.Field.VS30; import static org.opensha2.gmm.GmmInput.Field.ZTOP; import static org.opensha2.gmm.Imt.PGA; import org.opensha2.eq.Earthquakes; import org.opensha2.gmm.GmmInput.Constraints; import com.google.common.collect.Range; import java.util.Map; /** * Abstract implementation of the subduction ground motion model created for BC * Hydro, Canada, by Addo, Abrahamson, & Youngs (2012). This implementation * matches that used in the USGS NSHM as supplied by N. Abrahamson. * * <p>This model supports both slab and interface type events. In the 2008 * NSHMP, the 'interface' form is used with the Cascadia subduction zone models * and the 'slab' form is used with gridded 'deep' events in northern California * and the Pacific Northwest. * * <p><b>Note:</b> Direct instantiation of {@code GroundMotionModel}s is * prohibited. Use {@link Gmm#instance(Imt)} to retrieve an instance for a * desired {@link Imt}. * * <p><b>Implementation notes:</b> <ol><li>Treats all sites as * forearc.</li><li>'zTop' is interpreted as hypocentral depth and is only used * for slab events; it is limited to 125 km, consistent with other subduction * models.</li><li>The DeltaC1 term is keyed to the 'middle' BC Hydro branch for * interface events and fixed at -0.3 for slab events.</li></ol> * * <p><b>Reference:</b> Addo, K., Abrahamson, N., and Youngs, R., (BC Hydro), * 2012, Probabilistic seismic hazard analysis (PSHA) model—Ground motion * characterization (GMC) model: Report E658, v. 3, November. * * <p><b>Component:</b> Geometric mean of two horizontal components * * @author Peter Powers * @see Gmm#BCHYDRO_12_INTER * @see Gmm#BCHYDRO_12_SLAB */ public abstract class BcHydro_2012 implements GroundMotionModel { static final String NAME = "BC Hydro (2012)"; // TODO will probably want to have constraints per-implementation (e.g. slab // vs interface depth limits) static final Constraints CONSTRAINTS = Constraints.builder() .set(MW, Range.closed(5.0, 9.5)) .set(RRUP, Range.closed(0.0, 1000.0)) .set(ZTOP, Earthquakes.SLAB_DEPTH_RANGE) .set(VS30, Range.closed(150.0, 1000.0)) .build(); static final CoefficientContainer COEFFS = new CoefficientContainer("BCHydro12.csv"); private static final double C1 = 7.8; private static final double T3 = 0.1; private static final double T4 = 0.9; private static final double T5 = 0.0; private static final double T9 = 0.4; private static final double C4 = 10.0; private static final double C = 1.88; private static final double N = 1.18; private static final double VSS_MAX = 1000.0; private static final double SIGMA = 0.74; private static final double ΔC1_SLAB = -0.3; private static final class Coefficients { final double vlin, b, θ1, θ2, θ6, θ10, θ11, θ12, θ13, θ14, ΔC1mid; // not currently used // final double t7, t8, t15, t16, dC1lo, dC1hi; Coefficients(Imt imt, CoefficientContainer cc) { Map<String, Double> coeffs = cc.get(imt); vlin = coeffs.get("vlin"); b = coeffs.get("b"); θ1 = coeffs.get("t1"); θ2 = coeffs.get("t2"); θ6 = coeffs.get("t6"); θ10 = coeffs.get("t10"); θ11 = coeffs.get("t11"); θ12 = coeffs.get("t12"); θ13 = coeffs.get("t13"); θ14 = coeffs.get("t14"); ΔC1mid = coeffs.get("dC1mid"); } } private final Coefficients coeffs; private final Coefficients coeffsPGA; BcHydro_2012(final Imt imt) { coeffs = new Coefficients(imt, COEFFS); coeffsPGA = new Coefficients(PGA, COEFFS); } @Override public final ScalarGroundMotion calc(final GmmInput in) { // pgaRock only required to compute non-linear site response // when vs30 is less than period-dependent vlin cutoff double pgaRock = (in.vs30 < coeffs.vlin) ? exp(calcMean(coeffsPGA, isSlab(), 0.0, in.Mw, in.rRup, in.zTop, 1000.0)) : 0.0; double μ = calcMean(coeffs, isSlab(), pgaRock, in.Mw, in.rRup, in.zTop, in.vs30); return DefaultScalarGroundMotion.create(μ, SIGMA); } abstract boolean isSlab(); private static final double calcMean(final Coefficients c, final boolean slab, final double pgaRock, final double Mw, final double rRup, final double zTop, final double vs30) { double ΔC1 = (slab ? ΔC1_SLAB : c.ΔC1mid); double mCut = C1 + ΔC1; double t13m = c.θ13 * (10 - Mw) * (10 - Mw); double fMag = (Mw <= mCut ? T4 : T5) * (Mw - mCut) + t13m; // no depth term for interface events double fDepth = slab ? c.θ11 * (min(zTop, 125.0) - 60.) : 0.0; double vsS = min(vs30, VSS_MAX); double fSite = c.θ12 * log(vsS / c.vlin); if (vs30 < c.vlin) { // whether or not we use pgaRock fSite += -c.b * log(pgaRock + C) + c.b * log(pgaRock + C * pow((vsS / c.vlin), N)); } else { // for pgaRock loop, vs=1000 > vlinPGA=865 fSite += c.b * N * log(vsS / c.vlin); } return c.θ1 + T4 * ΔC1 + (c.θ2 + (slab ? c.θ14 : 0.0) + T3 * (Mw - 7.8)) * log(rRup + C4 * exp((Mw - 6.0) * T9)) + c.θ6 * rRup + (slab ? c.θ10 : 0.0) + fMag + fDepth + // fterm + no fterm for forearc sites fSite; } static final class Interface extends BcHydro_2012 { static final String NAME = BcHydro_2012.NAME + ": Interface"; Interface(Imt imt) { super(imt); } @Override final boolean isSlab() { return false; } } static final class Slab extends BcHydro_2012 { static final String NAME = BcHydro_2012.NAME + ": Slab"; Slab(Imt imt) { super(imt); } @Override final boolean isSlab() { return true; } } }