diff --git a/build.gradle b/build.gradle index 7f9232683c398bad60c7808c4b2d674e2f807a91..a554a8571724652547f6703b862cb547e5185bf7 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ apply plugin: 'jacoco' apply plugin: 'eclipse-wtp' sourceCompatibility = 1.8 +compileJava.options.encoding = 'UTF-8' repositories { jcenter() diff --git a/src/gov/usgs/earthquake/nshmp/calc/CalcConfig.java b/src/gov/usgs/earthquake/nshmp/calc/CalcConfig.java index 62d812a6beb6e02d58abf2226b4f4a0391bf5c5b..bdd48dd59fd02d37360dddb9bb559dcb8f3e205e 100644 --- a/src/gov/usgs/earthquake/nshmp/calc/CalcConfig.java +++ b/src/gov/usgs/earthquake/nshmp/calc/CalcConfig.java @@ -6,6 +6,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.padEnd; import static com.google.common.base.Strings.repeat; +import static gov.usgs.earthquake.nshmp.data.Data.checkInRange; import static gov.usgs.earthquake.nshmp.data.XySequence.create; import static gov.usgs.earthquake.nshmp.data.XySequence.immutableCopyOf; import static gov.usgs.earthquake.nshmp.internal.Parsing.enumsToString; @@ -15,6 +16,7 @@ import static gov.usgs.earthquake.nshmp.internal.TextUtils.NEWLINE; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.gson.Gson; @@ -37,17 +39,19 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.EnumSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import gov.usgs.earthquake.nshmp.data.Data; import gov.usgs.earthquake.nshmp.data.XySequence; import gov.usgs.earthquake.nshmp.eq.model.SourceType; import gov.usgs.earthquake.nshmp.gmm.Gmm; +import gov.usgs.earthquake.nshmp.gmm.GmmPostProcessor; import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel; import gov.usgs.earthquake.nshmp.gmm.Imt; - -import java.util.Set; +import gov.usgs.earthquake.nshmp.gmm.RezaeianDamping_2014; /** * Calculation configuration. @@ -133,6 +137,42 @@ public final class CalcConfig { */ public final Set<Imt> imts; + /** + * The post processors used to adjust ground motions derived from + * {@link GroundMotionModel}s (GMMs). The models may apply corrections or + * scale factors to GMM-derived {@code μ}- and {@code σ}-values. For + * example, see {@link RezaeianDamping_2014}. If multiple post processors + * are specified, they are executed in the order listed. + * + * <p><b>Default:</b> [ {@code (empty)} ] + */ + public final List<GmmPostProcessor.Model> gmmPostProcessors; + + /** + * Viscous damping ratio. The default value is consistent with that used in + * {@link GroundMotionModel} most (GMM) development. Values other than 5% + * will apply a damping scale factor (DSF) to adjust the 5% damped spectral + * ordinates predicted by GMMs. + * + * <p><b>Default:</b> {@code 5.0%}<br><b>Range:</b> {@code 0.5%} to + * {@code 30.0%} + * + * <p><b>Note:</b> At this time, the damping scaling factor (DSF) model + * (Rezaeian et al., 2014) is only applicable to active continental crust + * GMMs and will not be applied to ground motion values from GMMs for other + * tectonic regions. + * + * @see RezaeianDamping_2014 + */ + public final double gmmDampingRatio; + + /** + * Whether or not {@link GroundMotionModel} (GMM) sigmas are also modified + * according to the Rezaeian et al. (2014) model when applying damping + * scaling factors (DSF). + */ + public final boolean gmmDampingSigma; + /** * Whether to consider additional ground motion model uncertainty, or not. * Currently this is only applicable when using the PEER NGA-West or @@ -160,6 +200,9 @@ public final class CalcConfig { ExceedanceModel exceedanceModel, double truncationLevel, Set<Imt> imts, + List<GmmPostProcessor.Model> gmmPostProcessors, + double gmmDampingRatio, + boolean gmmDampingSigma, boolean gmmUncertainty, ValueFormat valueFormat, double[] defaultImls, @@ -170,6 +213,9 @@ public final class CalcConfig { this.exceedanceModel = exceedanceModel; this.truncationLevel = truncationLevel; this.imts = imts; + this.gmmPostProcessors = gmmPostProcessors; + this.gmmDampingRatio = gmmDampingRatio; + this.gmmDampingSigma = gmmDampingSigma; this.gmmUncertainty = gmmUncertainty; this.valueFormat = valueFormat; @@ -227,6 +273,10 @@ public final class CalcConfig { .append(formatEntry(Key.EXCEEDANCE_MODEL, exceedanceModel.name())) .append(formatEntry(Key.TRUNCATION_LEVEL, truncationLevel)) .append(formatEntry(Key.IMTS, enumsToString(imts, Imt.class))) + .append(formatEntry(Key.GMM_POST_PROCESSORS, + enumsToString(gmmPostProcessors, GmmPostProcessor.Model.class))) + .append(formatEntry(Key.GMM_DAMPING_RATIO, gmmDampingRatio)) + .append(formatEntry(Key.GMM_DAMPING_SIGMA, gmmDampingSigma)) .append(formatEntry(Key.GMM_UNCERTAINTY, gmmUncertainty)) .append(formatEntry(Key.VALUE_FORMAT, valueFormat.name())) .append(formatEntry(Key.DEFAULT_IMLS, wrap(Arrays.toString(defaultImls), false))) @@ -238,6 +288,9 @@ public final class CalcConfig { ExceedanceModel exceedanceModel; Double truncationLevel; Set<Imt> imts; + List<GmmPostProcessor.Model> gmmPostProcessors; + Double gmmDampingRatio; + Boolean gmmDampingSigma; Boolean gmmUncertainty; ValueFormat valueFormat; double[] defaultImls; @@ -248,6 +301,9 @@ public final class CalcConfig { exceedanceModel, truncationLevel, Sets.immutableEnumSet(imts), + gmmPostProcessors, + gmmDampingRatio, + gmmDampingSigma, gmmUncertainty, valueFormat, defaultImls, @@ -260,6 +316,9 @@ public final class CalcConfig { this.exceedanceModel = that.exceedanceModel; this.truncationLevel = that.truncationLevel; this.imts = that.imts; + this.gmmPostProcessors = that.gmmPostProcessors; + this.gmmDampingRatio = that.gmmDampingRatio; + this.gmmDampingSigma = that.gmmDampingSigma; this.gmmUncertainty = that.gmmUncertainty; this.valueFormat = that.valueFormat; this.defaultImls = that.defaultImls; @@ -276,6 +335,15 @@ public final class CalcConfig { if (that.imts != null) { this.imts = that.imts; } + if (that.gmmPostProcessors != null) { + this.gmmPostProcessors = that.gmmPostProcessors; + } + if (that.gmmDampingSigma != null) { + this.gmmDampingSigma = that.gmmDampingSigma; + } + if (that.gmmDampingRatio != null) { + this.gmmDampingRatio = that.gmmDampingRatio; + } if (that.gmmUncertainty != null) { this.gmmUncertainty = that.gmmUncertainty; } @@ -291,11 +359,13 @@ public final class CalcConfig { } /* Slightly modified version of NSHM 5Hz curve, size = 20 */ - private static final double[] IMLS_PGA_SA = new double[] { 0.0025, 0.0045, 0.0075, 0.0113, + private static final double[] IMLS_PGA_SA = new double[] { + 0.0025, 0.0045, 0.0075, 0.0113, 0.0169, 0.0253, 0.0380, 0.0570, 0.0854, 0.128, 0.192, 0.288, 0.432, 0.649, 0.973, 1.46, 2.19, 3.28, 4.92, 7.38 }; - private static final double[] IMLS_PGV = new double[] { 0.0100, 0.0177, 0.0312, 0.0552, + private static final double[] IMLS_PGV = new double[] { + 0.0100, 0.0177, 0.0312, 0.0552, 0.0976, 0.173, 0.305, 0.539, 0.953, 1.68, 2.98, 5.26, 9.30, 16.4, 29.1, 51.3, 90.8, 160.0, 284.0, 501.0 }; @@ -304,6 +374,9 @@ public final class CalcConfig { b.exceedanceModel = ExceedanceModel.TRUNCATION_UPPER_ONLY; b.truncationLevel = 3.0; b.imts = EnumSet.of(Imt.PGA, Imt.SA0P2, Imt.SA1P0); + b.gmmPostProcessors = ImmutableList.of(); + b.gmmDampingRatio = 5.0; + b.gmmDampingSigma = false; b.gmmUncertainty = false; b.valueFormat = ValueFormat.ANNUAL_RATE; b.defaultImls = IMLS_PGA_SA; @@ -316,6 +389,15 @@ public final class CalcConfig { checkNotNull(exceedanceModel, STATE_ERROR, Hazard.ID, Key.EXCEEDANCE_MODEL); checkNotNull(truncationLevel, STATE_ERROR, Hazard.ID, Key.TRUNCATION_LEVEL); checkNotNull(imts, STATE_ERROR, Hazard.ID, Key.IMTS); + checkNotNull(gmmPostProcessors, STATE_ERROR, Hazard.ID, Key.GMM_POST_PROCESSORS); + checkNotNull(gmmDampingRatio, STATE_ERROR, Hazard.ID, Key.GMM_DAMPING_RATIO); + checkInRange( + RezaeianDamping_2014.DAMPING_RATIO_RANGE, + Key.GMM_DAMPING_RATIO.toString(), + gmmDampingRatio); + checkNotNull(gmmDampingSigma, STATE_ERROR, Hazard.ID, Key.GMM_DAMPING_SIGMA); + checkNotNull(gmmUncertainty, STATE_ERROR, Hazard.ID, Key.GMM_UNCERTAINTY); + checkNotNull(valueFormat, STATE_ERROR, Hazard.ID, Key.VALUE_FORMAT); checkNotNull(defaultImls, STATE_ERROR, Hazard.ID, Key.DEFAULT_IMLS); checkNotNull(customImls, STATE_ERROR, Hazard.ID, Key.CUSTOM_IMLS); } @@ -993,6 +1075,9 @@ public final class CalcConfig { EXCEEDANCE_MODEL, TRUNCATION_LEVEL, IMTS, + GMM_POST_PROCESSORS, + GMM_DAMPING_RATIO, + GMM_DAMPING_SIGMA, GMM_UNCERTAINTY, VALUE_FORMAT, DEFAULT_IMLS, diff --git a/src/gov/usgs/earthquake/nshmp/calc/GmmProcessor.java b/src/gov/usgs/earthquake/nshmp/calc/GmmProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..774089deb624e5322b2a9c1c7888981f343c48c2 --- /dev/null +++ b/src/gov/usgs/earthquake/nshmp/calc/GmmProcessor.java @@ -0,0 +1,61 @@ +package gov.usgs.earthquake.nshmp.calc; + +import com.google.common.annotations.Beta; + +import java.util.List; +import java.util.stream.Collectors; + +import gov.usgs.earthquake.nshmp.gmm.Gmm; +import gov.usgs.earthquake.nshmp.gmm.GmmInput; +import gov.usgs.earthquake.nshmp.gmm.GmmPostProcessor; +import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel; +import gov.usgs.earthquake.nshmp.gmm.Imt; +import gov.usgs.earthquake.nshmp.gmm.ScalarGroundMotion; + +/** + * Ground motion calculation manager. More often than not, the default instance + * of this class is used to simply compute scalar ground motions. However, if + * any post processors are specified in the calculation configuration, they are + * applied in the order listed to the computed scalar ground motions. + * + * @author Peter Powers + */ +@Beta +abstract class GmmProcessor { + + abstract ScalarGroundMotion apply(GroundMotionModel model, GmmInput in, Imt imt, Gmm gmm); + + static GmmProcessor instance(CalcConfig config) { + boolean defaultOnly = config.hazard.gmmPostProcessors.isEmpty(); + return defaultOnly ? new DefaultInstance() : new Instance(config); + } + + private static final class Instance extends GmmProcessor { + + final List<GmmPostProcessor> postProcessors; + + Instance(CalcConfig config) { + this.postProcessors = config.hazard.gmmPostProcessors.stream() + .map(model -> model.instance(config)) + .collect(Collectors.toList()); + } + + @Override + public ScalarGroundMotion apply(GroundMotionModel model, GmmInput in, Imt imt, Gmm gmm) { + ScalarGroundMotion sgm = model.calc(in); + for (GmmPostProcessor processor : postProcessors) { + sgm = processor.apply(sgm, in, imt, gmm); + } + return sgm; + } + + } + + private static final class DefaultInstance extends GmmProcessor { + @Override + public ScalarGroundMotion apply(GroundMotionModel model, GmmInput in, Imt imt, Gmm gmm) { + return model.calc(in); + } + } + +} diff --git a/src/gov/usgs/earthquake/nshmp/calc/Transforms.java b/src/gov/usgs/earthquake/nshmp/calc/Transforms.java index bfc5519cf063cedb05d2ef91db9a7202d0f4d217..52f1c8eee7e5ac4a2dd9ed4ae64cdec1d215d134 100644 --- a/src/gov/usgs/earthquake/nshmp/calc/Transforms.java +++ b/src/gov/usgs/earthquake/nshmp/calc/Transforms.java @@ -112,9 +112,13 @@ final class Transforms { */ static final class InputsToGroundMotions implements Function<InputList, GroundMotions> { + private final GmmProcessor gmmProcessor; private final Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable; - InputsToGroundMotions(Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable) { + InputsToGroundMotions( + CalcConfig config, + Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable) { + this.gmmProcessor = GmmProcessor.instance(config); this.gmmTable = gmmTable; } @@ -132,7 +136,10 @@ final class Transforms { for (Gmm gmm : gmmKeys) { GroundMotionModel model = gmmTable.get(imt).get(gmm); for (GmmInput gmmInput : inputs) { - builder.add(imt, gmm, model.calc(gmmInput)); + builder.add( + imt, + gmm, + gmmProcessor.apply(model, gmmInput, imt, gmm)); } } } @@ -304,7 +311,7 @@ final class Transforms { gmmSet.gmms()); this.sourceToInputs = new SourceToInputs(site); - this.inputsToGroundMotions = new InputsToGroundMotions(gmmTable); + this.inputsToGroundMotions = new InputsToGroundMotions(config, gmmTable); this.groundMotionsToCurves = config.hazard.gmmUncertainty && gmmSet.epiUncertainty() ? new GroundMotionsToCurvesWithUncertainty(gmmSet, config) : new GroundMotionsToCurves(config); @@ -312,6 +319,9 @@ final class Transforms { @Override public HazardCurves apply(Source source) { + + // return + // sourceToInputs.andThen(inputsToGroundMotions).andThen(groundMotionsToCurves).apply(source); return groundMotionsToCurves.apply( inputsToGroundMotions.apply( sourceToInputs.apply(source))); @@ -395,7 +405,7 @@ final class Transforms { config.hazard.imts, gmmSet.gmms()); - InputsToGroundMotions inputsToGm = new InputsToGroundMotions(gmmTable); + InputsToGroundMotions inputsToGm = new InputsToGroundMotions(config, gmmTable); GroundMotions gms = inputsToGm.apply(inputs); Function<GroundMotions, HazardCurves> gmToCurves = @@ -482,7 +492,7 @@ final class Transforms { config.hazard.imts, gmmSet.gmms()); - this.inputsToGroundMotions = new InputsToGroundMotions(gmmTable); + this.inputsToGroundMotions = new InputsToGroundMotions(config, gmmTable); this.groundMotionsToCurves = config.hazard.gmmUncertainty && gmmSet.epiUncertainty() ? new GroundMotionsToCurvesWithUncertainty(gmmSet, config) : new GroundMotionsToCurves(config); @@ -527,8 +537,10 @@ final class Transforms { private final InputsToGroundMotions transform; - ClusterInputsToGroundMotions(Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable) { - transform = new InputsToGroundMotions(gmmTable); + ClusterInputsToGroundMotions( + CalcConfig config, + Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable) { + transform = new InputsToGroundMotions(config, gmmTable); } @Override @@ -632,7 +644,7 @@ final class Transforms { Map<Imt, Map<Gmm, GroundMotionModel>> gmmTable = instances(config.hazard.imts, gmms); this.sourceToInputs = new ClusterSourceToInputs(site); - this.inputsToGroundMotions = new ClusterInputsToGroundMotions(gmmTable); + this.inputsToGroundMotions = new ClusterInputsToGroundMotions(config, gmmTable); this.groundMotionsToCurves = new ClusterGroundMotionsToCurves(config); } diff --git a/src/gov/usgs/earthquake/nshmp/gmm/GmmPostProcessor.java b/src/gov/usgs/earthquake/nshmp/gmm/GmmPostProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..3f3e513ae4996722ce6b40a0dc9de7e0d6916847 --- /dev/null +++ b/src/gov/usgs/earthquake/nshmp/gmm/GmmPostProcessor.java @@ -0,0 +1,48 @@ +package gov.usgs.earthquake.nshmp.gmm; + +import gov.usgs.earthquake.nshmp.calc.CalcConfig; + +/** + * Interface implemented by any model designed to modify scalar ground motions + * computed from any {@link GroundMotionModel} (GMM). + * + * @author Peter Powers + */ +public interface GmmPostProcessor { + + /** + * Update the supplied {@code ScalarGroundMotion}. + * + * @param sgm the {@code ScalarGroundMotion} to modify + * @param in the source-site parameterization + * @param imt the intensity measure type being considered + * @param gmm the ground motion model in use + */ + ScalarGroundMotion apply(ScalarGroundMotion sgm, GmmInput in, Imt imt, Gmm gmm); + + /** + * Ground motion post processors identifiers + */ + public enum Model { + + /** + * The Rezaeian et al. (2014) viscous damping model. + * + * @see RezaeianDamping_2014 + */ + REZAEIAN_DAMPING_2014 { + @Override + public GmmPostProcessor instance(CalcConfig config) { + return new RezaeianDamping_2014(config); + } + }; + + /** + * Create an instance of the post processor. + * @param config for instance intialization + * @return a concrete {@code GmmPostProcessor} instance + */ + public abstract GmmPostProcessor instance(CalcConfig config); + + } +} diff --git a/src/gov/usgs/earthquake/nshmp/gmm/RezaeianDamping_2014.java b/src/gov/usgs/earthquake/nshmp/gmm/RezaeianDamping_2014.java new file mode 100644 index 0000000000000000000000000000000000000000..1ad81037be22d98b7e8aa1e1c4c69b437c2c3e97 --- /dev/null +++ b/src/gov/usgs/earthquake/nshmp/gmm/RezaeianDamping_2014.java @@ -0,0 +1,211 @@ +package gov.usgs.earthquake.nshmp.gmm; + +import static com.google.common.base.Preconditions.checkArgument; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.ASK_14; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.BA_08; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.BSSA_14; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.CB_08; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.CB_14; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.CY_08; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.CY_14; +import static gov.usgs.earthquake.nshmp.gmm.Gmm.IDRISS_14; +import static java.lang.Math.abs; +import static java.lang.Math.log; +import static java.lang.Math.sqrt; + +import com.google.common.annotations.Beta; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Lists; +import com.google.common.collect.Range; +import com.google.common.primitives.Doubles; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import gov.usgs.earthquake.nshmp.calc.CalcConfig; +import gov.usgs.earthquake.nshmp.data.Interpolator; +import gov.usgs.earthquake.nshmp.data.XySequence; + +/** + * Implementation of Rezaeian et al. (2014) damping scaling factor model. + * + * <p><b>Reference:</b> Rezaeian, S., Bozorgnia, Y., Idriss, I.M., Abrahamson, + * N., Campbell, K., and Silva, W., 2014, Damping scaling factors for elastic + * response spectra for shallow crustal earthquakes in active tectonic regions: + * "Average" horizontal component: Earthquake SPectra, v. 30, n. 2, p. 939-963. + * + * <p><b>doi:</b> <a href="http://dx.doi.org/10.1193/100512EQS298M"> + * 10.1193/100512EQS298M</a> + * + * @author Peter Powers + */ +@Beta +public class RezaeianDamping_2014 implements GmmPostProcessor { + + /* + * Developer notes: + * + * The apply method doesn't do anything if the supplied damping ratio is set + * to 5% (lnDSF = 0.0). In point of fact, the computeDsf() model returns a + * value much closer to zero for a damping ratio of 5.027590868... The + * assumption is that only coarser damping ratios will be used (e.g. 3.5, 4.0) + * such that this inconsistency will not make a difference. + */ + + private static final String NAME = "Rezaeian et al. (2014)"; + + private static final CoefficientContainer COEFFS; + + private static final Map<Imt, Coefficients> COEFF_MAP = new EnumMap<>(Imt.class); + private static final Map<Imt, XySequence> CORR_COEFF_MAP = new EnumMap<>(Imt.class); + + private static final String[] corrCoeffKeys = + { "0.5", "1", "2", "3", "5", "7", "10", "15", "20", "25", "30" }; + + private static final List<Double> CORR_COEFF_DSFS = + FluentIterable.from(corrCoeffKeys) + .transform(Doubles.stringConverter()) + .toList(); + + private static final Interpolator CC_INTERP = Interpolator.builder().build(); + + static { + COEFFS = new CoefficientContainer("Rezaeian14.csv"); + for (Imt imt : COEFFS.imts()) { + COEFF_MAP.put(imt, new Coefficients(imt, COEFFS)); + CORR_COEFF_MAP.put(imt, initCorrCoeff(imt, COEFFS)); + } + } + + /** + * The range of damping ratios supported by this model: {@code [0.5..30.0]}. + */ + public static final Range<Double> DAMPING_RATIO_RANGE = Range.closed( + CORR_COEFF_DSFS.get(0), + CORR_COEFF_DSFS.get(CORR_COEFF_DSFS.size() - 1)); + + /** + * The GMMs supported by this model. Currently the Rezaien et al. (2014) model + * only supports GMMs for active continental crust (i.e. the NGA-West1 and + * NGA-West2 models as implemented for the 2008 and 2014 NSHMs for the + * Conterminous U.S. This set is for external use and filtering prior to + * calling public methods of this class. + */ + public static final Set<Gmm> SUPPORTED_GMMS = EnumSet.of( + BA_08, CB_08, CY_08, + ASK_14, BSSA_14, CB_14, CY_14, IDRISS_14); + + private static final class Coefficients { + + final Imt imt; + final double a0, a1, b0, b1, b2, b3, b4, b5, b6, b7, b8; + + Coefficients(Imt imt, CoefficientContainer cc) { + this.imt = imt; + Map<String, Double> coeffs = cc.get(imt); + a0 = coeffs.get("a0"); + a1 = coeffs.get("a1"); + b0 = coeffs.get("b0"); + b1 = coeffs.get("b1"); + b2 = coeffs.get("b2"); + b3 = coeffs.get("b3"); + b4 = coeffs.get("b4"); + b5 = coeffs.get("b5"); + b6 = coeffs.get("b6"); + b7 = coeffs.get("b7"); + b8 = coeffs.get("b8"); + } + } + + /* + * Correlation coeffs at fixed damping ratios as a sequence for interpolation + * over the range [0.5..30.0] + */ + private static XySequence initCorrCoeff(Imt imt, CoefficientContainer cc) { + Map<String, Double> coeffs = cc.get(imt); + List<Double> corrCoeffs = Lists.newArrayList(); + for (String key : corrCoeffKeys) { + corrCoeffs.add(coeffs.get(key)); + } + return XySequence.createImmutable(CORR_COEFF_DSFS, corrCoeffs); + } + + /* The correlation coefficient (rho) for the supplied IMT and DSF. */ + private static double calcCorrCoeff(Imt imt, double dsf) { + XySequence cc = CORR_COEFF_MAP.get(imt); + return CC_INTERP.findY(cc, dsf); + } + + private final double dampingRatio; + private final boolean updateSigma; + + RezaeianDamping_2014(CalcConfig config) { + dampingRatio = config.hazard.gmmDampingRatio; + updateSigma = config.hazard.gmmDampingSigma; + } + + /** + * If the configured damping ratio equals 5.0% or {@link #SUPPORTED_GMMS} does + * not contain the supplied {@code gmm}, this method returns the supplied + * {@code ScalarGroundMotion}, {@code sgm}. + */ + @Override + public ScalarGroundMotion apply( + ScalarGroundMotion sgm, + GmmInput in, + Imt imt, + Gmm gmm) { + + if (dampingRatio == 5.0 || !SUPPORTED_GMMS.contains(gmm)) { + return sgm; + } + + checkArgument( + COEFF_MAP.containsKey(imt), + "%s damping model does not support IMT: %s", NAME, imt.name()); + + Coefficients c = COEFF_MAP.get(imt); + double dsf = computeDsf(c, dampingRatio, in.Mw, in.rRup); + double σ = updateSigma ? updateSigma(c, dampingRatio, sgm.sigma()) : sgm.sigma(); + return DefaultScalarGroundMotion.create(sgm.mean() + dsf, σ); + } + + /* + * Compute the damping scaling factor (DSF) in natural log units for the + * damping ratio of interest. Equation (3). + */ + private static double computeDsf( + Coefficients c, + double dampingRatio, + double Mw, + double rRup) { + + if (dampingRatio == 5.0) { + return 0.0; + } + + double lnβ = log(dampingRatio); + double lnβsq = lnβ * lnβ; + return c.b0 + c.b1 * lnβ + c.b2 * lnβsq + + (c.b3 + c.b4 * lnβ + c.b5 * lnβsq) * Mw + + (c.b6 + c.b7 * lnβ + c.b8 * lnβsq) * log(rRup + 1.0); + } + + /* + * Adjust the aleatory variability of ground motion for the damping ratio of + * interest. Equation (5). + */ + private static double updateSigma( + Coefficients c, + double dampingRatio, + double σ) { + + double βTerm = log(dampingRatio / 5.0); + double σDsf = abs(c.a0 * βTerm + c.a1 * βTerm * βTerm); + double Ï = calcCorrCoeff(c.imt, dampingRatio); + return sqrt(σ * σ + σDsf * σDsf + 2.0 * σ * σDsf * Ï); + } +} diff --git a/src/gov/usgs/earthquake/nshmp/gmm/coeffs/Rezaeian14.csv b/src/gov/usgs/earthquake/nshmp/gmm/coeffs/Rezaeian14.csv new file mode 100644 index 0000000000000000000000000000000000000000..640bc9fa8a68d1004e36b18b6febf56faf9f8de0 --- /dev/null +++ b/src/gov/usgs/earthquake/nshmp/gmm/coeffs/Rezaeian14.csv @@ -0,0 +1,23 @@ +T, b0, b1, b2, b3, b4, b5, b6, b7, b8, a0, a1, 0.5, 1, 2, 3, 5, 7, 10, 15, 20, 25, 30 +PGA, 1.73E-03, -2.07E-04, -6.29E-04, 1.08E-06, -8.24E-05, 7.36E-05, -1.07E-03, 9.08E-04, -2.02E-04, -3.70E-03, 2.30E-04, 0.01, 0.00, 0.00, 0.00, 0.00, 0.02, 0.02, 0.01, -0.01, -0.02, -0.03 +0.01, 1.73E-03, -2.07E-04, -6.29E-04, 1.08E-06, -8.24E-05, 7.36E-05, -1.07E-03, 9.08E-04, -2.02E-04, -3.70E-03, 2.30E-04, 0.01, 0.00, 0.00, 0.00, 0.00, 0.02, 0.02, 0.01, -0.01, -0.02, -0.03 +0.02, 5.53E-02, -3.77E-02, 2.15E-03, -4.30E-03, 3.21E-03, -3.32E-04, -4.75E-03, 2.52E-03, 2.29E-04, -2.19E-02, 2.11E-03, 0.01, 0.03, 0.04, 0.06, 0.00, -0.06, -0.06, -0.07, -0.08, -0.09, -0.09 +0.03, 1.22E-01, -7.02E-02, -2.28E-03, -3.21E-03, 6.91E-05, 9.82E-04, -1.30E-02, 7.82E-03, 2.27E-04, -5.21E-02, 4.60E-03, 0.12, 0.12, 0.12, 0.13, 0.00, -0.14, -0.15, -0.17, -0.17, -0.17, -0.17 +0.05, 2.39E-01, -1.06E-01, -2.63E-02, -8.57E-04, -7.43E-03, 4.87E-03, -1.69E-02, 8.08E-03, 1.71E-03, -9.57E-02, 1.31E-03, 0.15, 0.17, 0.17, 0.18, 0.00, -0.21, -0.21, -0.22, -0.22, -0.22, -0.22 +0.075, 3.05E-01, -7.32E-02, -7.29E-02, 2.02E-04, -1.64E-02, 1.03E-02, -9.26E-04, -6.40E-03, 4.42E-03, -1.21E-01, -5.79E-03, 0.10, 0.12, 0.15, 0.15, 0.00, -0.16, -0.18, -0.19, -0.20, -0.20, -0.20 +0.1, 2.69E-01, 4.18E-03, -1.07E-01, 5.80E-03, -2.49E-02, 1.34E-02, 2.35E-02, -2.37E-02, 5.84E-03, -1.24E-01, -1.08E-02, 0.06, 0.09, 0.10, 0.11, 0.00, -0.14, -0.16, -0.18, -0.18, -0.18, -0.18 +0.15, 1.41E-01, 1.00E-01, -1.18E-01, 3.01E-02, -4.09E-02, 1.41E-02, 3.16E-02, -2.47E-02, 3.15E-03, -1.15E-01, -1.14E-02, 0.00, 0.01, 0.03, 0.04, 0.00, -0.10, -0.12, -0.14, -0.14, -0.15, -0.15 +0.2, 5.01E-02, 1.45E-01, -1.11E-01, 4.69E-02, -4.77E-02, 1.18E-02, 3.10E-02, -2.29E-02, 2.41E-03, -1.08E-01, -8.85E-03, 0.03, 0.05, 0.07, 0.06, 0.00, -0.10, -0.12, -0.14, -0.14, -0.14, -0.14 +0.25, 2.28E-02, 1.43E-01, -9.73E-02, 5.20E-02, -4.70E-02, 9.47E-03, 2.71E-02, -2.02E-02, 1.31E-03, -1.04E-01, -7.35E-03, 0.04, 0.06, 0.08, 0.08, 0.00, -0.09, -0.10, -0.11, -0.12, -0.12, -0.12 +0.3, -1.58E-02, 1.48E-01, -8.83E-02, 5.21E-02, -4.36E-02, 7.33E-03, 3.87E-02, -2.66E-02, 1.76E-03, -1.01E-01, -6.90E-03, 0.02, 0.03, 0.05, 0.06, 0.00, -0.09, -0.11, -0.13, -0.13, -0.13, -0.13 +0.4, 2.24E-02, 1.03E-01, -7.41E-02, 4.63E-02, -3.58E-02, 4.65E-03, 3.63E-02, -2.45E-02, 1.18E-03, -1.02E-01, -6.71E-03, 0.00, 0.02, 0.04, 0.05, 0.00, -0.10, -0.11, -0.12, -0.13, -0.13, -0.13 +0.5, 3.19E-02, 7.04E-02, -5.57E-02, 4.25E-02, -2.94E-02, 1.88E-03, 3.87E-02, -2.47E-02, 3.13E-04, -1.01E-01, -6.22E-03, -0.01, 0.01, 0.03, 0.05, 0.00, -0.11, -0.13, -0.15, -0.16, -0.17, -0.17 +0.75, 1.04E-02, 5.33E-02, -3.72E-02, 4.47E-02, -2.40E-02, -2.40E-03, 3.47E-02, -2.59E-02, 2.90E-03, -1.01E-01, -5.86E-03, 0.08, 0.09, 0.11, 0.13, 0.00, -0.19, -0.23, -0.28, -0.30, -0.32, -0.34 +1.0, -8.84E-02, 8.92E-02, -2.14E-02, 4.98E-02, -2.36E-02, -4.70E-03, 5.02E-02, -3.43E-02, 2.32E-03, -1.02E-01, -7.31E-03, 0.07, 0.08, 0.10, 0.11, 0.00, -0.19, -0.24, -0.29, -0.32, -0.35, -0.37 +1.5, -1.57E-01, 9.33E-02, 3.28E-03, 5.85E-02, -2.36E-02, -8.02E-03, 4.81E-02, -3.30E-02, 2.10E-03, -1.02E-01, -8.75E-03, 0.17, 0.19, 0.22, 0.22, 0.00, -0.27, -0.32, -0.37, -0.40, -0.43, -0.44 +2.0, -2.96E-01, 1.50E-01, 2.09E-02, 7.30E-02, -2.96E-02, -9.95E-03, 5.24E-02, -3.32E-02, 6.86E-04, -1.03E-01, -9.22E-03, 0.25, 0.25, 0.25, 0.26, 0.00, -0.33, -0.37, -0.42, -0.46, -0.49, -0.51 +3.0, -4.07E-01, 1.97E-01, 3.28E-02, 8.35E-02, -3.54E-02, -1.01E-02, 5.57E-02, -2.91E-02, -3.17E-03, -9.63E-02, -1.07E-02, 0.32, 0.32, 0.31, 0.32, 0.00, -0.35, -0.39, -0.43, -0.46, -0.48, -0.50 +4.0, -4.49E-01, 2.07E-01, 4.42E-02, 8.75E-02, -3.59E-02, -1.14E-02, 5.07E-02, -2.43E-02, -4.67E-03, -9.83E-02, -1.37E-02, 0.33, 0.33, 0.34, 0.34, 0.00, -0.36, -0.38, -0.41, -0.43, -0.44, -0.46 +5.0, -4.98E-01, 2.17E-01, 5.36E-02, 9.03E-02, -3.48E-02, -1.29E-02, 5.19E-02, -2.30E-02, -5.68E-03, -9.42E-02, -1.53E-02, 0.38, 0.38, 0.39, 0.38, 0.00, -0.40, -0.42, -0.45, -0.47, -0.49, -0.51 +7.5, -5.25E-01, 2.06E-01, 7.79E-02, 9.88E-02, -3.76E-02, -1.51E-02, 2.91E-02, -4.93E-03, -9.02E-03, -8.95E-02, -1.63E-02, 0.49, 0.49, 0.49, 0.49, 0.00, -0.51, -0.53, -0.55, -0.57, -0.58, -0.59 +10.0, -3.89E-01, 1.43E-01, 6.12E-02, 7.14E-02, -2.36E-02, -1.30E-02, 2.33E-02, -5.46E-03, -5.92E-03, -6.89E-02, -1.43E-02, 0.38, 0.39, 0.41, 0.41, 0.00, -0.42, -0.44, -0.47, -0.49, -0.51, -0.52