diff --git a/src/main/App.kt b/src/main/App.kt index 7f56770..0b11698 100644 --- a/src/main/App.kt +++ b/src/main/App.kt @@ -1,5 +1,6 @@ package com.github.statnett.loadflowservice +import com.powsybl.sensitivity.SensitivityAnalysis import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* @@ -111,6 +112,24 @@ fun Application.module() { call.respondText(diagram, ContentType.Image.SVG, HttpStatusCode.OK) } } + + post("/sensitivity-analysis") { + val loadParamCnt = LoadParameterContainer() + val sensParamCnt = SensitivityAnalysisParametersContainer() + val sensFactorCnt = SensitivityFactorContainer() + val contingencyCnt = ContingencyListContainer() + val itemHandler = MultiFormItemLoaders(listOf(loadParamCnt, sensParamCnt, sensFactorCnt, contingencyCnt)) + + val files = multiPartDataHandler(call.receiveMultipart(), itemHandler::formItemHandler) + if (files.isEmpty()) { + call.response.status(HttpStatusCode.UnprocessableEntity) + } else { + sensParamCnt.parameters.setLoadFlowParameters(loadParamCnt.parameters) + val network = networkFromFileContent(files[0]) + val result = runSensitivityAnalysis(network, sensFactorCnt.factors, sensParamCnt.parameters, contingencyCnt.contingencies) + call.respondText(result, ContentType.Application.Json, HttpStatusCode.OK) + } + } swaggerUI(path = "openapi", swaggerFile = "openapi/documentation.yaml") } } diff --git a/src/main/ContingencyListContainer.kt b/src/main/ContingencyListContainer.kt index 5c7455e..c32caf0 100644 --- a/src/main/ContingencyListContainer.kt +++ b/src/main/ContingencyListContainer.kt @@ -1,6 +1,7 @@ package com.github.statnett.loadflowservice import com.powsybl.contingency.contingency.list.ContingencyList +import com.powsybl.contingency.contingency.list.DefaultContingencyList import com.powsybl.contingency.json.JsonContingencyListLoader import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.http.content.* @@ -8,7 +9,7 @@ import io.ktor.http.content.* private val logger = KotlinLogging.logger {} class ContingencyListContainer : AutoVersionableJsonParser(), FormItemLoadable { - var contingencies: ContingencyList? = null + var contingencies: ContingencyList = DefaultContingencyList() override fun currentVersion(): String { return ContingencyList.VERSION diff --git a/src/main/MultiFormItemLoaders.kt b/src/main/MultiFormItemLoaders.kt new file mode 100644 index 0000000..7040f21 --- /dev/null +++ b/src/main/MultiFormItemLoaders.kt @@ -0,0 +1,10 @@ +package com.github.statnett.loadflowservice + +import io.ktor.http.content.* + +class MultiFormItemLoaders(private val loaders: List): FormItemLoadable { + + override fun formItemHandler(part: PartData.FormItem) { + this.loaders.forEach {loader -> loader.formItemHandler(part) } + } +} \ No newline at end of file diff --git a/src/main/Solver.kt b/src/main/Solver.kt index a501220..ea950f1 100644 --- a/src/main/Solver.kt +++ b/src/main/Solver.kt @@ -1,13 +1,17 @@ package com.github.statnett.loadflowservice import com.powsybl.commons.PowsyblException +import com.powsybl.commons.json.JsonUtil import com.powsybl.commons.reporter.Reporter import com.powsybl.commons.reporter.ReporterModel import com.powsybl.computation.local.LocalComputationManager +import com.powsybl.contingency.contingency.list.ContingencyList import com.powsybl.iidm.network.* import com.powsybl.loadflow.LoadFlow import com.powsybl.loadflow.LoadFlowParameters import com.powsybl.loadflow.json.JsonLoadFlowParameters +import com.powsybl.sensitivity.* +import com.powsybl.sensitivity.json.SensitivityJsonModule import io.github.oshai.kotlinlogging.KotlinLogging import java.io.ByteArrayOutputStream import java.io.StringWriter @@ -90,3 +94,28 @@ fun solve( report = reporterToString(reporter) ) } + +fun runSensitivityAnalysis(network: Network, factors: List, params: SensitivityAnalysisParameters, contingenciesList: ContingencyList): String { + val reporter = ReporterModel("sensitivity", "") + val variableSets: List = listOf() + val contingencies = contingenciesList.getContingencies(network) + val factorReader = SensitivityFactorModelReader(factors, network) + + val factory = JsonUtil.createJsonFactory() + val writer = StringWriter() + val jsonGenerator = factory.createGenerator(writer) + val resultWriter = SensitivityResultJsonWriter(jsonGenerator, contingencies) + + SensitivityAnalysis.run( + network, + network.variantManager.workingVariantId, + factorReader, + resultWriter, + contingencies, + variableSets, + params, + LocalComputationManager.getDefault(), + reporter + ) + return resultWriter.toString() +} \ No newline at end of file