diff --git a/docs/pages/Calculation-Configuration.md b/docs/pages/Calculation-Configuration.md index 7f8bf3d8a1e10796ac3f577cf72b7e77e9d2edba..097e8d5920e0c6c435c45b261826c3fcde7822b4 100644 --- a/docs/pages/Calculation-Configuration.md +++ b/docs/pages/Calculation-Configuration.md @@ -14,38 +14,43 @@ may be overridden. See [building and running](./Building-&-Running.md) and the Parameter | Type | Default | Notes | --------- | ---- | ------- | ----- | __`hazard`__ - `.exceedanceModel` |`String` | `TRUNCATION_3SIGMA_UPPER` | [`ExceedanceModel`][url-exceedance] + `.exceedanceModel` |`String` | `"TRUNCATION_3SIGMA_UPPER"`| [`ExceedanceModel`][url-exceedance] `.truncationLevel` |`Double` | `3.0` | [1](#notes) - `.imts` |`String[]` | `[ PGV, PGA, SA0P01, SA0P02, SA0P03, SA0P05, SA0P075, SA0P1, SA0P15, SA0P2, SA0P25, SA0P3, SA0P4, SA0P5, SA0P75, SA1P0, SA1P5, SA2P0, SA3P0, SA4P0, SA5P0, SA7P5, SA10P0 ]` | [`Imt`][url-imt] - `.tectonicSettings` |`String[]` | `[]` | Tectonic setting filter - `.sourceTypes` |`String[]` | `[]` | Source type filter + `.imts` |`String[]` | `["PGV","PGA","SA0P01","SA0P02",`<br>`"SA0P03","SA0P05","SA0P075",`<br>`"SA0P1","SA0P15","SA0P2","SA0P25",`<br>`"SA0P3","SA0P4","SA0P5","SA0P75",`<br>`"SA1P0","SA1P5","SA2P0","SA3P0",`<br>`"SA4P0","SA5P0","SA7P5","SA10P0"]` | [`Imt`][url-imt] + `.tectonicSettings` |`String[]` | `[]` | [`TectonicSetting`][url-tectonicsetting] filter + `.sourceTypes` |`String[]` | `[]` | [`SourceType`][url-sourcetype] filter `.vs30s` |`Double[]` | `[]` | Vs30s to use for batch jobs + `.useSiteData` |`Boolean` | `true` | Enable site data (e.g. basin depths) `.customImls` |`Map<String, Double[]>` | `{}` (empty object) | [2](#notes) - `.gmmDampingRatio` |`Double` | `0.05` (5%) | [3](#notes) - `.gmmSigmaScale` |`Double` | `1.0` (100%, no scaling) | - `.valueFormat` |`String` | `ANNUAL_RATE` | [`ValueFormat`][url-valueformat] + `.valueFormat` |`String` | `"ANNUAL_RATE"` | [`ValueFormat`][url-valueformat] +__`gmm`__ + `.dampingRatio` |`Double` | `0.05` (5%) | Limited to range [0.005..0.3] 0.5% to 30% + `.sigmaScale` |`Double` | `1.0` (100%, no scaling) | Limited to range [0.5..1.0] 50% to 100% + `.vertical` |`Boolean` | `false` | Compute vertical ground motions __`disagg`__ - `.retrunPeriod` |`Double` | `2475` | + `.returnPeriod` |`Double` | `2475` | `.bins` |`Object` | | [4](#notes) `.contributorLimit` |`Double` | `0.1` | [5](#notes) __`rate`__ `.bins` |`Object` | | [6](#notes) `.distance` |`Double` | `20` km - `.distributionFormat` |`String` | `INCREMENTAL` | [`DistributionFormat`][url-distribution] + `.distributionFormat` |`String` | `"INCREMENTAL"` | [`DistributionFormat`][url-distribution] `.timespan` |`Double` | `30` years - `.valueFormat` |`String` | `ANNUAL_RATE` | [`ValueFormat`][url-valueformat] + `.valueFormat` |`String` | `"ANNUAL_RATE"` | [`ValueFormat`][url-valueformat] __`output`__ | `.directory` |`String` | `hazout` - `.dataTypes` |`String[]` | `[ TOTAL, MAP ]` | [`DataType`][url-datatype] - `.returnPeriods` |`Double[]` | `[ 475, 975, 2475, 10000]` | [`ReturnPeriods`][url-returnperiods] + `.dataTypes` |`String[]` | `["TOTAL","MAP"]` | [`DataType`][url-datatype] + `.returnPeriods` |`Double[]` | `[475,975,2475,10000]` | [`ReturnPeriods`][url-returnperiods] __`performance`__ `.optimizeGrids` |`Boolean` | `true` | [7](#notes) `.smoothGrids` |`Boolean` | `true` | [8](#notes) `.systemPartition` |`Integer` | `1000` | [9](#notes) - `.threadCount` |`String` | `ALL` | [`ThreadCount`][url-sheets] + `.threadCount` |`String` | `"ALL"` | [`ThreadCount`][url-sheets] [url-exceedance]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/calc/ExceedanceModel.html [url-imt]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/gmm/Imt.html +[url-tectonicsetting]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/model/TectonicSetting.html +[url-sourcetype]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/model/SourceType.html [url-valueformat]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/calc/ValueFormat.html [url-distribution]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/calc/DistributionFormat.html [url-datatype]: https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/calc/DataType.html diff --git a/gradle.properties b/gradle.properties index c97c988f51647e4f24ca18df5a54d66ee1f6cb5d..04ae04e2d10f92e45bc0d81598dffd799e627f7d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ micronautVersion = 3.2.3 micronautRxVersion = 2.1.1 nodePluginVersion = 3.0.1 nodeVersion = 16.3.0 -nshmpLibVersion = 1.2.8 +nshmpLibVersion = 1.2.10 nshmpWsUtilsVersion = 0.3.11 openApiVersion = 4.0.0 shadowVersion = 7.1.2 diff --git a/gradle/nshm.gradle b/gradle/nshm.gradle index 5eecb87f60f13bc56d519bbdc4b64f494cd659df..0e1a39a17c9477faf6afe3985adf691099b5e3bc 100644 --- a/gradle/nshm.gradle +++ b/gradle/nshm.gradle @@ -43,7 +43,7 @@ clean.dependsOn cleanNshm task nshms() { dependsOn cleanNshm def yaml = new Yaml() - def nshmConfig = new Yaml().load(new File("nshms.yml").newInputStream()) + def nshmConfig = new Yaml().load(new File("${projectDir}/nshms.yml").newInputStream()) doLast { for (nshm in nshmConfig.nshms) { diff --git a/nshms.yml b/nshms.yml index 2a4f21e7658609ea651b2be297e2b01640164ab8..a3a2c9975aad5e793312fe004d113aeed02dedf4 100644 --- a/nshms.yml +++ b/nshms.yml @@ -5,7 +5,7 @@ nshms: # Alaska 2023 NSHM - repo: nshm-alaska - tag: 3.a.0 + tag: 3.a.1 year: 2023 deployments: development: @@ -32,7 +32,7 @@ nshms: # CONUS 2023 NSHM - repo: nshm-conus - tag: 6.a.3 + tag: 6.a.4 year: 2023 deployments: development: diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesController.java index 1c6b2396ffb5f88780752728a34d06fbdc555631..2f941ff14789f3fe25383dea32c0bb8b150c654b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesController.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesController.java @@ -70,7 +70,7 @@ public class LogicTreesController { description = "Returns the logic tree of features for the supplied ID", operationId = "source-tree-features") @ApiResponse( - description = "NSHM source logic tree", + description = "NSHM source logic tree of features", responseCode = "200", content = @Content( schema = @Schema(implementation = TreeResponse.class))) @@ -94,7 +94,7 @@ public class LogicTreesController { description = "Returns the logic tree of MFDs for the supplied ID", operationId = "source-tree-mfds") @ApiResponse( - description = "NSHM source logic tree", + description = "NSHM source logic tree of MFDs", responseCode = "200", content = @Content( schema = @Schema(implementation = TreeResponse.class))) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsController.java new file mode 100644 index 0000000000000000000000000000000000000000..3d87c87bb4dd583ed65f3528671a0d2511829333 --- /dev/null +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsController.java @@ -0,0 +1,131 @@ +package gov.usgs.earthquake.nshmp.www.source; + +import java.util.Optional; + +import gov.usgs.earthquake.nshmp.model.SourceType; +import gov.usgs.earthquake.nshmp.model.TectonicSetting; +import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet; +import gov.usgs.earthquake.nshmp.www.ResponseBody; +import gov.usgs.earthquake.nshmp.www.ServletUtil; +import gov.usgs.earthquake.nshmp.www.source.MfdsService.Metadata; +import gov.usgs.earthquake.nshmp.www.source.MfdsService.RequestData; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.inject.Inject; + +/** + * Micronaut web service controller for summed MFDs in the installed model. + * These endpoints return the magnitude frequency distributions (MFDs) + * associated with the different tectonic settings and source types present in + * the model. MFDs for requested tetonic settings and source types are scaled by + * their branch weights and then summed. + * + * <p>See src/main/resources/application.yml nshmp-haz.model-path for installed + * model. + * + * <p>To run the Micronaut jar file with a model: java -jar + * path/to/nshmp-haz.jar --model=<path/to/model> + * + * @author U.S. Geological Survey + */ +@Tag( + name = MfdsService.NAME, + description = "USGS NSHM source model MFD service") +@Controller("/mfds") +public class MfdsController { + + @Inject + private NshmpMicronautServlet servlet; + + @Operation( + summary = "Source model tectonic settings and source types", + description = "Returns the tectonic settings and source types in the model", + operationId = "source-mfd-metadata") + @ApiResponse( + description = "Source MFD metadata", + responseCode = "200", + content = @Content( + schema = @Schema( + implementation = MetadataResponse.class))) + @Get + public HttpResponse<String> doGetMetadata(HttpRequest<?> http) { + try { + return LogicTreesService.getMetadata(http); + } catch (Exception e) { + return ServletUtil.error( + LogicTreesService.LOG, e, + LogicTreesService.NAME, + http.getUri().toString()); + } + } + + /** + * @param setting model tectonic setting + */ + @Operation( + summary = "Get a source model MFD for a tectonic setting", + description = "Returns the total MFD for the supplied tectonic setting", + operationId = "source-setting-mfd") + @ApiResponse( + description = "NSHM source MFD", + responseCode = "200", + content = @Content( + schema = @Schema(implementation = Response.class))) + @Get(uri = "/{setting}") + public HttpResponse<String> doGetMfdSettingGroup( + HttpRequest<?> http, + @PathVariable TectonicSetting setting) { + try { + return MfdsService.getMfdGroup(http, setting, Optional.empty()); + } catch (Exception e) { + return ServletUtil.error( + LogicTreesService.LOG, e, + LogicTreesService.NAME, + http.getUri().toString()); + } + } + + /** + * @param setting model tectonic setting + * @param type model source type} + */ + @Operation( + summary = "Get a source model MFD for a tectonic setting and source type", + description = "Returns the total MFD for the supplied tectonic setting and source type", + operationId = "source-setting-type-mfd") + @ApiResponse( + description = "NSHM source MFD", + responseCode = "200", + content = @Content( + schema = @Schema(implementation = Response.class))) + @Get(uri = "/{setting}/{type}") + public HttpResponse<String> doGetMfdTypeGroup( + HttpRequest<?> http, + @PathVariable TectonicSetting setting, + @PathVariable SourceType type) { + try { + return MfdsService.getMfdGroup(http, setting, Optional.of(type)); + } catch (Exception e) { + return ServletUtil.error( + LogicTreesService.LOG, e, + LogicTreesService.NAME, + http.getUri().toString()); + } + } + + // Swagger schema + private static class MetadataResponse extends ResponseBody<String, Metadata> {} + + // Swagger schema + private static class Response extends ResponseBody<RequestData, Object> {} + +} diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java new file mode 100644 index 0000000000000000000000000000000000000000..4062fd449bc564e643924d10a62246d07410fe06 --- /dev/null +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java @@ -0,0 +1,107 @@ +package gov.usgs.earthquake.nshmp.www.source; + +import java.util.Optional; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gov.usgs.earthquake.nshmp.model.HazardModel; +import gov.usgs.earthquake.nshmp.model.Models; +import gov.usgs.earthquake.nshmp.model.SourceType; +import gov.usgs.earthquake.nshmp.model.TectonicSetting; +import gov.usgs.earthquake.nshmp.www.HazVersion; +import gov.usgs.earthquake.nshmp.www.ResponseBody; +import gov.usgs.earthquake.nshmp.www.ResponseMetadata; +import gov.usgs.earthquake.nshmp.www.ServletUtil; +import gov.usgs.earthquake.nshmp.www.source.SourceService.SourceModel; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpResponse; +import jakarta.inject.Singleton; + +/** + * Source model MFD handler {@link MfdsController} + * + * @author U.S. Geological Survey + */ +@Singleton +public class MfdsService { + + static final String NAME = "Model MFDs"; + static final Logger LOG = LoggerFactory.getLogger(LogicTreesService.class); + + public static HttpResponse<String> getMetadata(HttpRequest<?> request) { + var url = request.getUri().toString(); + var metadata = new Metadata(ServletUtil.model()); + var response = ResponseBody.usage() + .name(NAME) + .url(url) + .metadata(new ResponseMetadata(HazVersion.appVersions())) + .request(url) + .response(metadata) + .build(); + return HttpResponse.ok(ServletUtil.GSON2.toJson(response)); + } + + public static HttpResponse<String> getMfdGroup( + HttpRequest<?> request, + TectonicSetting setting, + Optional<SourceType> type) { + + var url = request.getUri().toString(); + var mfd = Models.mfd(ServletUtil.model(), setting, type); + var requestData = new RequestData(setting, type.orElse(null)); + var response = ResponseBody.success() + .name(NAME) + .url(url) + .metadata(new ResponseMetadata(HazVersion.appVersions())) + .request(requestData) + .response(mfd) + .build(); + return HttpResponse.ok(ServletUtil.GSON2.toJson(response)); + } + + static class Metadata { + final SourceModel model; + final Set<TectonicSetting> settings; + final Set<SourceType> types; + + Metadata(HazardModel model) { + this.model = new SourceModel(model); + this.settings = model.settings(); + this.types = model.types(); + } + + public SourceModel getModel() { + return model; + } + + public Set<TectonicSetting> getSettings() { + return settings; + } + + public Set<SourceType> getTypes() { + return types; + } + } + + static class RequestData { + final TectonicSetting setting; + final SourceType type; + + RequestData(TectonicSetting setting, SourceType type) { + this.setting = setting; + this.type = type; + } + + public TectonicSetting getSetting() { + return setting; + } + + public SourceType getType() { + return type; + } + } + +}