diff --git a/src/main/java/gov/usgs/earthquake/nshmp/gmm/Imt.java b/src/main/java/gov/usgs/earthquake/nshmp/gmm/Imt.java index 093dd6bc78c2969b366568749f254db74ff8999d..0e4ee4c76af22cf629ea9b3b180c19089287e7bb 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/gmm/Imt.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/gmm/Imt.java @@ -2,14 +2,10 @@ package gov.usgs.earthquake.nshmp.gmm; import static com.google.common.math.DoubleMath.fuzzyEquals; -import java.text.DecimalFormat; -import java.util.Collection; import java.util.EnumSet; -import java.util.List; +import java.util.OptionalDouble; import java.util.Set; -import com.google.common.collect.Lists; - /** * Intesity measure type (Imt) identifiers. {@code SA0P1} stands for spectal * acceleration of 0.1 seconds. @@ -73,7 +69,16 @@ public enum Imt { SA7P5, SA10P0; - private static final DecimalFormat SA_FORMAT = new DecimalFormat("0.00#"); + private final OptionalDouble period; + + private Imt() { + if (ordinal() < 10) { + period = OptionalDouble.empty(); + } else { + String valStr = name().substring(2).replace("P", "."); + period = OptionalDouble.of(Double.parseDouble(valStr)); + } + } @Override public String toString() { @@ -99,7 +104,7 @@ public enum Imt { case DS595: return "Significant Duration 5-95%"; default: - return SA_FORMAT.format(period()) + " Second Spectral Acceleration"; + return period() + " Second Spectral Acceleration"; } } @@ -134,36 +139,21 @@ public enum Imt { } /** - * Returns the corresponding period or frequency for this {@code Imt} if it - * represents a spectral acceleration. + * Returns the corresponding period for this {@code Imt} if it represents a + * spectral acceleration and throws an {@code UnsupportedOperationException} + * otherwise. Rather than trying to catch the exception, users should call + * {@link #isSA()} to check validity of this {@code Imt} before calling this + * method. * * @return the period for this {@code Imt} if it represents a spectral - * acceleration; null otherwise - */ - public Double period() { - if (ordinal() < 10) { - return null; - } - String valStr = name().substring(2).replace("P", "."); - return Double.parseDouble(valStr); - } - - /** - * Returns the {@code List} of periods for the supplied {@code Imt}s. The - * result will be sorted according to the iteration order of the supplied - * {@code Collection}. Any non spectral acceleration {@code Imt}s will have - * null values in the returned {@code List}. - * - * @param imts to list periods for - * @return a {@code List} of spectral periods - * @see #saImts() + * acceleration + * @throws UnsupportedOperationException if this {@code Imt} is not a spectral + * acceleration */ - public static List<Double> periods(Collection<Imt> imts) { - List<Double> periodList = Lists.newArrayListWithCapacity(imts.size()); - for (Imt imt : imts) { - periodList.add(imt.period()); - } - return periodList; + public double period() { + return period.orElseThrow( + () -> new UnsupportedOperationException( + name() + " is not a SA IMT.")); } /** @@ -177,9 +167,8 @@ public enum Imt { */ public static Imt fromPeriod(double period) { for (Imt imt : Imt.values()) { - if (imt.name().startsWith("SA")) { - double saPeriod = imt.period(); - if (fuzzyEquals(saPeriod, period, 0.000001)) { + if (imt.isSA()) { + if (fuzzyEquals(imt.period(), period, 0.000001)) { return imt; } } @@ -200,16 +189,17 @@ public enum Imt { if (this == PGA) { return 100; } - if (this.isSA()) { + if (isSA()) { return 1.0 / period(); } throw new UnsupportedOperationException("frequency() supports PGA and SA IMTs only"); } /** - * Returns true if this Imt is some flavor of spectral acceleration. + * Returns true if this {@code Imt} represents a spectral acceleration. * - * @return {@code true} if this is a spectral period, {@code false} otherwise + * @return {@code true} if this is a spectral acceleration {@code Imt}, + * {@code false} otherwise */ public boolean isSA() { return ordinal() > 9; @@ -221,7 +211,7 @@ public enum Imt { * @return the set of spectral acceleration IMTs */ public static Set<Imt> saImts() { - return EnumSet.complementOf(EnumSet.range(PGA, AI)); + return EnumSet.range(SA0P01, SA10P0); } /** @@ -248,5 +238,4 @@ public enum Imt { SA1P0, SA1P5, SA2P0, SA3P0, SA4P0, SA5P0, SA7P5, SA10P0); } - } diff --git a/src/test/java/gov/usgs/earthquake/nshmp/gmm/ImtTest.java b/src/test/java/gov/usgs/earthquake/nshmp/gmm/ImtTest.java index f1aecc9942d7970f1f43d4db957533533df5e6ef..e3feb1c2d8d03cc389e8fcf7021eec92987bf918 100644 --- a/src/test/java/gov/usgs/earthquake/nshmp/gmm/ImtTest.java +++ b/src/test/java/gov/usgs/earthquake/nshmp/gmm/ImtTest.java @@ -10,16 +10,33 @@ import static gov.usgs.earthquake.nshmp.gmm.Imt.PGA; import static gov.usgs.earthquake.nshmp.gmm.Imt.PGD; import static gov.usgs.earthquake.nshmp.gmm.Imt.PGV; import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P01; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P02; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P03; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P05; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P075; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P1; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P15; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P2; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P25; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P3; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P4; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P5; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA0P75; import static gov.usgs.earthquake.nshmp.gmm.Imt.SA10P0; import static gov.usgs.earthquake.nshmp.gmm.Imt.SA1P0; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA1P5; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA2P0; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA3P0; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA4P0; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA5P0; +import static gov.usgs.earthquake.nshmp.gmm.Imt.SA7P5; import static gov.usgs.earthquake.nshmp.gmm.Imt.SI; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.EnumSet; -import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import org.junit.jupiter.api.Test; @@ -43,7 +60,7 @@ class ImtTest { assertEquals(CAV.toString(), "Cumulative Absolute Velocity"); assertEquals(DS575.toString(), "Significant Duration 5-75%"); assertEquals(DS595.toString(), "Significant Duration 5-95%"); - assertEquals(SA1P0.toString(), "1.00 Second Spectral Acceleration"); + assertEquals(SA1P0.toString(), "1.0 Second Spectral Acceleration"); } @Test @@ -62,17 +79,27 @@ class ImtTest { } @Test - void testPeriods() { - Set<Imt> imts = EnumSet.range(SA0P01, SA10P0); - List<Double> expected = imts.stream() - .map(Imt::period) - .collect(Collectors.toList()); - assertEquals(expected, Imt.periods(imts)); + void testPeriod() { + assertEquals(0.2, SA0P2.period()); + assertThrows(UnsupportedOperationException.class, () -> { + PGV.period(); + }); + } + @Test + void testFromPeriod() { + assertEquals(SA0P2, Imt.fromPeriod(0.2)); assertThrows(IllegalArgumentException.class, () -> { Imt.fromPeriod(0.1234); }); + } + @Test + void testFrequency() { + assertEquals(100, PGA.frequency()); + assertEquals(5.0, SA0P2.frequency()); + assertEquals(3.3333, SA0P3.frequency(), 0.0001); + assertEquals(0.1, SA10P0.frequency()); assertThrows(UnsupportedOperationException.class, () -> { PGV.frequency(); }); @@ -80,9 +107,19 @@ class ImtTest { @Test void testSaImts() { - // underlying method is complement of non-SA Imts - // which are listed first in the enum assertEquals(Imt.saImts(), EnumSet.range(SA0P01, SA10P0)); + assertFalse(Imt.saImts().contains(PGV)); + } + + @Test + void testMprs() { + Set<Imt> mprsImts = EnumSet.of( + PGA, + SA0P01, SA0P02, SA0P03, SA0P05, SA0P075, + SA0P1, SA0P15, SA0P2, SA0P25, SA0P3, SA0P4, SA0P5, SA0P75, + SA1P0, SA1P5, SA2P0, SA3P0, SA4P0, SA5P0, SA7P5, + SA10P0); + assertEquals(mprsImts, Imt.mprsImts()); } } diff --git a/src/test/java/gov/usgs/earthquake/nshmp/gmm/InstanceTest.java b/src/test/java/gov/usgs/earthquake/nshmp/gmm/InstanceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c5ce869d2499a0209c84e947df4aade190f1b5ce --- /dev/null +++ b/src/test/java/gov/usgs/earthquake/nshmp/gmm/InstanceTest.java @@ -0,0 +1,43 @@ +package gov.usgs.earthquake.nshmp.gmm; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class InstanceTest { + + /* + * Intantiates all supported IMTs for all GMMs and runs a test calculation. + */ + + private static GmmInput GMM_INPUT = GmmInput.builder().withDefaults().build(); + + @ParameterizedTest + @MethodSource("gmmImtPairs") + public void testInstances(Gmm gmm, Imt imt) { + assertDoesNotThrow(() -> { + GroundMotionModel instance = gmm.instance(imt); + instance.calc(GMM_INPUT); + }); + } + + private static Stream<Arguments> gmmImtPairs() { + List<Arguments> argsList = new ArrayList<>(); + Set<Gmm> gmms = EnumSet.allOf(Gmm.class); + for (Gmm gmm : gmms) { + Set<Imt> imts = gmm.supportedImts(); + for (Imt imt : imts) { + argsList.add(Arguments.of(gmm, imt)); + } + } + return argsList.stream(); + } +}