package org.opensha2.gmm;
import static java.lang.Math.log;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
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.MagConverter.NONE;
import static org.opensha2.gmm.SiteClass.HARD_ROCK;
import org.opensha2.gmm.GmmInput.Constraints;
import com.google.common.collect.Range;
import java.util.Map;
/**
* Implementation of the hybrid ground motion model for stable continental
* regions by Campbell (2003). This implementation matches that used in the 2008
* USGS NSHMP and comes in two additional magnitude converting (mb to Mw)
* flavors to support the 2008 central and eastern US model.
*
* <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 note:</b> Mean values are clamped per
* {@link GmmUtils#ceusMeanClip(Imt, double)}.
*
* <p><b>Reference:</b> Campbell, K.W., 2003, Prediction of strong ground motion
* using the hybrid empirical method and its use in the devel- opment of
* ground-motion (attenuation) relations in eastern North America: Bulletin of
* the Seismological Society of America, v. 93, p. 1012–1033.
*
* <p><b>doi:</b> <a href="http://dx.doi.org/10.1785/0120020002">
* 10.1785/0120020002</a>
*
* <p><b>Component:</b> geometric mean of two horizontal components
*
* @author Peter Powers
* @see Gmm#CAMPBELL_03
* @see Gmm#CAMPBELL_03_AB
* @see Gmm#CAMPBELL_03_J
*/
public class Campbell_2003 implements GroundMotionModel, ConvertsMag {
// notes from original implementation and fortran:
//
// some coefficients are labeled differnetly than in paper
// localCoeff(paperCoeff):
// c5(c7) c6(c8) c7(c9) c8(c10) c9(c5) c10(c6)
//
// c clamp for 2s set to 0 as per Ken Campbell's email of Aug 18 2008.
// TODO fix clamp values (not implemented here yet) to match other CEUS gmms
static final String NAME = "Campbell (2003)";
static final Constraints CONSTRAINTS = Constraints.builder()
.set(MW, Range.closed(4.0, 8.0))
.set(RRUP, Range.closed(0.0, 1000.0))
.set(VS30, Range.closed(760.0, 2000.0))
.build();
static final CoefficientContainer COEFFS = new CoefficientContainer("Campbell03.csv");
private static final double LOG_70 = 4.2484952;
private static final double LOG_130 = 4.8675345;
private static final class Coefficients {
final Imt imt;
final double c1, c1h, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13;
Coefficients(Imt imt, CoefficientContainer cc) {
this.imt = imt;
Map<String, Double> coeffs = cc.get(imt);
c1 = coeffs.get("c1");
c1h = coeffs.get("c1h");
c2 = coeffs.get("c2");
c3 = coeffs.get("c3");
c4 = coeffs.get("c4");
c5 = coeffs.get("c5");
c6 = coeffs.get("c6");
c7 = coeffs.get("c7");
c8 = coeffs.get("c8");
c9 = coeffs.get("c9");
c10 = coeffs.get("c10");
c11 = coeffs.get("c11");
c12 = coeffs.get("c12");
c13 = coeffs.get("c13");
}
}
private final Coefficients coeffs;
Campbell_2003(final Imt imt) {
coeffs = new Coefficients(imt, COEFFS);
}
@Override
public final ScalarGroundMotion calc(final GmmInput in) {
double Mw = converter().convert(in.Mw);
SiteClass siteClass = GmmUtils.ceusSiteClass(in.vs30);
double μ = calcMean(coeffs, Mw, in.rRup, siteClass);
double σ = calcStdDev(coeffs, Mw);
return DefaultScalarGroundMotion.create(μ, σ);
}
@Override
public MagConverter converter() {
return NONE;
}
private final double calcMean(final Coefficients c, final double Mw, final double rRup,
final SiteClass siteClass) {
double gnd0 = siteClass == HARD_ROCK ? c.c1h : c.c1;
double gndm = gnd0 + c.c2 * Mw + c.c3 * (8.5 - Mw) * (8.5 - Mw);
double cfac = pow((c.c5 * Math.exp(c.c6 * Mw)), 2);
double arg = sqrt(rRup * rRup + cfac);
double fac = 0.0;
if (rRup > 70.0) {
fac = c.c7 * (log(rRup) - LOG_70);
}
if (rRup > 130.0) {
fac = fac + c.c8 * (log(rRup) - LOG_130);
}
double gnd = gndm + c.c4 * log(arg) + fac + (c.c9 + c.c10 * Mw) * rRup;
return GmmUtils.ceusMeanClip(c.imt, gnd);
}
private final double calcStdDev(final Coefficients c, final double Mw) {
return (Mw < 7.16) ? c.c11 + c.c12 * Mw : c.c13;
}
}