├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── ci.yml │ └── dependabot-auto-merge.yml ├── .gitignore ├── .readthedocs.yaml ├── .scalafmt.conf ├── AUTHORS.md ├── CHANGELOG.md ├── CITATION.cff ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── build.gradle ├── docs ├── logo │ └── logo_tightcrop_transparent.png ├── readthedocs │ ├── Makefile │ ├── _static │ │ ├── bibliography │ │ │ ├── bibAboutSimona.bib │ │ │ └── bibtexAll.bib │ │ └── figures │ │ │ ├── models │ │ │ ├── bm_model │ │ │ │ ├── bm_behaviour.png │ │ │ │ ├── bm_parameters.png │ │ │ │ └── mc.png │ │ │ ├── chp_model │ │ │ │ ├── ChpModelCalculation.png │ │ │ │ ├── ChpModelMathematicalNotations.png │ │ │ │ ├── ModelChpModelCalculationConcept.png │ │ │ │ └── chp4.png │ │ │ ├── pv_model │ │ │ │ └── ModelPv.png │ │ │ ├── transformer_model │ │ │ │ ├── ModelTwt.png │ │ │ │ └── tecdoc_tc1.jpg │ │ │ └── wec_model │ │ │ │ ├── EnerconE82cpPlot.png │ │ │ │ └── WecModelCalculation.png │ │ │ └── uml │ │ │ ├── InitializationPhase.png │ │ │ ├── ParticipantTriggeredByItself.png │ │ │ ├── ParticipantTriggeredByPrimaryData.png │ │ │ └── ParticipantTriggeredBySecondaryData.png │ ├── about.md │ ├── conf.py │ ├── config.md │ ├── developersguide.md │ ├── howto │ │ └── weatherDataHowToCopernicusERA5.md │ ├── images │ │ └── usersguide │ │ │ ├── agent_messages.png │ │ │ ├── basic_simona_environment.png │ │ │ ├── copy-path.png │ │ │ ├── edit-conf.png │ │ │ ├── edit-conf2.png │ │ │ ├── jdk-download.png │ │ │ ├── scala-plugin.png │ │ │ └── scala-sdk-error.png │ ├── index.md │ ├── make.bat │ ├── models.md │ ├── models │ │ ├── bm_model.md │ │ ├── chp_model.md │ │ ├── cts_model.md │ │ ├── em.md │ │ ├── evcs_model.md │ │ ├── hp_model.md │ │ ├── line_model.md │ │ ├── load_model.md │ │ ├── measurement_control.md │ │ ├── pv_model.md │ │ ├── reference_system.md │ │ ├── switch_model.md │ │ ├── thermal_grid_model.md │ │ ├── thermal_house_model.md │ │ ├── three_winding_transformer_model.md │ │ ├── two_winding_transformer_model.md │ │ ├── voltage_limits.md │ │ └── wec_model.md │ ├── protocols.md │ ├── references.md │ ├── requirements.txt │ └── usersguide.md └── uml │ ├── main │ ├── ExtEvSimulationClasses.puml │ ├── ParticipantInheritance.puml │ ├── ParticipantModelling.puml │ ├── StateDataHierarchy.puml │ ├── em │ │ └── PrioritizedFlexStrat.puml │ ├── models │ │ ├── pv_model │ │ │ └── BehaviourPvModel.puml │ │ └── thermal │ │ │ └── grid │ │ │ ├── HandleConsumption.puml │ │ │ └── HandleInfeed.puml │ └── participants │ │ ├── ChpModelCalculation.puml │ │ ├── ChpModelCalculationConcept.puml │ │ ├── HpModelCalculation.puml │ │ └── WecModelCalculation.puml │ └── protocol │ ├── ExtEvSimulationSequence.puml │ ├── InitializationPhase.puml │ ├── ParticipantTriggeredByItself.puml │ ├── ParticipantTriggeredByPrimaryData.puml │ ├── ParticipantTriggeredBySecondaryData.puml │ └── em │ ├── ControlledEm.puml │ └── UncontrolledEm.puml ├── gradle.properties ├── gradle ├── scripts │ ├── branchName.gradle │ ├── checkJavaVersion.gradle │ ├── deploy.gradle │ ├── documentation.gradle │ ├── mavenCentralPublish.gradle │ ├── scoverage.gradle │ ├── semVer.gradle │ ├── sonarqube.gradle │ ├── spotless.gradle │ └── tests.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── greclipse.properties ├── input └── samples │ ├── common │ └── pekko.conf │ └── vn_simona │ ├── fullGrid │ ├── bm_input.csv │ ├── bm_type_input.csv │ ├── evcs_input.csv │ ├── fixed_feed_in_input.csv │ ├── its_pq_8c04e94e-76b0-4369-a55c-f5e1117fb83e.csv │ ├── line_graphic_input.csv │ ├── line_input.csv │ ├── line_type_input.csv │ ├── load_input.csv │ ├── measurement_unit_input.csv │ ├── node_graphic_input.csv │ ├── node_input.csv │ ├── pv_input.csv │ ├── storage_type_input.csv │ ├── time_series_mapping.csv │ ├── transformer_2_w_input.csv │ ├── transformer_2_w_type_input.csv │ ├── wec_input.csv │ └── wec_type_input.csv │ └── vn_simona.conf ├── scripts ├── branch_type.sh ├── get_versions.sh ├── run-version-check.sh └── version_check.sh ├── settings.gradle ├── src ├── main │ ├── resources │ │ ├── META-INF │ │ │ └── services │ │ │ │ └── tech.units.indriya.spi.NumberSystem │ │ ├── log4j2 │ │ │ └── log4j2-dev.xml │ │ └── logback.xml │ ├── scala │ │ └── edu │ │ │ └── ie3 │ │ │ ├── simona │ │ │ ├── actor │ │ │ │ ├── ActorUtil.scala │ │ │ │ └── SimonaActorNaming.scala │ │ │ ├── agent │ │ │ │ ├── EnvironmentRefs.scala │ │ │ │ ├── em │ │ │ │ │ ├── EmAgent.scala │ │ │ │ │ ├── EmDataCore.scala │ │ │ │ │ ├── FlexControlledData.scala │ │ │ │ │ └── FlexCorrespondenceStore.scala │ │ │ │ ├── grid │ │ │ │ │ ├── DBFSAlgorithm.scala │ │ │ │ │ ├── GridAgent.scala │ │ │ │ │ ├── GridAgentBuilder.scala │ │ │ │ │ ├── GridAgentData.scala │ │ │ │ │ ├── GridAgentDataHelper.scala │ │ │ │ │ ├── GridAgentMessages.scala │ │ │ │ │ ├── GridEnvironment.scala │ │ │ │ │ ├── GridResultsSupport.scala │ │ │ │ │ ├── PowerFlowParams.scala │ │ │ │ │ ├── PowerFlowSupport.scala │ │ │ │ │ ├── ReceivedValuesStore.scala │ │ │ │ │ ├── SweepValueStore.scala │ │ │ │ │ └── congestion │ │ │ │ │ │ ├── CongestedComponents.scala │ │ │ │ │ │ ├── CongestionManagementMessages.scala │ │ │ │ │ │ ├── CongestionManagementParams.scala │ │ │ │ │ │ ├── Congestions.scala │ │ │ │ │ │ ├── DCMAlgorithm.scala │ │ │ │ │ │ ├── data │ │ │ │ │ │ ├── AwaitingData.scala │ │ │ │ │ │ └── CongestionManagementData.scala │ │ │ │ │ │ └── detection │ │ │ │ │ │ ├── CongestionDetection.scala │ │ │ │ │ │ └── DetectionMessages.scala │ │ │ │ └── participant │ │ │ │ │ ├── ParticipantAgent.scala │ │ │ │ │ ├── ParticipantAgentInit.scala │ │ │ │ │ ├── ParticipantGridAdapter.scala │ │ │ │ │ ├── ParticipantInputHandler.scala │ │ │ │ │ └── ParticipantResultHandler.scala │ │ │ ├── api │ │ │ │ └── ExtSimAdapter.scala │ │ │ ├── config │ │ │ │ ├── ArgsParser.scala │ │ │ │ ├── ConfigConventions.scala │ │ │ │ ├── ConfigFailFast.scala │ │ │ │ ├── ConfigParams.scala │ │ │ │ ├── GridConfigParser.scala │ │ │ │ ├── InputConfig.scala │ │ │ │ ├── OutputConfig.scala │ │ │ │ ├── RuntimeConfig.scala │ │ │ │ ├── SimonaConfig.scala │ │ │ │ └── VoltLvlParser.scala │ │ │ ├── event │ │ │ │ ├── Event.scala │ │ │ │ ├── ResultEvent.scala │ │ │ │ ├── RuntimeEvent.scala │ │ │ │ ├── listener │ │ │ │ │ ├── DeadLetterListener.scala │ │ │ │ │ ├── DelayedStopHelper.scala │ │ │ │ │ ├── ResultEventListener.scala │ │ │ │ │ ├── RuntimeEventListener.scala │ │ │ │ │ └── Transformer3wResultSupport.scala │ │ │ │ └── notifier │ │ │ │ │ ├── Notifier.scala │ │ │ │ │ └── NotifierConfig.scala │ │ │ ├── exceptions │ │ │ │ ├── CharacteristicsException.scala │ │ │ │ ├── CriticalFailureException.scala │ │ │ │ ├── FileHierarchyException.scala │ │ │ │ ├── FileIOException.scala │ │ │ │ ├── FlexException.scala │ │ │ │ ├── GridInconsistencyException.scala │ │ │ │ ├── InitializationException.scala │ │ │ │ ├── InvalidActionRequestException.scala │ │ │ │ ├── InvalidConfigParameterException.scala │ │ │ │ ├── InvalidParameterException.scala │ │ │ │ ├── ProcessResultEventException.scala │ │ │ │ ├── QControlException.scala │ │ │ │ ├── QuantityException.scala │ │ │ │ ├── SchedulerException.scala │ │ │ │ ├── ServiceException.scala │ │ │ │ ├── SimonaAnalysisException.scala │ │ │ │ ├── WeatherServiceException.scala │ │ │ │ └── agent │ │ │ │ │ ├── ActorNotRegisteredException.scala │ │ │ │ │ ├── AgentInitializationException.scala │ │ │ │ │ ├── DBFSAlgorithmException.scala │ │ │ │ │ ├── GridAgentInitializationException.scala │ │ │ │ │ ├── InconsistentStateException.scala │ │ │ │ │ ├── InvalidRequestException.scala │ │ │ │ │ └── ServiceRegistrationException.scala │ │ │ ├── io │ │ │ │ ├── grid │ │ │ │ │ ├── GridProvider.scala │ │ │ │ │ └── GridSourceType.scala │ │ │ │ ├── result │ │ │ │ │ ├── AccompaniedSimulationResult.scala │ │ │ │ │ ├── ResultEntityCsvSink.scala │ │ │ │ │ ├── ResultEntityInfluxDbSink.scala │ │ │ │ │ ├── ResultEntityKafkaSink.scala │ │ │ │ │ ├── ResultEntitySink.scala │ │ │ │ │ ├── ResultSinkType.scala │ │ │ │ │ └── plain │ │ │ │ │ │ ├── PlainResult.scala │ │ │ │ │ │ └── PlainWriter.scala │ │ │ │ └── runtime │ │ │ │ │ ├── RuntimeEventKafkaSink.scala │ │ │ │ │ ├── RuntimeEventLogSink.scala │ │ │ │ │ ├── RuntimeEventQueueSink.scala │ │ │ │ │ └── RuntimeEventSink.scala │ │ │ ├── logging │ │ │ │ └── LogbackConfiguration.scala │ │ │ ├── main │ │ │ │ ├── RunSimona.scala │ │ │ │ └── RunSimonaStandalone.scala │ │ │ ├── model │ │ │ │ ├── InputModelContainer.scala │ │ │ │ ├── SystemComponent.scala │ │ │ │ ├── control │ │ │ │ │ ├── GridControls.scala │ │ │ │ │ └── TransformerControlGroupModel.scala │ │ │ │ ├── em │ │ │ │ │ ├── EmAggregateFlex.scala │ │ │ │ │ ├── EmAggregatePowerOpt.scala │ │ │ │ │ ├── EmAggregateSimpleSum.scala │ │ │ │ │ ├── EmModelShell.scala │ │ │ │ │ ├── EmModelStrat.scala │ │ │ │ │ ├── EmTools.scala │ │ │ │ │ ├── PrioritizedFlexStrat.scala │ │ │ │ │ └── ProportionalFlexStrat.scala │ │ │ │ ├── grid │ │ │ │ │ ├── GridModel.scala │ │ │ │ │ ├── LineModel.scala │ │ │ │ │ ├── NodeModel.scala │ │ │ │ │ ├── PiEquivalentCircuit.scala │ │ │ │ │ ├── RefSystem.scala │ │ │ │ │ ├── SwitchModel.scala │ │ │ │ │ ├── Transformer3wModel.scala │ │ │ │ │ ├── Transformer3wPowerFlowCase.scala │ │ │ │ │ ├── TransformerModel.scala │ │ │ │ │ ├── TransformerTapping.scala │ │ │ │ │ ├── TransformerTappingModel.scala │ │ │ │ │ └── VoltageLimits.scala │ │ │ │ ├── participant │ │ │ │ │ ├── BmModel.scala │ │ │ │ │ ├── ChargingHelper.scala │ │ │ │ │ ├── FixedFeedInModel.scala │ │ │ │ │ ├── HpModel.scala │ │ │ │ │ ├── ParticipantFlexibility.scala │ │ │ │ │ ├── ParticipantModel.scala │ │ │ │ │ ├── ParticipantModelInit.scala │ │ │ │ │ ├── ParticipantModelShell.scala │ │ │ │ │ ├── PrimaryDataParticipantModel.scala │ │ │ │ │ ├── PvModel.scala │ │ │ │ │ ├── SolarIrradiationCalculation.scala │ │ │ │ │ ├── StorageModel.scala │ │ │ │ │ ├── WecModel.scala │ │ │ │ │ ├── control │ │ │ │ │ │ └── QControl.scala │ │ │ │ │ ├── evcs │ │ │ │ │ │ ├── ConstantPowerCharging.scala │ │ │ │ │ │ ├── EvModelWrapper.scala │ │ │ │ │ │ ├── EvcsChargingProperties.scala │ │ │ │ │ │ ├── EvcsChargingStrategy.scala │ │ │ │ │ │ ├── EvcsModel.scala │ │ │ │ │ │ └── MaximumPowerCharging.scala │ │ │ │ │ └── load │ │ │ │ │ │ ├── FixedLoadModel.scala │ │ │ │ │ │ ├── LoadModel.scala │ │ │ │ │ │ ├── LoadModelBehaviour.scala │ │ │ │ │ │ ├── LoadReferenceType.scala │ │ │ │ │ │ └── ProfileLoadModel.scala │ │ │ │ ├── system │ │ │ │ │ └── Characteristic.scala │ │ │ │ └── thermal │ │ │ │ │ ├── CylindricalThermalStorage.scala │ │ │ │ │ ├── ThermalGrid.scala │ │ │ │ │ ├── ThermalHouse.scala │ │ │ │ │ ├── ThermalSink.scala │ │ │ │ │ ├── ThermalStorage.scala │ │ │ │ │ └── ThermalThreshold.scala │ │ │ ├── ontology │ │ │ │ ├── GridAgentHierarchy.scala │ │ │ │ └── messages │ │ │ │ │ ├── Activation.scala │ │ │ │ │ ├── SchedulerMessage.scala │ │ │ │ │ ├── flex │ │ │ │ │ ├── FlexOptions.scala │ │ │ │ │ ├── FlexibilityMessage.scala │ │ │ │ │ └── MinMaxFlexOptions.scala │ │ │ │ │ └── services │ │ │ │ │ ├── EvMessage.scala │ │ │ │ │ ├── LoadProfileMessage.scala │ │ │ │ │ ├── ServiceMessage.scala │ │ │ │ │ └── WeatherMessage.scala │ │ │ ├── scheduler │ │ │ │ ├── RuntimeNotifier.scala │ │ │ │ ├── ScheduleLock.scala │ │ │ │ ├── Scheduler.scala │ │ │ │ ├── TimeAdvancer.scala │ │ │ │ └── core │ │ │ │ │ ├── Core.scala │ │ │ │ │ └── RegularSchedulerCore.scala │ │ │ ├── service │ │ │ │ ├── Data.scala │ │ │ │ ├── ExtDataSupport.scala │ │ │ │ ├── ServiceStateData.scala │ │ │ │ ├── ServiceType.scala │ │ │ │ ├── SimonaService.scala │ │ │ │ ├── ev │ │ │ │ │ └── ExtEvDataService.scala │ │ │ │ ├── load │ │ │ │ │ ├── LoadProfileService.scala │ │ │ │ │ ├── LoadProfileSources.scala │ │ │ │ │ └── LoadProfileStore.scala │ │ │ │ ├── primary │ │ │ │ │ ├── PrimaryServiceProxy.scala │ │ │ │ │ └── PrimaryServiceWorker.scala │ │ │ │ └── weather │ │ │ │ │ ├── SampleWeatherSource.scala │ │ │ │ │ ├── WeatherService.scala │ │ │ │ │ ├── WeatherSource.scala │ │ │ │ │ └── WeatherSourceWrapper.scala │ │ │ ├── sim │ │ │ │ ├── SimonaSim.scala │ │ │ │ └── setup │ │ │ │ │ ├── ExtSimLoader.scala │ │ │ │ │ ├── ExtSimSetup.scala │ │ │ │ │ ├── ExtSimSetupData.scala │ │ │ │ │ ├── SetupHelper.scala │ │ │ │ │ ├── SimonaSetup.scala │ │ │ │ │ └── SimonaStandaloneSetup.scala │ │ │ └── util │ │ │ │ ├── CollectionUtils.scala │ │ │ │ ├── ConfigUtil.scala │ │ │ │ ├── EntityMapperUtil.scala │ │ │ │ ├── ParsableEnumeration.scala │ │ │ │ ├── ReceiveDataMap.scala │ │ │ │ ├── ResultFileHierarchy.scala │ │ │ │ ├── SimonaConstants.scala │ │ │ │ └── TickUtil.scala │ │ │ └── util │ │ │ └── scala │ │ │ ├── OperationInterval.scala │ │ │ ├── Scope.scala │ │ │ ├── collection │ │ │ ├── immutable │ │ │ │ └── SortedDistinctSeq.scala │ │ │ └── mutable │ │ │ │ └── PriorityMultiBiSet.scala │ │ │ ├── io │ │ │ ├── GraphicDataCleaner.scala │ │ │ └── ScalaReflectionSerde.scala │ │ │ └── quantities │ │ │ ├── ApparentPower.scala │ │ │ ├── DefaultQuantities.scala │ │ │ ├── EnergyDensity.scala │ │ │ ├── EnergyPrice.scala │ │ │ ├── Irradiance.scala │ │ │ ├── Irradiation.scala │ │ │ ├── QuantityConversionUtils.scala │ │ │ ├── QuantityUtil.scala │ │ │ ├── ReactivePower.scala │ │ │ ├── ScalaNumberSystem.scala │ │ │ ├── SpecificHeatCapacity.scala │ │ │ ├── Sq.scala │ │ │ ├── SquantsUtils.scala │ │ │ └── ThermalConductance.scala │ └── sh │ │ └── deploy │ │ ├── README.md │ │ ├── influxDb1x │ │ ├── docker │ │ │ ├── start_docker_grafana.sh │ │ │ ├── start_docker_influxdb.sh │ │ │ └── wait-for.sh │ │ ├── grafana │ │ │ └── provisioning │ │ │ │ └── datasources │ │ │ │ └── datasource.yml │ │ └── run_influxdb_with_metrics.sh │ │ ├── init-run.sh │ │ └── run-simona-cmd.sh └── test │ ├── java │ ├── edu │ │ └── ie3 │ │ │ └── simona │ │ │ └── test │ │ │ └── common │ │ │ └── model │ │ │ └── MockEvModel.java │ └── testutils │ │ └── TestObjectFactory.java │ ├── resources │ ├── edu │ │ └── ie3 │ │ │ └── simona │ │ │ ├── model │ │ │ └── participant │ │ │ │ └── _pv │ │ │ │ └── it │ │ │ │ ├── results.tar.gz │ │ │ │ └── weather.tar.gz │ │ │ ├── service │ │ │ ├── load │ │ │ │ └── _it │ │ │ │ │ └── lpts_g0.csv │ │ │ └── primary │ │ │ │ ├── _it │ │ │ │ ├── its_p_3fbfaa97-cff4-46d4-95ba-a95665e87c27.csv │ │ │ │ ├── its_p_9185b8c1-86ba-4a16-8dea-5ac898e8caa5.csv │ │ │ │ ├── its_pq_3fbfaa97-cff4-46d4-95ba-a95665e87c26.csv │ │ │ │ └── time_series_mapping.csv │ │ │ │ └── _timeseries │ │ │ │ ├── time_series_mapping.sql │ │ │ │ ├── time_series_p.sql │ │ │ │ └── time_series_pqh.sql │ │ │ └── sim │ │ │ └── setup │ │ │ └── ext-sim-loader │ │ │ ├── _jars │ │ │ ├── irrelevant.txt │ │ │ ├── mock_ext_sim-2.jar │ │ │ ├── mock_ext_sim-empty_file.jar │ │ │ ├── mock_ext_sim-missing_service_file.jar │ │ │ ├── mock_ext_sim-two_implementations.jar │ │ │ ├── mock_ext_sim-wrong_implementation.jar │ │ │ └── mock_ext_sim.jar │ │ │ └── _no-jars │ │ │ └── irrelevant.txt │ ├── log4j2-it.xml │ ├── log4j2-test.xml │ └── logback-test.xml │ └── scala │ └── edu │ └── ie3 │ ├── simona │ ├── agent │ │ ├── em │ │ │ ├── EmAgentIT.scala │ │ │ └── EmAgentSpec.scala │ │ ├── grid │ │ │ ├── DBFSAlgorithmCenGridSpec.scala │ │ │ ├── DBFSAlgorithmFailedPowerFlowSpec.scala │ │ │ ├── DBFSAlgorithmParticipantSpec.scala │ │ │ ├── DBFSAlgorithmSupGridSpec.scala │ │ │ ├── DBFSMockGridAgents.scala │ │ │ ├── GridAgentDataHelperSpec.scala │ │ │ ├── GridAgentSetupSpec.scala │ │ │ ├── GridResultsSupportSpec.scala │ │ │ ├── PowerFlowSupportSpec.scala │ │ │ ├── ReceivedValuesStoreSpec.scala │ │ │ ├── ThermalGridIT.scala │ │ │ └── congestion │ │ │ │ ├── CongestedComponentsSpec.scala │ │ │ │ ├── CongestionTestBaseData.scala │ │ │ │ ├── DCMAlgorithmSpec.scala │ │ │ │ ├── data │ │ │ │ └── CongestionManagementDataSpec.scala │ │ │ │ └── detection │ │ │ │ └── CongestionDetectionSpec.scala │ │ └── participant │ │ │ ├── MockParticipantModel.scala │ │ │ ├── ParticipantAgentInitSpec.scala │ │ │ ├── ParticipantAgentMockFactory.scala │ │ │ └── ParticipantAgentSpec.scala │ ├── api │ │ └── ExtSimAdapterSpec.scala │ ├── config │ │ ├── ConfigFailFastSpec.scala │ │ └── GridConfigParserSpec.scala │ ├── deploy │ │ └── DeploySpec.scala │ ├── event │ │ ├── NotifierSpec.scala │ │ └── listener │ │ │ ├── ResultEventListenerSpec.scala │ │ │ ├── RuntimeEventListenerKafkaSpec.scala │ │ │ ├── RuntimeEventListenerLoggingSpec.scala │ │ │ ├── RuntimeEventListenerSpec.scala │ │ │ ├── RuntimeTestData.scala │ │ │ ├── ThreeWindingResultHandlingSpec.scala │ │ │ └── ThreeWindingResultTestData.scala │ ├── integration │ │ ├── RunSimonaStandaloneIT.scala │ │ └── common │ │ │ └── IntegrationSpecCommon.scala │ ├── io │ │ ├── file │ │ │ └── ResultFileHierarchySpec.scala │ │ └── result │ │ │ ├── ResultEntityCsvSinkSpec.scala │ │ │ ├── ResultEntityKafkaSpec.scala │ │ │ ├── ResultSinkTypeSpec.scala │ │ │ └── plain │ │ │ └── PlainWriterSpec.scala │ ├── model │ │ ├── assets │ │ │ └── control │ │ │ │ └── QControlSpec.scala │ │ ├── control │ │ │ └── TransformerControlGroupModelSpec.scala │ │ ├── em │ │ │ ├── EmAggregatePowerOptSpec.scala │ │ │ ├── EmAggregateSimpleSumSpec.scala │ │ │ ├── EmModelShellSpec.scala │ │ │ ├── PrioritizedFlexStratSpec.scala │ │ │ └── ProportionalFlexStratSpec.scala │ │ ├── grid │ │ │ ├── GridSpec.scala │ │ │ ├── LineSpec.scala │ │ │ ├── NodeInputModelSpec.scala │ │ │ ├── RefSystemSpec.scala │ │ │ ├── SwitchModelSpec.scala │ │ │ ├── SystemComponentSpec.scala │ │ │ ├── Transformer3wModelSpec.scala │ │ │ ├── TransformerModelSpec.scala │ │ │ └── TransformerTappingModelSpec.scala │ │ ├── participant │ │ │ ├── BmModelSpec.scala │ │ │ ├── ChargingHelperSpec.scala │ │ │ ├── FixedFeedInModelSpec.scala │ │ │ ├── HpModelSpec.scala │ │ │ ├── PvModelITHelper.scala │ │ │ ├── PvModelITSpec.scala │ │ │ ├── PvModelSpec.scala │ │ │ ├── SolarIrradiationCalculationSpec.scala │ │ │ ├── StorageModelSpec.scala │ │ │ ├── WecModelSpec.scala │ │ │ ├── evcs │ │ │ │ ├── ConstantPowerChargingSpec.scala │ │ │ │ ├── EvcsModelIT.scala │ │ │ │ ├── EvcsModelSpec.scala │ │ │ │ ├── MaximumPowerChargingSpec.scala │ │ │ │ └── MockEvcsChargingProperties.scala │ │ │ └── load │ │ │ │ ├── FixedLoadModelSpec.scala │ │ │ │ ├── LoadModelTestHelper.scala │ │ │ │ └── ProfileLoadModelSpec.scala │ │ ├── system │ │ │ └── CharacteristicSpec.scala │ │ └── thermal │ │ │ ├── CylindricalThermalStorageSpec.scala │ │ │ ├── ThermalGridSpec.scala │ │ │ ├── ThermalGridTestData.scala │ │ │ ├── ThermalGridWithHouseAndStorageSpec.scala │ │ │ ├── ThermalGridWithHouseOnlySpec.scala │ │ │ ├── ThermalGridWithStorageOnlySpec.scala │ │ │ ├── ThermalHouseSpec.scala │ │ │ ├── ThermalHouseTestData.scala │ │ │ └── ThermalStorageTestData.scala │ ├── ontology │ │ └── messages │ │ │ └── flex │ │ │ └── MinMaxFlexOptionsSpec.scala │ ├── scheduler │ │ ├── ScheduleLockIT.scala │ │ ├── ScheduleLockSpec.scala │ │ ├── SchedulerSpec.scala │ │ └── TimeAdvancerSpec.scala │ ├── service │ │ ├── DataSpec.scala │ │ ├── RichValueSpec.scala │ │ ├── ev │ │ │ └── ExtEvDataServiceSpec.scala │ │ ├── load │ │ │ ├── LoadProfileServiceSpec.scala │ │ │ ├── LoadProfileSourcesSpec.scala │ │ │ └── LoadProfileStoreSpec.scala │ │ ├── primary │ │ │ ├── PrimaryServiceProxySpec.scala │ │ │ ├── PrimaryServiceProxySqlIT.scala │ │ │ ├── PrimaryServiceWorkerSpec.scala │ │ │ └── PrimaryServiceWorkerSqlIT.scala │ │ └── weather │ │ │ ├── SampleWeatherSourceSpec.scala │ │ │ ├── WeatherServiceSpec.scala │ │ │ ├── WeatherSourceSpec.scala │ │ │ └── WeatherSourceWrapperSpec.scala │ ├── sim │ │ ├── SimonaSimSpec.scala │ │ └── setup │ │ │ ├── ExtSimLoaderSpec.scala │ │ │ ├── ExtSimSetupDataSpec.scala │ │ │ ├── ExtSimSetupSpec.scala │ │ │ ├── SetupHelperSpec.scala │ │ │ └── SimonaSetupSpec.scala │ ├── test │ │ ├── KafkaSpecLike.scala │ │ ├── ParticipantAgentSpec.scala │ │ ├── common │ │ │ ├── AgentSpec.scala │ │ │ ├── ConfigTestData.scala │ │ │ ├── DefaultTestData.scala │ │ │ ├── EvTestData.scala │ │ │ ├── IOTestCommons.scala │ │ │ ├── SilentTestEventListener.scala │ │ │ ├── TestKitWithShutdown.scala │ │ │ ├── TestSpawnerTyped.scala │ │ │ ├── ThreeWindingTestData.scala │ │ │ ├── UnitSpec.scala │ │ │ ├── exceptions │ │ │ │ └── InvalidTestDataException.scala │ │ │ ├── input │ │ │ │ ├── EmInputTestData.scala │ │ │ │ ├── EvcsInputTestData.scala │ │ │ │ ├── FixedFeedInputTestData.scala │ │ │ │ ├── GridInputTestData.scala │ │ │ │ ├── HpInputTestData.scala │ │ │ │ ├── LineInputTestData.scala │ │ │ │ ├── LoadInputTestData.scala │ │ │ │ ├── NodeInputTestData.scala │ │ │ │ ├── PvInputTestData.scala │ │ │ │ ├── StorageInputTestData.scala │ │ │ │ ├── SwitchInputTestData.scala │ │ │ │ ├── TimeSeriesTestData.scala │ │ │ │ ├── Transformer3wTestData.scala │ │ │ │ ├── TransformerInputTestData.scala │ │ │ │ ├── WecInputTestData.scala │ │ │ │ └── WecTypeInputTestData.scala │ │ │ ├── model │ │ │ │ ├── grid │ │ │ │ │ ├── BasicGrid.scala │ │ │ │ │ ├── BasicGridWithSwitches.scala │ │ │ │ │ ├── DbfsTestGrid.scala │ │ │ │ │ ├── DbfsTestGridWithParticipants.scala │ │ │ │ │ ├── FiveLinesWithNodes.scala │ │ │ │ │ ├── SubGridGateMokka.scala │ │ │ │ │ ├── TapTestData.scala │ │ │ │ │ ├── TransformerTestData.scala │ │ │ │ │ └── TransformerTestGrid.scala │ │ │ │ ├── participant │ │ │ │ │ └── LoadTestData.scala │ │ │ │ └── system │ │ │ │ │ └── CharacteristicTestData.scala │ │ │ └── result │ │ │ │ ├── CongestedComponentsTestData.scala │ │ │ │ └── PowerFlowResultData.scala │ │ ├── helper │ │ │ ├── TableDrivenHelper.scala │ │ │ └── TestContainerHelper.scala │ │ └── matchers │ │ │ ├── DoubleMatchers.scala │ │ │ ├── QuantityMatchers.scala │ │ │ ├── QuantityMatchersSpec.scala │ │ │ └── SquantsMatchers.scala │ └── util │ │ ├── ActorUtils.scala │ │ ├── CollectionUtilsSpec.scala │ │ ├── ConfigUtilSpec.scala │ │ ├── TestGridFactory.scala │ │ ├── TickUtilSpec.scala │ │ └── collection │ │ └── immutable │ │ └── SortedDistinctSeqSpec.scala │ └── util │ ├── quantities │ ├── EnergyDensitySpec.scala │ ├── EnergyPriceSpec.scala │ ├── IrradianceSpec.scala │ ├── IrradiationSpec.scala │ ├── QuantityConversionUtilsSpec.scala │ ├── QuantityUtilSpec.scala │ ├── ReactivePowerSpec.scala │ ├── SpecificHeatCapacitySpec.scala │ └── ThermalConductanceSpec.scala │ └── scala │ └── collection │ └── mutable │ └── PriorityMultiBiSetSpec.scala └── version.properties /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Reviewers for Dependabot PRs 2 | build.gradle @sebastian-peter @danielfeismann @staudtMarius 3 | 4 | # Reviewers for CI/CD related PRs 5 | .github/workflows/ @sebastian-peter @PhilippSchmelter 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gradle 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | target-branch: dev 10 | ignore: 11 | - dependency-name: org.scalatest:scalatest_2.13 12 | versions: 13 | - 3.3.0-SNAP+ 14 | - dependency-name: org.scalatestplus:mockito-3-4_2.13 15 | versions: 16 | - 3.3.0.0-SNAP+ 17 | 18 | - package-ecosystem: pip 19 | directory: "/docs/readthedocs" 20 | schedule: 21 | interval: daily 22 | time: "04:00" 23 | open-pull-requests-limit: 8 24 | target-branch: dev 25 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ie3-institute/simona' 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@d7267f607e9d3fb96fc2fbe83e0af444713e90b7 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | 19 | - name: Check Snapshot 20 | if: contains(steps.metadata.outputs.new-version, 'snap') 21 | run: | 22 | echo "::error::Snapshot versions are not allowed – workflow stopped." 23 | exit 1 24 | 25 | - name: Approve the PR 26 | if: steps.metadata.outputs.update-type == 'version-update:semver-patch' 27 | run: gh pr review --approve "$PR_URL" 28 | env: 29 | PR_URL: ${{github.event.pull_request.html_url}} 30 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 31 | 32 | - name: Enable auto-merge for Dependabot PRs 33 | if: steps.metadata.outputs.update-type == 'version-update:semver-patch' 34 | run: gh pr merge --auto --merge "$PR_URL" 35 | env: 36 | PR_URL: ${{ github.event.pull_request.html_url }} 37 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | 14 | # Configure python 15 | python: 16 | install: 17 | - requirements: docs/readthedocs/requirements.txt 18 | 19 | # Build documentation in the docs/ directory with Sphinx 20 | sphinx: 21 | configuration: docs/readthedocs/conf.py 22 | fail_on_warning: true 23 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = 3.8.1 2 | runner.dialect = scala3 3 | 4 | rewrite.scala3.convertToNewSyntax = false 5 | rewrite.scala3.removeOptionalBraces = no 6 | 7 | rewrite.trailingCommas.style = multiple 8 | 9 | rewrite.rules = [] -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: "SIMONA - A Discrete-Event Distribution Grid Simulation Environment" 3 | message: "If you use this software, please cite it as below." 4 | type: software 5 | authors: 6 | - family-names: Hiry 7 | given-names: Johannes 8 | orcid: https://orcid.org/0000-0002-1447-0607 9 | - family-names: Kittl 10 | given-names: Chris 11 | orcid: https://orcid.org/0000-0002-1187-0568 12 | - family-names: Sen Sarma 13 | given-names: Debopama 14 | orcid: https://orcid.org/0000-0003-3311-3020 15 | - family-names: Oberließen 16 | given-names: Thomas 17 | orcid: https://orcid.org/0000-0001-5805-5408 18 | - family-names: Peter 19 | given-names: Sebastian 20 | orcid: https://orcid.org/0000-0001-6311-6113 21 | - family-names: Feismann 22 | given-names: Daniel 23 | orcid: https://orcid.org/0000-0002-3531-9025 24 | - family-names: Bao 25 | given-names: Johannes 26 | orcid: https://orcid.org/0009-0008-3641-6469 27 | - family-names: Hohmann 28 | given-names: Julian 29 | - family-names: Staudt 30 | given-names: Marius 31 | repository-code: https://github.com/ie3-institute/simona 32 | url: https://simona.ie3.e-technik.tu-dortmund.de 33 | repository-artifact: https://central.sonatype.com/artifact/com.github.ie3-institute/simona 34 | keywords: 35 | - agent-based 36 | - discrete-event simulation 37 | - powerflow 38 | - electricity distribution grid 39 | license: BSD-3-Clause 40 | version: 3.0.0 41 | date-released: 2023-08-07 42 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:17-slim 2 | 3 | # USAGE: 4 | # build with ARG version and if applicable with ARG snapshot suffix 5 | # e.g.: docker build --build-arg version=2.1.0 --build-arg snapshotSuffix=-SNAPSHOT -t simona . 6 | # run by mounting directory 7 | # e.g. docker run -v `realpath input`:/input --rm simona 8 | # note: this does not work for windows so you have to enter the absolute path manually and escape the \'s 9 | 10 | ARG version 11 | # snapshot suffix for jar files is "-SNAPSHOT" 12 | ARG snapshotSuffix="" 13 | 14 | ENV jarFile="simona-${version}${snapshotSuffix}-all.jar" 15 | ENV config="" 16 | 17 | RUN mkdir exec \ 18 | && mkdir input 19 | 20 | # copy simona fat jar into container 21 | COPY build/libs/$jarFile /exec/ 22 | # inputData is mounted upon running 23 | VOLUME /input 24 | 25 | ENTRYPOINT ["sh", "-c", "java -jar exec/${jarFile} --config=${config}"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Institute of Energy Systems, Energy Efficiency and Energy Economics - ie3 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /docs/logo/logo_tightcrop_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/logo/logo_tightcrop_transparent.png -------------------------------------------------------------------------------- /docs/readthedocs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= python3 -msphinx 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/bm_model/bm_behaviour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/bm_model/bm_behaviour.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/bm_model/bm_parameters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/bm_model/bm_parameters.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/bm_model/mc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/bm_model/mc.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/chp_model/ChpModelCalculation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/chp_model/ChpModelCalculation.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/chp_model/ChpModelMathematicalNotations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/chp_model/ChpModelMathematicalNotations.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/chp_model/ModelChpModelCalculationConcept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/chp_model/ModelChpModelCalculationConcept.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/chp_model/chp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/chp_model/chp4.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/pv_model/ModelPv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/pv_model/ModelPv.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/transformer_model/ModelTwt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/transformer_model/ModelTwt.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/transformer_model/tecdoc_tc1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/transformer_model/tecdoc_tc1.jpg -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/wec_model/EnerconE82cpPlot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/wec_model/EnerconE82cpPlot.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/models/wec_model/WecModelCalculation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/models/wec_model/WecModelCalculation.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/uml/InitializationPhase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/uml/InitializationPhase.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/uml/ParticipantTriggeredByItself.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/uml/ParticipantTriggeredByItself.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/uml/ParticipantTriggeredByPrimaryData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/uml/ParticipantTriggeredByPrimaryData.png -------------------------------------------------------------------------------- /docs/readthedocs/_static/figures/uml/ParticipantTriggeredBySecondaryData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/_static/figures/uml/ParticipantTriggeredBySecondaryData.png -------------------------------------------------------------------------------- /docs/readthedocs/howto/weatherDataHowToCopernicusERA5.md: -------------------------------------------------------------------------------- 1 | (weatherDataHowToCopernicusERA5)= 2 | 3 | # How To use Copernicus ERA5 weather data in SIMONA 4 | 5 | To use weather data from the past within SIMONA we recommend to use the dataset [ERA5 hourly data on single levels from 1940 to present](https://cds.climate.copernicus.eu/datasets/reanalysis-era5-single-levels?tab=download) of [Copernicus Climate Data Store](https://cds.climate.copernicus.eu/). 6 | 7 | The following data parameter should be used 8 | 9 | - Wind 10 | - 100m u-component of wind 11 | - 100m v-component of wind 12 | - Radiation 13 | - Total sky direct solar radiation at surface (FDIR) 14 | - Surface solar radiation downwards (SSRD) 15 | - Temperature 16 | - 2m temperature 17 | 18 | Since SIMONAs [PV Model](pv_model) requires direct and diffuse solar radiation, the diffuse solar radiation need to be determined from the ERA5 data. 19 | 20 | ## Pre-Processing solar radiation weather data 21 | 22 | To obtain diffuse solar radiation data from ERA5 weather data, the necessary diffuse solar radiation (FDIFF) at surface can be calculated by 23 | 24 | $$ 25 | FDIFF = SSRD - FDIR 26 | $$ 27 | 28 | *with*\ 29 | **SSRD** = Surface solar radiation downwards\ 30 | **FDIR** = Total sky direct solar radiation at surface 31 | 32 | 33 | **References:** 34 | * {cite:cts}`Radiation_ECMWF` 35 | -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/agent_messages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/agent_messages.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/basic_simona_environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/basic_simona_environment.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/copy-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/copy-path.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/edit-conf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/edit-conf.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/edit-conf2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/edit-conf2.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/jdk-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/jdk-download.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/scala-plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/scala-plugin.png -------------------------------------------------------------------------------- /docs/readthedocs/images/usersguide/scala-sdk-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/docs/readthedocs/images/usersguide/scala-sdk-error.png -------------------------------------------------------------------------------- /docs/readthedocs/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to simona docs 2 | 3 | ```{image} ../logo/logo_tightcrop_transparent.png 4 | :width: 25% 5 | :align: right 6 | :alt: logo of simona 7 | ``` 8 | 9 | Welcome to the documentation of simona - an agent-based discrete-event power system simulation model developed at the 10 | Institute of Energy Systems, Energy Efficiency and Energy Economics at TU Dortmund University, Germany. 11 | 12 | ```{toctree} 13 | --- 14 | maxdepth: 2 15 | --- 16 | about 17 | usersguide 18 | config 19 | models 20 | developersguide 21 | references 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/readthedocs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/readthedocs/models.md: -------------------------------------------------------------------------------- 1 | (models)= 2 | 3 | # Models 4 | 5 | This page gives an overview of the available models in *SIMONA*. 6 | 7 | ## Grid Related Models 8 | 9 | ```{toctree} 10 | --- 11 | maxdepth: 1 12 | --- 13 | models/line_model 14 | models/switch_model 15 | models/two_winding_transformer_model 16 | models/three_winding_transformer_model 17 | models/reference_system 18 | models/thermal_grid_model 19 | models/thermal_house_model 20 | models/voltage_limits 21 | ``` 22 | 23 | ## System Participant Related Models 24 | 25 | ```{toctree} 26 | --- 27 | maxdepth: 1 28 | --- 29 | models/bm_model 30 | models/chp_model 31 | models/cts_model 32 | models/evcs_model 33 | models/hp_model 34 | models/load_model 35 | models/pv_model 36 | models/wec_model 37 | models/em 38 | ``` 39 | 40 | ## Measurement and Control 41 | ```{toctree} 42 | --- 43 | maxdepth: 1 44 | --- 45 | models/measurement_control 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/readthedocs/models/evcs_model.md: -------------------------------------------------------------------------------- 1 | (evcs_model)= 2 | # Electric Vehicle Charging Station Model 3 | 4 | The currently connected EvModels are saved within the state data of EvcsAgent and passed to EvcsModel with each trigger. The model then calculates the active load of the charging station. 5 | 6 | ## Attributes, Units and Remarks 7 | 8 | Please refer to {doc}`PowerSystemDataModel - Evcs Model ` for Attributes and Units used in this Model. 9 | 10 | ## Calculation 11 | 12 | 13 | The following arguments need to be provided for power calculation: 14 | 15 | 16 | | Argument | Unit | Remarks | 17 | |------------------|---------|-----------------------------------------------| 18 | | dataFrameLength | -- | duration in ticks until next EV movement data | 19 | | currentEVs | -- | set of EVs connected to the CS at this moment | 20 | -------------------------------------------------------------------------------- /docs/readthedocs/models/hp_model.md: -------------------------------------------------------------------------------- 1 | (hp_model)= 2 | 3 | # Heat Pump Model 4 | 5 | This page documents the functionality of the Heat Pump Model (HP model) available in SIMONA. This model is part of the SIMONA simulation framework and represented by an agent. As it is a cross-sector agent (heat/electricity) the usage of a house-heat-model is mandatory. In the following, the HP unit model is described. 6 | 7 | ## Assumptions 8 | 9 | The HP unit is able to operate either at full load or not at all. Uncovered heat demand of former time-steps is not considered in the following steps, as the HP unit does not possess a memory. 10 | 11 | ## Parameters 12 | 13 | ## Attributes, Units and Remarks 14 | 15 | Please refer to {doc}`PowerSystemDataModel - HP Model ` for Attributes and Units used in this Model. 16 | 17 | ## Implemented Behaviour 18 | 19 | - Agent Objectives 20 | The objective of the HP agent is to cover the given heat demand of its thermal bus in each time-step. 21 | 22 | The implemented behaviour is shown in the program sequence plan below. In general, the unit will turn on, if the thermal bus is demanding heat. During operation, the HP unit operates at full utilization. 23 | -------------------------------------------------------------------------------- /docs/readthedocs/models/line_model.md: -------------------------------------------------------------------------------- 1 | (line_model)= 2 | # Line Model 3 | 4 | Lines are modelled according to {doc}`PowerSystemDataModel ` 5 | 6 | ## Attributes, Units and Remarks 7 | 8 | Please refer to {doc}`PowerSystemDataModel - Line Model ` for Attributes and Units used in this Model. 9 | -------------------------------------------------------------------------------- /docs/readthedocs/models/measurement_control.md: -------------------------------------------------------------------------------- 1 | (measurement_control)= 2 | 3 | # Transformer Control Groups 4 | 5 | Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer. 6 | -------------------------------------------------------------------------------- /docs/readthedocs/models/reference_system.md: -------------------------------------------------------------------------------- 1 | (reference_system)= 2 | 3 | # Reference System 4 | 5 | The reference system is built up by specifying the included voltage levels. The following table describes typical network levels and the corresponding parameterization. 6 | 7 | ## Default reference system 8 | 9 | ```{list-table} 10 | :widths: auto 11 | :header-rows: 1 12 | 13 | * - Voltage level (id) 14 | - Nominal voltage (vNom) 15 | - Apparent power (sNom) 16 | 17 | * - LV 18 | - 0.4 kV 19 | - 100 kVA 20 | 21 | * - MV 22 | - 10 kV 23 | - 40 MVA 24 | 25 | * - MV 26 | - 20 kV 27 | - 60 MVA 28 | 29 | * - MV 30 | - 30 kV 31 | - 150 MVA 32 | 33 | * - HV 34 | - 110 kV 35 | - 600 MVA 36 | 37 | * - EHV 38 | - 220 kV 39 | - 800 MVA 40 | 41 | * - EHV 42 | - 380 kV 43 | - 1000 MVA 44 | ``` 45 | 46 | 47 | ## Configuration of the reference system 48 | 49 | To configure the reference system, the voltage levels listed in the table above must be selected and integrated into the reference system with the nominal apparent power (sNom), the nominal voltage (vNom), and the individual voltage level configuration (voltLvls) according to the example below. Each voltage level is composed of the identifier and the nominal voltage. 50 | 51 | ``` 52 | simona.gridConfig.refSystems = [ 53 | {sNom = "100 kVA", vNom = "0.4 kV", voltLvls = [{id = "LV", vNom = "0.4 kV"}]}, 54 | {sNom = "60 MVA", vNom = "20 kV", voltLvls = [{id = "MV", vNom = "20 kV"}]}, 55 | {sNom = "600 MVA", vNom = "110 kV", voltLvls = [{id = "HV", vNom = "110 kV"}]}, 56 | {sNom = "1000 MVA", vNom = "380 kV", voltLvls = [{id = "EHV", vNom = "380 kV"}]} 57 | ] 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/readthedocs/models/switch_model.md: -------------------------------------------------------------------------------- 1 | (switch_model)= 2 | # Switch Model 3 | 4 | Switches are modelled according to {doc}`PowerSystemDataModel ` 5 | 6 | ## Attributes, Units and Remarks 7 | 8 | Please refer to {doc}`PowerSystemDataModel - Switch Model ` for Attributes and Units used in this Model. 9 | -------------------------------------------------------------------------------- /docs/readthedocs/models/thermal_grid_model.md: -------------------------------------------------------------------------------- 1 | (thermal_grid_model)= 2 | # Thermal Grid Model 3 | 4 | The Thermal Grid Model introduces a coupling point to thermal system, equivalent to an electrical node. It can be used to interconnect thermal units to a thermal heat network. 5 | 6 | A Thermal Grid Model consists of a {ref}`thermal_house_model` and / or a {ref}`cts_model` which are supplied by a thermal source like a {ref}`hp_model`. 7 | 8 | ## Attributes, Units and Remarks 9 | 10 | Please refer to {doc}`PowerSystemDataModel - Thermal Bus ` for Attributes and Units used in this Model. 11 | -------------------------------------------------------------------------------- /docs/readthedocs/models/voltage_limits.md: -------------------------------------------------------------------------------- 1 | (voltage_limits)= 2 | 3 | # Voltage Limits 4 | 5 | The voltage limits are built up by specifying the included voltage levels. The following table describes typical network 6 | levels and their parameterization. They are primarily used for the optional congestion management. 7 | 8 | ## Default voltage limits 9 | 10 | ```{list-table} 11 | :widths: auto 12 | :header-rows: 1 13 | 14 | * - Voltage level (id) 15 | - Minimal voltage (vMin) 16 | - Maximal voltage (vMax) 17 | 18 | * - LV 19 | - 0.9 p.u. 20 | - 1.1 p.u. 21 | 22 | * - MV (10 kV) 23 | - 0.9 p.u. 24 | - 1.1 p.u. 25 | 26 | * - MV (20 kV) 27 | - 0.9 p.u. 28 | - 1.1 p.u. 29 | 30 | * - MV (30 kV) 31 | - 0.9 p.u. 32 | - 1.1 p.u. 33 | 34 | * - HV 35 | - 0.9 p.u. 36 | - 1.1 p.u. 37 | 38 | * - EHV (220 kV) 39 | - 0.9 p.u. 40 | - 1.118 p.u. 41 | 42 | * - EHV (380 kV) 43 | - 0.9 p.u. 44 | - 1.05 p.u. 45 | ``` 46 | 47 | **References:** 48 | 49 | * {cite:cts}`EN_50160` 50 | * {cite:cts}`EU_2017/1485` 51 | 52 | ## Configuration of the voltage limits 53 | 54 | To configure the voltage limits, the voltage levels listed in the table above must be selected and integrated into the 55 | config. The individual voltage level configuration (voltLvls) according to the example below. Each voltage level consists 56 | of an identifier and the nominal voltage. 57 | 58 | ``` 59 | simona.gridConfig.voltageLimits = [ 60 | {vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Lv", vNom = "0.4 kV"}]}, 61 | {vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Mv", vNom = "20 kV"}]}, 62 | {vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Hv", vNom = "110 kV"}]}, 63 | {vMin = 0.9, vMax = 1.05, voltLvls = [{id = "EHV", vNom = "380 kV"}]}, 64 | ] 65 | ``` 66 | -------------------------------------------------------------------------------- /docs/readthedocs/protocols.md: -------------------------------------------------------------------------------- 1 | 2 | # Initialization phase 3 | 4 | ![Initialization Phase Sequence Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/ie3-institute/simona/dev/docs/uml/protocol/InitializationPhase.puml) 5 | 6 | # Triggering of participant agents 7 | 8 | 9 | ## Participant triggered by primary data 10 | 11 | This activation protocol is used, if the agent receives and is required to playback externally given, precalculated model 12 | results. 13 | 14 | ![Participant triggered by primary data Sequence Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/ie3-institute/simona/dev/docs/uml/protocol/ParticipantTriggeredByPrimaryData.puml) 15 | 16 | ## Participant triggered by secondary data 17 | 18 | This is the usual activation protocol of a participant agent. 19 | The participant agent asks the scheduler to trigger it (the participant agent) in the same tick in order to achieve 20 | timely synchronization within the ready check window. 21 | 22 | ![Participant triggered by secondary data Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/ie3-institute/simona/dev/docs/uml/protocol/ParticipantTriggeredBySecondaryData.puml) 23 | 24 | ## Participant triggered by itself 25 | 26 | This case only occurs, when the participant model itself does not rely on any other data. 27 | This might be the case for a fixed feed in model as well as constant power load models. 28 | 29 | ![Participant triggered by itself Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/ie3-institute/simona/dev/docs/uml/protocol/ParticipantTriggeredByItself.puml) 30 | -------------------------------------------------------------------------------- /docs/readthedocs/references.md: -------------------------------------------------------------------------------- 1 | # Publications and References 2 | 3 | ## SIMONA publications 4 | 5 | The following publications discuss SIMONA and implementation details as well as outcomes where SIMONA have been used: 6 | 7 | ```{bibliography} _static/bibliography/bibAboutSimona.bib 8 | :style: unsrt 9 | :all: 10 | ``` 11 | 12 | ## References 13 | 14 | References of publications SIMONA referred on: 15 | 16 | ```{bibliography} _static/bibliography/bibtexAll.bib 17 | :style: custom 18 | :all: 19 | ``` 20 | -------------------------------------------------------------------------------- /docs/readthedocs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx==8.2.3 2 | sphinx-rtd-theme==3.0.2 3 | sphinxcontrib-plantuml==0.30 4 | myst-parser==4.0.1 5 | markdown-it-py==3.0.0 6 | sphinx-hoverxref==1.4.2 7 | sphinxcontrib-bibtex==2.6.3 8 | -------------------------------------------------------------------------------- /docs/uml/main/em/PrioritizedFlexStrat.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 'https://plantuml.com/activity-diagram-beta 3 | 4 | start 5 | 6 | if () then (excess feed-in) 7 | if (EVCS exists?) then (yes) 8 | :asset = EVCS; 9 | (A) 10 | endif 11 | if (Battery exists?) then (yes) 12 | :asset = Battery; 13 | (A) 14 | endif 15 | if (Heat pump exists?) then (yes) 16 | :asset = Heat pump; 17 | (A) 18 | endif 19 | if (PV exists?) then (yes) 20 | :asset = PV; 21 | (A) 22 | endif 23 | if (WEC exists?) then (yes) 24 | :asset = WEC; 25 | (A) 26 | endif 27 | else (excess load) 28 | if (Battery exists?) then (yes) 29 | :asset = Battery; 30 | (A) 31 | endif 32 | if (EVCS exists?) then (yes) 33 | :asset = EVCS; 34 | (A) 35 | endif 36 | if (Heat pump exists?) then (yes) 37 | :asset = Heat pump; 38 | (A) 39 | endif 40 | endif 41 | 42 | stop 43 | 44 | (A) 45 | if (flexibility demand already satisfied?) then (no) 46 | if (asset offers flexibility) then (yes) 47 | if (flexibility covers demand) then (fully) 48 | :remainingDemand = 0; 49 | else (partially) 50 | :remainingDemand -= flex; 51 | endif 52 | else (no) 53 | endif 54 | else (yes) 55 | endif 56 | 57 | stop 58 | 59 | @enduml 60 | -------------------------------------------------------------------------------- /docs/uml/main/models/pv_model/BehaviourPvModel.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | rectangle "Setup" as s01 3 | rectangle "Receive new time step" as s02 4 | rectangle "Receive weather data" as s03 5 | rectangle "Calculation of sun position" as s04 6 | rectangle "Calculation of direct radiation" as s05 7 | rectangle "Calculation of diffuse radiation" as s06 8 | rectangle "Calculation of reflected radiation" as s07 9 | rectangle "Estimation of correction factors" as s08 10 | rectangle "Calculation of output power P" as s09 11 | rectangle "Calculation of reactive power Q" as s10 12 | rectangle "Return p and Q to node agent" as s11 13 | 14 | s01 -down-> s02 15 | s02 -down-> s03 16 | s03 -down-> s04 17 | s04 -down-> s05 18 | s05 -down-> s06 19 | s06 -down-> s07 20 | s07 -down-> s08 21 | s08 -down-> s09 22 | s09 -down-> s10 23 | s10 -down-> s11 24 | s11 -up-> s02 25 | @enduml 26 | -------------------------------------------------------------------------------- /docs/uml/main/models/thermal/grid/HandleConsumption.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 'https://plantuml.com/activity-diagram-beta 3 | 4 | start 5 | if (house exists?) then (yes) 6 | :Set qDot = 0 and\ncalculate next threshold; 7 | else (no) 8 | endif 9 | if (storage exists?) then (yes) 10 | :Discharge storage and calculate next threshold; 11 | endif 12 | :Return thermal grid state and grid threshold; 13 | stop 14 | 15 | @enduml 16 | -------------------------------------------------------------------------------- /docs/uml/main/models/thermal/grid/HandleInfeed.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 'https://plantuml.com/activity-diagram-beta 3 | 4 | start 5 | if (house exists?) then (no) 6 | :Fill storage; 7 | else if (house below upper temp?) then (yes) 8 | :Heat the house; 9 | else if (storage exists?) then (yes) 10 | :Fill storage; 11 | endif 12 | :Return updated state and reached threshold; 13 | stop 14 | 15 | @enduml 16 | -------------------------------------------------------------------------------- /docs/uml/main/participants/ChpModelCalculation.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | start 3 | :Receive heat demand\nfor a given time interval; 4 | if (Heat demand is zero 5 | and CHP unit off) then (yes) 6 | elseif (Heat demand covered by 7 | storage and CHP unit off) then (yes) 8 | :Take thermal energy\nfrom storage; 9 | elseif (Heat demand covered 10 | and CHP unit on) then (yes) 11 | :Exchange difference with storage; 12 | if (Storage is full) then (yes) 13 | :Turn CHP unit off; 14 | :Set storage level\nto maximum; 15 | else (no) 16 | :Leave CHP unit on; 17 | endif 18 | else (Heat demand 19 | cannot be\n covered) 20 | :Set storage level 21 | to minimum; 22 | endif 23 | :Update time tick; 24 | :Return active power and thermal output energy; 25 | stop 26 | @enduml -------------------------------------------------------------------------------- /docs/uml/main/participants/ChpModelCalculationConcept.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | (*) --> "Receive heat demand for a given time interval" 3 | if "Is heat demand\n greater zero" then 4 | --> [yes] "Check if stored thermal 5 | energy can cover demand" 6 | if "Is demand covered\nby stored thermal energy" then 7 | --> [yes] Check if CHP unit is running 8 | else 9 | --> [no] "Turn on CHP unit" 10 | --> "Check if stored energy plus generated 11 | energy can cover demand" 12 | if "Is demand covered\nby total energy" then 13 | --> [yes] "Add generated thermal 14 | energy to storage" 15 | else 16 | --> [no] "Return active power" 17 | Endif 18 | 19 | Endif 20 | else 21 | --> [no] "Check if CHP unit is running" 22 | if "Is CHP unit\n turned on" then 23 | --> [on] "Add generated thermal 24 | energy to storage" 25 | if "Is storage full" then 26 | --> [yes] "Turn CHP unit off" 27 | --> "Return active power" 28 | else 29 | --> [no] "Return active power" 30 | Endif 31 | else 32 | --> [off] "Return active power" 33 | Endif 34 | Endif 35 | --> (*) 36 | 37 | @enduml -------------------------------------------------------------------------------- /docs/uml/main/participants/HpModelCalculation.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | start 4 | 5 | :Receive local ambient temperature for time step; 6 | 7 | fork 8 | :Calculate temperature deviation between\ninner and ambient temperature; 9 | 10 | :Calculate thermal energy losses\nduring time step; 11 | 12 | fork again 13 | if (inner temperature is higher\nthan upper boundary) then (yes) 14 | :isRunning = false 15 | activePower = 0; 16 | else (no) 17 | if (inner temperature is lower\nthan lower boundary) then (yes) 18 | :isRunning = true 19 | activePower = pRated; 20 | else (no) 21 | if (isRunning = true) then (yes) 22 | :isRunning = true 23 | activePower = pRated; 24 | else (no) 25 | :isRunning = false 26 | activePower = 0; 27 | endif 28 | endif 29 | endif 30 | :Calculate thermal energy gain during time step; 31 | end fork 32 | 33 | :Calculate thermal energy change during time step; 34 | 35 | :Calculate inner temperature change and\nupdate inner temperature for next time step; 36 | 37 | stop 38 | 39 | @enduml -------------------------------------------------------------------------------- /docs/uml/main/participants/WecModelCalculation.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | start 3 | :Initialize **WecModel** with **WecInput** 4 | (extract //rotor area A// and betz curve); 5 | 6 | :Feed in **WecData** with //wind velocity v//, 7 | //temperature// and //pressure// for calculation; 8 | 9 | :Find corresponding //performance coefficient c_p// 10 | in betz curve using //wind velocity v//; 11 | 12 | :Calculate //air density ρ// using current 13 | //temperature// and //air pressure//; 14 | 15 | :Use determined values to calculate the 16 | active power output as follows: 17 | P = 0.5 * ρ * c_p * A * v³ * -1; 18 | 19 | if(Turbine output smaller than\nrated apparent power: 20 | P < sMax * cos(φ)) then (yes) 21 | :Set P = sMax * cos(φ) * -1; 22 | else (no) 23 | endif 24 | :Return value of P; 25 | stop 26 | @enduml -------------------------------------------------------------------------------- /docs/uml/protocol/InitializationPhase.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | SimonaSim -> Listener: create() 3 | SimonaSim -> Scheduler: create() 4 | SimonaSim -> Services: create() 5 | Services -> Scheduler: ! ScheduleActivation(\n\tweatherActorRef, \n\tINIT_SIM_TICK) 6 | SimonaSim -> GridAgents: create() 7 | GridAgents -> Scheduler: ! ScheduleActivation(\n\tgridAgentRef, \n\tINIT_SIM_TICK) 8 | SimonaSim -> Scheduler: ? StartScheduleMessage() 9 | Scheduler -> Services: ! Activation(\n\tINIT_SIM_TICK) 10 | Services --> Scheduler: ! Completion(\n\tweatherActorRef, \n\ttick) 11 | Scheduler -> GridAgents: ! Activation(\n\tINIT_SIM_TICK) 12 | GridAgents -> Scheduler: ! ScheduleActivation(\n\tassetAgentRef, \n\tINIT_SIM_TICK) 13 | GridAgents --> Scheduler: ! Completion(\n\tgridAgentRef,\n\ttick) 14 | Scheduler -> ParticipantAgents: ! Activation(\n\tINIT_SIM_TICK) 15 | ParticipantAgents -> Services: ! RegisterForWeatherMessage(lat, lon) 16 | ParticipantAgents -> Services: ! RegisterFor... 17 | Services --> ParticipantAgents: ! RegistrationResponseMessages 18 | ParticipantAgents --> Scheduler: ! Completion(\n\tassetAgentRef,\n\ttick) 19 | @enduml -------------------------------------------------------------------------------- /docs/uml/protocol/ParticipantTriggeredByItself.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | Scheduler -> ParticipantAgents: ! Activation(\n\tINIT_SIM_TICK) 3 | ParticipantAgents --> Scheduler: ! Completion(\n\tactor, tick) 4 | Scheduler -> ParticipantAgents: ! Activation(\n\ttick) 5 | ParticipantAgents --> Scheduler: ! Completion(\n\tactor, newTick) 6 | @enduml -------------------------------------------------------------------------------- /docs/uml/protocol/ParticipantTriggeredByPrimaryData.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | Scheduler -> PrimaryServiceWorker: ! Activation(\n\tInit_SIM_TICK) 3 | PrimaryServiceWorker -> ParticipantAgents: ! ProvisionMessage 4 | PrimaryServiceWorker --> Scheduler: ! Completion(\n\tactor,None) 5 | Scheduler -> ParticipantAgents: ! Activation(\n\ttick) 6 | ParticipantAgents --> Scheduler: ! Completion(\n\tactor, newTick) 7 | @enduml -------------------------------------------------------------------------------- /docs/uml/protocol/ParticipantTriggeredBySecondaryData.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | Scheduler -> Services: ! Activation(\n\tINIT_SIM_TICK) 3 | Services -> ParticipantAgents: ! ProvideWeatherMessage(\n\ttick,\n\tweatherData,\n\tnextDataTick) 4 | Scheduler -> ParticipantAgents: ! Activation(\n\ttick) 5 | Services -> ParticipantAgents: ! ProvisionMessage 6 | Services -> ParticipantAgents: ! ProvisionMessage 7 | Services --> Scheduler: ! Completion(\n\tactor, None) 8 | ParticipantAgents -> ParticipantAgents: ! StartCalculationTrigger(tick) 9 | ParticipantAgents --> Scheduler: ! Completion(\n\tactor, newTick) 10 | @enduml -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx4096m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | com.github.maiflai.gradle-scalatest.mode = append 20 | -------------------------------------------------------------------------------- /gradle/scripts/branchName.gradle: -------------------------------------------------------------------------------- 1 | tasks.register('checkBranchName') { 2 | doLast { 3 | if (!project.hasProperty('branchName')) { 4 | throw new GradleException("Error: Missing required property 'branchName'.") 5 | } 6 | 7 | def branchName = project.property('branchName') 8 | 9 | def patterns = [ 10 | ~/^(developer|develop|dev)$/, 11 | ~/.*rel\/.*/, 12 | ~/^dependabot\/.*$/, 13 | ~/.*hotfix\/\pL{2}\/#\d+.*/, 14 | ~/.*main/, 15 | ~/^[a-z]{2}\/#[0-9]+(?:-.+)?$/ 16 | ] 17 | 18 | def isValid = patterns.any { pattern -> branchName ==~ pattern } 19 | 20 | if (!isValid) { 21 | throw new GradleException("Error: Check Branch name format (e.g., ps/#1337-FeatureName). Current branch name is $branchName.") 22 | } 23 | 24 | println "Branch name is $branchName" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /gradle/scripts/checkJavaVersion.gradle: -------------------------------------------------------------------------------- 1 | // Enforces the correct Java version, as some parts of the project may malfunction under a wrong version 2 | // If this task fails, try changing your JAVA_HOME to the required version 3 | tasks.register("checkJavaVersion") { 4 | group = 'Verification' 5 | description = 'Enforces correct Java version' 6 | 7 | doLast { 8 | def foundVersion = JavaVersion.current() 9 | if (foundVersion != javaVersion) 10 | throw new IllegalStateException("Wrong Java version: required is " 11 | + javaVersion + ", but found " + foundVersion) 12 | } 13 | } 14 | compileJava.dependsOn(checkJavaVersion) 15 | -------------------------------------------------------------------------------- /gradle/scripts/documentation.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Additional tasks, that are defined by default: 3 | * - sphinx -> Generate HTML output of *.rst files in /docs/readthedocs 4 | */ 5 | 6 | /** 7 | * Configuring the sphinx plugin 8 | */ 9 | sphinx { 10 | description = 'Generate high level HTML documentation output.' 11 | group = 'Documentation' 12 | 13 | sourceDirectory = "${project.projectDir}/docs/readthedocs" 14 | outputDirectory = (project.hasProperty('sphinxOutput')) ? project.getProperty('sphinxOutput') : "${project.rootDir}/build/docs/readthedocs" 15 | } 16 | 17 | /** 18 | * Task to generate the JavaDoc 19 | */ 20 | tasks.javadoc { 21 | description = 'Generates java API doc at the correct place.' 22 | group = 'Documentation' 23 | 24 | source = sourceSets.main.allJava 25 | destinationDir = file("${project.projectDir}/docs/javadoc") 26 | classpath = project.sourceSets.main.compileClasspath 27 | } 28 | 29 | /** 30 | * Task to generate the ScalaDoc 31 | */ 32 | tasks.scaladoc { 33 | description = 'Generates scala API doc at the correct place.' 34 | group = 'Documentation' 35 | 36 | source = sourceSets.main.allSource 37 | destinationDir = file("${project.projectDir}/docs/scaladoc") 38 | classpath = project.sourceSets.main.compileClasspath 39 | 40 | // Exclude SimonaConfig because implicits used by pureconfig's 41 | // ConfigSource.load and ConfigWriter.apply lead to failure of scaladoc 42 | exclude("edu/ie3/simona/config/SimonaConfig.scala") 43 | } 44 | -------------------------------------------------------------------------------- /gradle/scripts/scoverage.gradle: -------------------------------------------------------------------------------- 1 | // scala code coverage gradle plugin 2 | // see https://github.com/scoverage/gradle-scoverage#configuration and 3 | // https://github.com/scoverage/gradle-scoverage/issues/109 for details 4 | 5 | scoverage { 6 | scoverageVersion = "2.3.0" 7 | scoverageScalaVersion //= scalaBinaryVersion 8 | coverageOutputHTML = false 9 | coverageOutputXML = true 10 | coverageOutputCobertura = false 11 | minimumRate = 0.5 // minimum code coverage 12 | coverageDebug = false 13 | } 14 | -------------------------------------------------------------------------------- /gradle/scripts/semVer.gradle: -------------------------------------------------------------------------------- 1 | // tasks for semantic versioning using semver-gradle https://github.com/ethauvin/semver-gradle 2 | 3 | tasks.register('currentVersion') { 4 | doFirst { 5 | println semver.semver 6 | } 7 | } 8 | 9 | tasks.register('devVersion') { 10 | doFirst { 11 | println "${semver.major}.${semver.minor}-SNAPSHOT" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /gradle/scripts/sonarqube.gradle: -------------------------------------------------------------------------------- 1 | sonarqube { 2 | properties { 3 | // general stuff 4 | property 'sonar.projectName', 'simona' // project name 5 | property 'sonar.projectKey', 'edu.ie3:simona' 6 | property 'sonar.verbose', 'true' // verbose mode 7 | property 'sonar.sourceEncoding', 'UTF-8' // encoding 8 | property 'sonar.sources', [ 9 | 'src/main/resources', 10 | 'src/main/scala'] // src dirs 11 | property "sonar.tests", [ 12 | 'src/test/resources', 13 | 'src/test/scala'] // test src dirs 14 | // reports stuff (for all languages) 15 | property 'sonar.junit.reportPaths', [ 16 | 'build/test-results/test'] // Comma-delimited list of paths to Surefire XML-format reports. 17 | // unit tests reports dirs 18 | // scapegoat report dir 19 | property "sonar.scala.scapegoat.reportPaths", [ 20 | "build/reports/scapegoat/src/scapegoat-scalastyle.xml", 21 | "build/reports/scapegoat/testsrc/scapegoat-scalastyle.xml"] // Comma-delimited list of paths to Scapegoat reports in the Scalastyle format 22 | // scala specific stuff 23 | property 'sonar.scala.coverage.reportPaths', 'build/reports/scoverageTest/scoverage.xml' 24 | } 25 | } 26 | 27 | // sonarqube task dependencies 28 | tasks.named("sonarqube") { 29 | dependsOn(tasks.named("test")) 30 | dependsOn(tasks.named("reportScoverage")) 31 | dependsOn(tasks.named("checkScoverage")) 32 | } 33 | -------------------------------------------------------------------------------- /gradle/scripts/spotless.gradle: -------------------------------------------------------------------------------- 1 | // spotless is a code formatter 2 | 3 | spotless { 4 | def ie3LicHead = '/*\n' + 5 | ' * © $YEAR. TU Dortmund University,\n' + 6 | ' * Institute of Energy Systems, Energy Efficiency and Energy Economics,\n' + 7 | ' * Research group Distribution grid planning and operation\n' + 8 | ' */\n\n' 9 | 10 | //sets a license header, removes unused imports and formats conforming to the google java format 11 | java { 12 | removeUnusedImports() // removes any unused imports 13 | googleJavaFormat() 14 | licenseHeader(ie3LicHead) 15 | } 16 | 17 | /* cf. https://github.com/diffplug/spotless/tree/master/plugin-gradle */ 18 | groovyGradle { 19 | // same as groovy, but for .gradle (defaults to '*.gradle') 20 | target('*.gradle', 'gradle/scripts/*.gradle') 21 | greclipse() 22 | leadingTabsToSpaces(2) 23 | } 24 | 25 | //sets a license header, removes unused imports and formats conforming to the scala fmt formatter 26 | scala { 27 | scalafmt().configFile(".scalafmt.conf") 28 | licenseHeader(ie3LicHead, "package.*\\n") 29 | } 30 | 31 | // removes unnecessary whitespace, indents with tabs and ends on new line for gradle, md and gitignore files and config-XMLs 32 | format ('misc') { 33 | target('**/.gitignore', 'configs/**') 34 | trimTrailingWhitespace() 35 | leadingSpacesToTabs() 36 | endWithNewline() 37 | } 38 | 39 | /* Formats markdown files, just like the other misc files, but without trimming trailing white spaces (nested 40 | * enumerations) */ 41 | format('md') { 42 | target('**/*.md') 43 | leadingTabsToSpaces(2) 44 | endWithNewline() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gradle/scripts/tests.gradle: -------------------------------------------------------------------------------- 1 | tasks.named("test", Test) { 2 | useJUnitPlatform { 3 | includeEngines("scalatest") 4 | } 5 | 6 | testLogging { 7 | events("skipped", "failed") 8 | exceptionFormat = "full" 9 | } 10 | } 11 | 12 | // test task performance improvements, see -> https://docs.gradle.org/current/userguide/performance.html 13 | tasks.withType(Test).configureEach { 14 | // No parallel execution in order to avoid problems with insufficient computation resources/timeouts. 15 | // Sequential execution might be even faster, as some limited tests have shown. 16 | maxParallelForks = 1 17 | forkEvery = 100 18 | } 19 | 20 | tasks.withType(JavaCompile).configureEach { 21 | options.fork = true 22 | options.incremental = true 23 | } 24 | 25 | tasks.withType(ScalaCompile).configureEach { 26 | options.fork = true 27 | options.incremental = true 28 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /greclipse.properties: -------------------------------------------------------------------------------- 1 | # Disable formatting errors 2 | ignoreFormatterProblems=true 3 | 4 | -------------------------------------------------------------------------------- /input/samples/common/pekko.conf: -------------------------------------------------------------------------------- 1 | pekko { 2 | 3 | loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger"] 4 | # Options: OFF, ERROR, WARNING, INFO, DEBUG 5 | loglevel = "debug" 6 | logging-filter = "org.apache.pekko.event.slf4j.Slf4jLoggingFilter" 7 | 8 | actor { 9 | 10 | // pekko supervision strategy for failure handling 11 | // https://pekko.apache.org/docs/pekko/current/typed/fault-tolerance.html 12 | // and https://pekko.apache.org/docs/pekko/current/general/supervision.html#user-guardian 13 | guardian-supervisor-strategy = "org.apache.pekko.actor.StoppingSupervisorStrategy" 14 | 15 | } 16 | 17 | # For the sample, just bind to loopback and do not allow access from the network 18 | # the port is overridden by the logic in main class 19 | remote.artery { 20 | enabled = on 21 | transport = tcp 22 | canonical.port = 2551 23 | canonical.hostname = 127.0.0.1 24 | } 25 | 26 | 27 | coordinated-shutdown { 28 | phases { 29 | actor-system-terminate { 30 | timeout = 500 s // increased to allow file operations to terminate! 31 | depends-on = [before-actor-system-terminate] 32 | } 33 | } 34 | 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/bm_input.csv: -------------------------------------------------------------------------------- 1 | uuid,cost_controlled,feed_in_tariff,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type 2 | a3b7576b-cac7-4350-90ff-06316cdca192,true,51.0,BM_Test,true,f5839ade-5968-4879-a824-90b5fb3552cd,,,,"cosPhiFixed:{(0.0,1.0)}",2fdca5f1-c11b-4169-a695-4c98f0e0a84a 3 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/bm_type_input.csv: -------------------------------------------------------------------------------- 1 | uuid,active_power_gradient,capex,cos_phi_rated,eta_conv,id,opex,s_rated 2 | 2fdca5f1-c11b-4169-a695-4c98f0e0a84a,5.0,0.0,1.0,1.0,typ_01,0.05,190.0 3 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/evcs_input.csv: -------------------------------------------------------------------------------- 1 | uuid,charging_points,cos_phi_rated,id,location_type,node,operates_from,operates_until,operator,q_characteristics,type,v_2g_support 2 | 06a14909-366e-4e94-a593-1016e1455b30,4,0.9,test_evcs_1,HOME,5f1c776c-6935-40f7-ba9e-60646e08992b,,,,"cosPhiFixed:{(0.0,1.0)}",ChargingStationType1,true 3 | 104acdaa-5dc5-4197-aed2-2fddb3c4f237,4,0.9,test_evcs_2,HOME,ed4697fd-016c-40c2-a66b-e793878dadea,,,,"cosPhiFixed:{(0.0,1.0)}",ChargingStationType1,true 4 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/fixed_feed_in_input.csv: -------------------------------------------------------------------------------- 1 | uuid,cos_phi_rated,id,node,operates_from,operates_until,operator,q_characteristics,s_rated 2 | 9abe950d-362e-4efe-b686-500f84d8f368,0.9,test_feed_in,5f1c776c-6935-40f7-ba9e-60646e08992b,,,,"cosPhiFixed:{(0.0,0.95)}",200.0 3 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/its_pq_8c04e94e-76b0-4369-a55c-f5e1117fb83e.csv: -------------------------------------------------------------------------------- 1 | "p","q","time" 2 | 3.999998968803,0.0,2011-01-01T00:00:00Z 3 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/storage_type_input.csv: -------------------------------------------------------------------------------- 1 | uuid,active_power_gradient,capex,cos_phi_rated,dod,e_storage,eta,id,life_cycle,life_time,opex,p_max,s_rated 2 | 95d4c980-d9e1-4813-9f2a-b0942488a570,1.0,0.0,0.96,8.0,16.0,93.0,Typ_1,5000,5000.0,0.65,4.0,4.166666666666667 3 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/time_series_mapping.csv: -------------------------------------------------------------------------------- 1 | asset,time_series 2 | 4642d648-b0dd-4597-a3bd-2cc1fce74f27,8c04e94e-76b0-4369-a55c-f5e1117fb83e -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/transformer_2_w_input.csv: -------------------------------------------------------------------------------- 1 | uuid,auto_tap,id,node_a,node_b,operates_from,operates_until,operator,parallel_devices,tap_pos,type 2 | aa5d6bf2-2a88-4cac-9e1f-2a5c19dd2c18,false,TRA_MS4_06-NS_NET146_ONS,fa6d5184-b205-4b1b-839f-7b21ac956c29,3da4fd3d-ac5e-409d-91fa-36516673cf57,,,,1,10,49cfe484-0183-4a23-a922-d72909dba673 3 | bfa702b1-d4d4-44ff-8c3d-a79c2418b5d3,true,S1_MS-Trafo,00d03670-7833-47ee-ad52-04d18d1c64fd,f5839ade-5968-4879-a824-90b5fb3552cd,,,,1,0,1214c366-826e-4aeb-88f5-af8f40acaa04 4 | 1132dbf4-e8a1-44ae-8415-f42d4497aa1d,true,S3_MS-Trafo,33f29587-f63e-45b7-960b-037bda37a3cb,bb59ca46-1f2e-41c9-9723-90b306f043cd,,,,1,0,cf7b1102-8dbd-4da2-a469-90800b3394b6 5 | 2cbbd48e-e6d8-40b4-80cc-010157dfbf3e,false,TRA_MS1_06-NS_NET116,b22c9299-5fb4-46a7-b566-fc17e0d51d60,31a2b9bf-e785-4475-aa44-1c34646e8c79,,,,1,10,4984f493-d6e5-4201-a040-c10722b30362 6 | 18d6ef15-962a-480d-a96a-9ba19ba4b3b3,false,TRA_MS2_06-NS_NET126_ONS,df97c0d1-379b-417a-a473-8e7fe37da99d,2d4beb13-8e6c-46de-9b1c-409c7ca7573a,,,,1,10,f88989c7-9812-4b3e-9bc0-3df29f1e5ae1 7 | e62b6f82-9a37-49e6-af51-93008df6ea53,true,S2_MS-Trafo,dfae9806-9b44-4995-ba27-d66d8e4a43e0,1a8ba1a5-3cee-4791-b21b-f17b08526873,,,,1,0,5901c24c-0c64-4be7-82df-21d4335abdb7 8 | 253a0e3a-c7e0-415e-bdbd-5152aa8f9e27,true,S4_MS-Trafo,401f37f8-6f2c-4564-bc78-6736cb9cbf8d,77fc154f-f41c-4e75-bbb1-b7fca68b2f4e,,,,1,0,14b1798a-6903-49d6-8578-ad2a7d399341 9 | d2a3736d-d10b-4f38-88cf-871df43e3665,true,HöS-Trafo_S1,34cd8ee0-e607-4c47-89a7-121c3e32768a,00d03670-7833-47ee-ad52-04d18d1c64fd,,,,1,0,97735722-05cc-4ca8-8a8d-c08ac3ded19a 10 | 4ac7f0bd-2ea9-4510-9e71-0da40886d9d3,false,TRA_MS3_06-NS_NET136,39dbc5ed-d874-48a8-9128-e970436a94b4,d29f66a1-dee9-4e3e-9f41-c4bc8d375bbe,,,,1,10,a7a3d9b8-da90-4670-b865-4a527df542bd 11 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/transformer_2_w_type_input.csv: -------------------------------------------------------------------------------- 1 | uuid,b_m,d_phi,d_v,g_m,id,r_sc,s_rated,tap_max,tap_min,tap_neutr,tap_side,v_rated_a,v_rated_b,x_sc 2 | cf7b1102-8dbd-4da2-a469-90800b3394b6,0.0,0.0,1.5,0.0,HS-MS_1,45.375,20000.0,10,-10,0,false,110.0,20.0,102.759 3 | 49cfe484-0183-4a23-a922-d72909dba673,0.0,0.0,0.5,0.0,MS-NS_2,25.0,400.0,10,-10,0,false,20.0,0.4,31.225 4 | 4984f493-d6e5-4201-a040-c10722b30362,0.0,0.0,0.5,0.0,MS-NS_1,10.078,630.0,10,-10,0,false,20.0,0.4,23.312 5 | 97735722-05cc-4ca8-8a8d-c08ac3ded19a,-1.27,0.0,1.5,555.5,HöS-HS_1,5.415,200000.0,5,-5,0,false,380.0,110.0,108.165 6 | 1214c366-826e-4aeb-88f5-af8f40acaa04,0.0,0.0,1.5,0.0,HS-MS_1,45.375,20000.0,10,-10,0,false,110.0,20.0,102.759 7 | 14b1798a-6903-49d6-8578-ad2a7d399341,0.0,0.0,1.5,0.0,HS-MS_1,45.375,20000.0,10,-10,0,false,110.0,20.0,102.759 8 | f88989c7-9812-4b3e-9bc0-3df29f1e5ae1,0.0,0.0,0.5,0.0,MS-NS_1,10.078,630.0,10,-10,0,false,20.0,0.4,23.312 9 | 5901c24c-0c64-4be7-82df-21d4335abdb7,0.0,0.0,1.5,0.0,HS-MS_1,45.375,20000.0,10,-10,0,false,110.0,20.0,102.759 10 | a7a3d9b8-da90-4670-b865-4a527df542bd,0.0,0.0,0.5,0.0,MS-NS_1,10.078,630.0,10,-10,0,false,20.0,0.4,23.312 11 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/wec_input.csv: -------------------------------------------------------------------------------- 1 | uuid,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type 2 | d6ad8c73-716a-4244-9ae2-4a3735e492ab,HS_NET1_S2_WEA,false,dfae9806-9b44-4995-ba27-d66d8e4a43e0,,,,"cosPhiFixed:{(0.0,0.9)}",b70374f3-1feb-45af-8011-1304a532d398 3 | f9eaec6e-ce25-42d7-8265-2f8f4679a816,HS_NET1_S4_WEA,false,401f37f8-6f2c-4564-bc78-6736cb9cbf8d,,,,"cosPhiFixed:{(0.0,0.9)}",b70374f3-1feb-45af-8011-1304a532d398 4 | -------------------------------------------------------------------------------- /input/samples/vn_simona/fullGrid/wec_type_input.csv: -------------------------------------------------------------------------------- 1 | uuid,capex,cos_phi_rated,cp_characteristic,eta_conv,hub_height,id,opex,rotor_area,s_rated 2 | b70374f3-1feb-45af-8011-1304a532d398,0.0,0.9,"cP:{(0.0,0.0),(1.0,0.0),(2.0,0.115933516),(3.0,0.286255595),(4.0,0.39610618),(5.0,0.430345211),(6.0,0.45944023),(7.0,0.479507331),(8.0,0.492113623),(9.0,0.500417188),(10.0,0.488466547),(11.0,0.420415054),(12.0,0.354241299),(13.0,0.288470591),(14.0,0.230965702),(15.0,0.18778367),(16.0,0.154728976),(17.0,0.128998552),(18.0,0.108671106),(19.0,0.09239975),(20.0,0.079221236),(21.0,0.068434282),(22.0,0.059520087),(23.0,0.052089249),(24.0,0.045845623),(25.0,0.040561273),(26.0,0.036058824),(27.0,0.032198846),(28.0,0.016618264),(29.0,0.010330976),(30.0,0.006091519),(31.0,0.003331177),(32.0,0.001641637),(33.0,7.05423E-4),(34.0,1.96644E-4),(35.0,0.0),(36.0,0.0),(37.0,0.0),(38.0,0.0),(39.0,0.0),(40.0,0.0),(41.0,0.0),(42.0,0.0),(43.0,0.0),(44.0,0.0),(45.0,0.0),(46.0,0.0),(47.0,0.0),(48.0,0.0),(49.0,0.0),(50.0,0.0)}",100.0,98.0,EnerconE-82,0.0,5281.02,2222.2 3 | -------------------------------------------------------------------------------- /scripts/branch_type.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | if [ -z "${BRANCH_NAME:-}" ]; then 5 | echo "Error: BRANCH_NAME variable is not set." 6 | exit 1 7 | fi 8 | 9 | 10 | pattern_dev='^(developer|develop|dev)$' 11 | pattern_release='.*rel/.*' 12 | pattern_dependabot='^dependabot/.*' 13 | pattern_hotfix='.*hotfix/.*' 14 | pattern_main='.*main' 15 | pattern_feature='^[a-z]{2}/#[0-9]+(-.+)?$' 16 | 17 | BRANCH_TYPE="unknown" 18 | 19 | if [[ "$BRANCH_NAME" =~ $pattern_dev ]]; then 20 | BRANCH_TYPE="dev" 21 | elif [[ "$BRANCH_NAME" =~ $pattern_release ]]; then 22 | BRANCH_TYPE="release" 23 | elif [[ "$BRANCH_NAME" =~ $pattern_dependabot ]]; then 24 | BRANCH_TYPE="dependabot" 25 | elif [[ "$BRANCH_NAME" =~ $pattern_hotfix ]]; then 26 | BRANCH_TYPE="hotfix" 27 | elif [[ "$BRANCH_NAME" =~ $pattern_main ]]; then 28 | BRANCH_TYPE="main" 29 | elif [[ "$BRANCH_NAME" =~ $pattern_feature ]]; then 30 | BRANCH_TYPE="feature" 31 | else 32 | echo "Error:'$BRANCH_NAME' does not match any pattern." 33 | exit 1 34 | fi 35 | 36 | echo "=========================" 37 | echo "Branch type: $BRANCH_TYPE" 38 | echo "BRANCH_TYPE=$BRANCH_TYPE" >> "$GITHUB_ENV" 39 | echo "=========================" 40 | -------------------------------------------------------------------------------- /scripts/get_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | cd "$(dirname "$0")/.." 5 | 6 | REPO_URL=$(git config --get remote.origin.url) 7 | export REPO_URL 8 | echo "REPO_URL=$REPO_URL" >> $GITHUB_ENV 9 | 10 | echo "Fetching current version of PR..." 11 | PR_VERSION=$(./gradlew -q currentVersion) 12 | echo "PR_VERSION=$PR_VERSION" 13 | echo "export PR_VERSION=$PR_VERSION" >> versions.env 14 | echo "PR_VERSION=$PR_VERSION" >> "$GITHUB_ENV" 15 | 16 | get_branch_version() { 17 | local BRANCH_NAME=$1 18 | local DIR_NAME="${BRANCH_NAME}-branch" 19 | 20 | git clone --depth 1 --branch "$BRANCH_NAME" "$REPO_URL" "$DIR_NAME" 21 | cd "$DIR_NAME" 22 | 23 | echo "Fetching version from $BRANCH_NAME branch..." 24 | BRANCH_VERSION=$(./gradlew -q currentVersion) 25 | cd .. 26 | 27 | echo "${BRANCH_NAME^^}_VERSION=$BRANCH_VERSION" 28 | echo "export ${BRANCH_NAME^^}_VERSION=$BRANCH_VERSION" >> versions.env 29 | echo "${BRANCH_NAME^^}_VERSION=$BRANCH_VERSION" >> "$GITHUB_ENV" 30 | 31 | rm -rf "$DIR_NAME" 32 | } 33 | 34 | 35 | get_branch_version "dev" 36 | get_branch_version "main" 37 | 38 | echo "Get Versions: OK!" 39 | -------------------------------------------------------------------------------- /scripts/run-version-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | rm -f versions.env 5 | 6 | scripts/get_versions.sh 7 | 8 | source versions.env 9 | 10 | scripts/version_check.sh 11 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.3/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'simona_public' 11 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/tech.units.indriya.spi.NumberSystem: -------------------------------------------------------------------------------- 1 | edu.ie3.util.scala.quantities.ScalaNumberSystem -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/actor/ActorUtil.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.actor 8 | 9 | import org.apache.pekko.actor.typed.Behavior 10 | import org.apache.pekko.actor.typed.scaladsl.{ActorContext, Behaviors} 11 | 12 | object ActorUtil { 13 | def stopOnError[M]( 14 | ctx: ActorContext[M], 15 | msg: String, 16 | ): Behavior[M] = { 17 | ctx.log.error(s"$msg. Stopping.") 18 | Behaviors.stopped 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent 8 | 9 | import edu.ie3.simona.event.RuntimeEvent 10 | import edu.ie3.simona.ontology.messages.SchedulerMessage 11 | import edu.ie3.simona.ontology.messages.services.{ 12 | EvMessage, 13 | LoadProfileMessage, 14 | ServiceMessage, 15 | WeatherMessage, 16 | } 17 | import org.apache.pekko.actor.typed.ActorRef 18 | 19 | /** Container class, that gather together reference to relevant entities, that 20 | * represent the environment in the simulation. 21 | * 22 | * @param scheduler 23 | * Reference to the event handling entity. 24 | * @param runtimeEventListener 25 | * Reference to the runtime event listener. 26 | * @param primaryServiceProxy 27 | * Reference to the primary service proxy. 28 | * @param weather 29 | * Reference to the service, that provides weather information. 30 | * @param loadProfiles 31 | * Reference to the service, that provides load profile information. 32 | * @param evDataService 33 | * Reference to the EV data service, if existing. 34 | */ 35 | final case class EnvironmentRefs( 36 | scheduler: ActorRef[SchedulerMessage], 37 | runtimeEventListener: ActorRef[RuntimeEvent], 38 | primaryServiceProxy: ActorRef[ServiceMessage], 39 | weather: ActorRef[WeatherMessage], 40 | loadProfiles: ActorRef[LoadProfileMessage], 41 | evDataService: Option[ActorRef[EvMessage]], 42 | ) 43 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/em/FlexControlledData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.em 8 | 9 | import edu.ie3.simona.ontology.messages.flex.FlexOptions 10 | import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.{ 11 | FlexRequest, 12 | FlexResponse, 13 | } 14 | import org.apache.pekko.actor.typed.ActorRef 15 | 16 | /** The existence of this data object indicates that the corresponding agent is 17 | * EM-controlled (by [[emAgent]]). 18 | * 19 | * @param emAgent 20 | * The parent EmAgent that is controlling this agent. 21 | * @param flexAdapter 22 | * The flex adapter handling [[FlexRequest]] messages 23 | * @param lastFlexOptions 24 | * Last flex options that have been calculated for this agent. 25 | */ 26 | final case class FlexControlledData( 27 | emAgent: ActorRef[FlexResponse], 28 | flexAdapter: ActorRef[FlexRequest], 29 | lastFlexOptions: Option[FlexOptions] = None, 30 | ) 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/grid/GridEnvironment.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.grid 8 | 9 | import edu.ie3.datamodel.graph.SubGridGate 10 | import edu.ie3.simona.agent.participant.ParticipantAgent 11 | import edu.ie3.simona.model.grid.GridModel 12 | import org.apache.pekko.actor.typed.ActorRef 13 | 14 | import java.util.UUID 15 | 16 | /** Wrapper class containing all information on the grid environment a 17 | * [[GridAgent]] has access to 18 | * 19 | * @param gridModel 20 | * [[GridModel]] with all asset information 21 | * @param subgridGateToActorRef 22 | * a mapping of all [[SubGridGate]] s to their corresponding [[ActorRef]] s 23 | * @param nodeToAssetAgents 24 | * a mapping of all node uuids to a set of asset [[ActorRef]] s at those 25 | * nodes 26 | */ 27 | final case class GridEnvironment( 28 | gridModel: GridModel, 29 | subgridGateToActorRef: Map[SubGridGate, ActorRef[GridAgent.Request]], 30 | nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantAgent.Request]]], 31 | ) 32 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/grid/PowerFlowParams.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.grid 8 | 9 | import scala.concurrent.duration.FiniteDuration 10 | 11 | /** Holds all power flow configuration parameters used in 12 | * [[edu.ie3.simona.agent.grid]] 13 | * 14 | * @param maxSweepPowerDeviation 15 | * the maximum allowed power deviation until convergence in the 16 | * backward-forward-sweep algorithm is reached 17 | * @param epsilon 18 | * Permissible deviation between actual (given) use of the grid (P, Q, |V|) 19 | * and those values determined during iterative solving of the system of 20 | * equations 21 | * @param maxIterations 22 | * Maximum amount of iterations in a [[edu.ie3.powerflow.NewtonRaphsonPF]] 23 | * @param sweepTimeout 24 | * [[org.apache.pekko.pattern.ask]] timeout for a sweep 25 | * @param stopOnFailure 26 | * Whether to stop the GridAgent after a power flow calculation failed 27 | */ 28 | final case class PowerFlowParams( 29 | maxSweepPowerDeviation: Double, 30 | epsilon: Vector[Double], 31 | maxIterations: Int, 32 | sweepTimeout: FiniteDuration, 33 | stopOnFailure: Boolean, 34 | ) 35 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/grid/congestion/CongestionManagementMessages.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.grid.congestion 8 | 9 | import edu.ie3.simona.agent.grid.GridAgent 10 | 11 | /** Messages for the congestion management. 12 | */ 13 | object CongestionManagementMessages { 14 | 15 | /** Message that informs all actors that the current step is started. 16 | */ 17 | final case object StartStep extends GridAgent.InternalRequest 18 | 19 | /** Message that informs all actors that the current step is finished. 20 | */ 21 | final case object FinishStep extends GridAgent.InternalRequest 22 | 23 | /** Message that informs all actors that the next state is the idle state. 24 | */ 25 | final case object GotoIdle extends GridAgent.InternalRequest 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/grid/congestion/CongestionManagementParams.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.grid.congestion 8 | 9 | import scala.concurrent.duration.FiniteDuration 10 | 11 | /** Holds all congestion management configuration parameters used in 12 | * [[edu.ie3.simona.agent.grid]]. If the parameter [[detectionEnabled]] is set 13 | * to false, no congestion management is run and all the other parameters are 14 | * ignored 15 | * 16 | * @param detectionEnabled 17 | * defines if the congestion management is active and can be run 18 | * @param timeout 19 | * used for asking other actors 20 | */ 21 | final case class CongestionManagementParams( 22 | detectionEnabled: Boolean, 23 | timeout: FiniteDuration, 24 | ) 25 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/agent/grid/congestion/detection/DetectionMessages.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.agent.grid.congestion.detection 8 | 9 | import edu.ie3.simona.agent.grid.GridAgent 10 | import edu.ie3.simona.agent.grid.GridAgent.{ 11 | InternalReply, 12 | InternalReplyWithSender, 13 | InternalRequest, 14 | } 15 | import edu.ie3.simona.agent.grid.congestion.Congestions 16 | import org.apache.pekko.actor.typed.ActorRef 17 | 18 | object DetectionMessages { 19 | 20 | /** Request for congestion the inferior grid. 21 | * @param sender 22 | * that is asking 23 | */ 24 | final case class CongestionCheckRequest( 25 | sender: ActorRef[GridAgent.Request] 26 | ) extends InternalRequest 27 | 28 | /** Response with congestions from an inferior grid. 29 | * @param sender 30 | * inferior grid ref 31 | * @param value 32 | * congestions in the inferior grid 33 | */ 34 | final case class CongestionResponse( 35 | override val sender: ActorRef[GridAgent.Request], 36 | override val value: Congestions, 37 | ) extends InternalReplyWithSender[Congestions] 38 | 39 | /** Answer with all congestion in all inferior grids. 40 | * @param values 41 | * vector of congestion in inferior grids 42 | */ 43 | final case class ReceivedCongestions( 44 | values: Vector[(ActorRef[GridAgent.Request], Congestions)] 45 | ) extends InternalReply 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/config/ConfigConventions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.config 8 | 9 | import scala.util.matching.Regex 10 | 11 | /** Contains centralized conventions used for config parameters that should be 12 | * used in several places to work with config parameters (e.g. regex'es that 13 | * are used in several places) 14 | */ 15 | object ConfigConventions { 16 | // regex matches 17 | // / 1,2,3,12,5-10,6-10,10-5,10...100,100...1000,10-5 18 | // val gridIdsRegex: Regex = """(\d+-\d+|\d+\.\.\.\d+|^\d{1}$)""".r.unanchored 19 | 20 | val gridIdMinusRange: Regex = """(\d+)-(\d+)""".r.unanchored 21 | val gridIdDotRange: Regex = """(\d+)\.\.\.(\d+)""".r.unanchored 22 | val singleGridId: Regex = """(^\d{1,10}$)""".r.unanchored 23 | 24 | // regex matches 25 | // / 10 kV, 10 kVA, 10 V, 1 V, 1A 26 | val refSystemQuantRegex: Regex = """(\d+\s*\pL{1,4})""".r.unanchored 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/event/Event.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event 8 | 9 | /** Trait that should be mixed into each event in [[edu.ie3.simona.event]] to 10 | * provide easy access to its name 11 | */ 12 | trait Event { 13 | 14 | def id: String = this.getClass.getSimpleName 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/event/listener/DeadLetterListener.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event.listener 8 | 9 | import org.apache.pekko.actor.{Actor, DeadLetter, Props} 10 | import com.typesafe.scalalogging.LazyLogging 11 | 12 | /** Simply reads the message, it receives 13 | */ 14 | final class DeadLetterListener extends Actor with LazyLogging { 15 | override def receive: Receive = { case msg: DeadLetter => 16 | logger.error(s"Received the following message from ${sender()}:\n$msg") 17 | } 18 | } 19 | 20 | object DeadLetterListener { 21 | def props(): Props = Props(new DeadLetterListener) 22 | } 23 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/event/notifier/Notifier.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event.notifier 8 | 9 | import edu.ie3.simona.event.Event 10 | import org.apache.pekko.actor.ActorRef 11 | 12 | trait Notifier { 13 | 14 | def listener: Iterable[ActorRef] 15 | 16 | def notifyListener(event: Event): Unit = { 17 | listener.foreach(listener => listener ! event) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/event/notifier/NotifierConfig.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event.notifier 8 | 9 | /** A case class to configure the behaviour of the Participant w.r.t. its 10 | * implementation of the [[edu.ie3.simona.event.notifier.Notifier]] trait 11 | * 12 | * @param simulationResultInfo 13 | * true, if the participant should inform about results 14 | */ 15 | final case class NotifierConfig( 16 | simulationResultInfo: Boolean, 17 | powerRequestReply: Boolean, 18 | flexResult: Boolean, 19 | ) 20 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/CharacteristicsException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | import edu.ie3.simona.model.system.Characteristic 10 | 11 | /** Exception that should be used whenever an exception occurs in 12 | * [[Characteristic]] 13 | * 14 | * @param message 15 | * specific error message 16 | */ 17 | class CharacteristicsException(message: String) extends Exception(message) { 18 | 19 | def this(message: String, cause: Throwable) = { 20 | this(message) 21 | initCause(cause) 22 | } 23 | 24 | def this(cause: Throwable) = { 25 | this(Option(cause).map(_.toString).orNull, cause) 26 | } 27 | 28 | def this() = { 29 | this(null: String) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/CriticalFailureException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Error that should cause an actor to fail, which might terminate the whole 10 | * simulation 11 | * @param message 12 | * The error message 13 | */ 14 | class CriticalFailureException(message: String) extends Exception(message) { 15 | def this(message: String, cause: Throwable) = { 16 | this(message) 17 | initCause(cause) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/FileHierarchyException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an exception occurs in 10 | * [[edu.ie3.simona.util.ResultFileHierarchy]] 11 | * @param message 12 | * specific error message 13 | */ 14 | class FileHierarchyException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/FileIOException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception to be thrown whenever an agent which is not registered for weather 10 | * service requests for weather data 11 | * @param message 12 | * specific error message 13 | */ 14 | class FileIOException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/FlexException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | class FlexException(message: String) extends Exception(message) { 10 | 11 | def this(message: String, cause: Throwable) = { 12 | this(message) 13 | initCause(cause) 14 | } 15 | 16 | def this(cause: Throwable) = { 17 | this(Option(cause).map(_.toString).orNull, cause) 18 | } 19 | 20 | def this() = { 21 | this(null: String) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/GridInconsistencyException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an exception occurs in 10 | * [[edu.ie3.simona.util.ResultFileHierarchy]] 11 | * @param message 12 | * specific error message 13 | */ 14 | class GridInconsistencyException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/InitializationException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception to be thrown whenever an invalid Initialization Trigger is 10 | * received 11 | * @param message 12 | * spcecific error message 13 | */ 14 | class InitializationException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/InvalidActionRequestException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an invalid action is requested from a 10 | * grid component. 11 | * @param message 12 | * spcecific error message 13 | */ 14 | class InvalidActionRequestException(message: String) 15 | extends Exception(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/InvalidConfigParameterException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be thrown whenever a wrong config parameter or a wrong 10 | * combination of config parameters is provided. 11 | */ 12 | class InvalidConfigParameterException(message: String) 13 | extends Exception(message) { 14 | 15 | def this(message: String, cause: Throwable) = { 16 | this(message) 17 | initCause(cause) 18 | } 19 | 20 | def this(cause: Throwable) = { 21 | this(Option(cause).map(_.toString).orNull, cause) 22 | } 23 | 24 | def this() = { 25 | this(null: String) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/InvalidParameterException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an invalid parameter is passed into a 10 | * grid component. 11 | * @param message 12 | * specific error message 13 | */ 14 | class InvalidParameterException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/ProcessResultEventException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an exception occurs in during the 10 | * processing of an [[edu.ie3.simona.event.ResultEvent]] 11 | */ 12 | class ProcessResultEventException(message: String) extends Exception(message) { 13 | 14 | def this(message: String, cause: Throwable) = { 15 | this(message) 16 | initCause(cause) 17 | } 18 | 19 | def this(cause: Throwable) = { 20 | this(Option(cause).map(_.toString).orNull, cause) 21 | } 22 | 23 | def this() = { 24 | this(null: String) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/QControlException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | import edu.ie3.simona.model.participant.control.QControl 10 | 11 | /** Exception that should be used whenever an exception occurs in [[QControl]] 12 | * 13 | * @param message 14 | * specific error message 15 | */ 16 | class QControlException(message: String) extends Exception(message) { 17 | 18 | def this(message: String, cause: Throwable) = { 19 | this(message) 20 | initCause(cause) 21 | } 22 | 23 | def this(cause: Throwable) = { 24 | this(Option(cause).map(_.toString).orNull, cause) 25 | } 26 | 27 | def this() = { 28 | this(null: String) 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/QuantityException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception to be thrown whenever an operation on [[javax.measure.Quantity]] 10 | * fails 11 | * 12 | * @param message 13 | * specific error message 14 | */ 15 | class QuantityException(message: String) extends RuntimeException(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/SchedulerException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that is thrown whenever something invalid happend in 10 | * [[edu.ie3.simona.scheduler.Scheduler]] 11 | * 12 | * @param message 13 | * specific error message 14 | */ 15 | class SchedulerException(message: String) extends RuntimeException(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/ServiceException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | final case class ServiceException(message: String) extends Exception(message) { 10 | 11 | def this(message: String, cause: Throwable) = { 12 | this(message) 13 | initCause(cause) 14 | } 15 | 16 | def this(cause: Throwable) = { 17 | this(Option(cause).map(_.toString).orNull, cause) 18 | } 19 | 20 | def this() = { 21 | this(null: String) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/SimonaAnalysisException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions 8 | 9 | /** Exception that should be used whenever an exception occurs in 10 | * [[edu.ie3.simona.analysis.SimonaAnalysis]] 11 | * @param message 12 | * specific error message 13 | */ 14 | class SimonaAnalysisException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/ActorNotRegisteredException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception to be thrown whenever an agent which is not registered for weather 10 | * service requests for weather data 11 | * @param message 12 | * specific error message 13 | */ 14 | class ActorNotRegisteredException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/AgentInitializationException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception that should be used whenever inconsistency during initialization 10 | * of any agent is detected. 11 | * 12 | * @param message 13 | * Specific error message 14 | */ 15 | class AgentInitializationException(message: String) extends Exception(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/DBFSAlgorithmException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception that should be used whenever an exception occurs in 10 | * [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] 11 | * @param message 12 | * specific error message 13 | */ 14 | class DBFSAlgorithmException(message: String) extends Exception(message) { 15 | 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/GridAgentInitializationException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception that should be used whenever inconsistency during initialization 10 | * of a [[edu.ie3.simona.agent.grid.GridAgent]] is detected. 11 | * @param message 12 | * Specific error message 13 | */ 14 | class GridAgentInitializationException(message: String) 15 | extends AgentInitializationException(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/InconsistentStateException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** This exception may be used, whenever inconsistent state data leads to 10 | * calculation problems in agents 11 | * 12 | * @param message 13 | * Error message to prompt 14 | */ 15 | class InconsistentStateException(message: String) extends Exception(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/InvalidRequestException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception, that is raised, if somebody request something stupid from an 10 | * agent. 11 | * 12 | * @param message 13 | * Error message 14 | */ 15 | class InvalidRequestException(message: String) extends Exception(message) { 16 | def this(message: String, cause: Throwable) = { 17 | this(message) 18 | initCause(cause) 19 | } 20 | 21 | def this(cause: Throwable) = { 22 | this(Option(cause).map(_.toString).orNull, cause) 23 | } 24 | 25 | def this() = { 26 | this(null: String) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/exceptions/agent/ServiceRegistrationException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.exceptions.agent 8 | 9 | /** Exception to be thrown whenever an agent fails to register for some service 10 | * @param message 11 | * specific error message 12 | */ 13 | class ServiceRegistrationException(message: String) extends Exception(message) { 14 | 15 | def this(message: String, cause: Throwable) = { 16 | this(message) 17 | initCause(cause) 18 | } 19 | 20 | def this(cause: Throwable) = { 21 | this(Option(cause).map(_.toString).orNull, cause) 22 | } 23 | 24 | def this() = { 25 | this(null: String) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/grid/GridSourceType.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.grid 8 | 9 | import edu.ie3.simona.util.ParsableEnumeration 10 | 11 | /** Enumeration to describe all eligible grid sources 12 | */ 13 | object GridSourceType extends ParsableEnumeration { 14 | val CSV: Value = Value("csv") 15 | val DB: Value = Value("db") 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/result/AccompaniedSimulationResult.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.result 8 | 9 | import edu.ie3.datamodel.models.result.ResultEntity 10 | import edu.ie3.simona.service.Data.PrimaryData.PrimaryDataWithComplexPower 11 | 12 | /** A class to offer means to transport accompanying results alongside of 13 | * [[PrimaryDataWithComplexPower]], e.g. heat results obtained during a 14 | * simulation 15 | * 16 | * @param primaryData 17 | * The original primary data of the electrical asset 18 | * @tparam PD 19 | * Type of primary data, that is carried 20 | */ 21 | final case class AccompaniedSimulationResult[ 22 | PD <: PrimaryDataWithComplexPower[PD] 23 | ](primaryData: PD, accompanyingResults: Seq[ResultEntity] = Seq.empty) 24 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/result/ResultEntitySink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.result 8 | 9 | import edu.ie3.datamodel.models.result.ResultEntity 10 | import edu.ie3.simona.exceptions.ProcessResultEventException 11 | 12 | /** Trait that should be mixed into each sink in [[edu.ie3.simona.io.result]] to 13 | * allow an easy calling of different sinks e.g. csv-file sink or database sink 14 | */ 15 | trait ResultEntitySink { 16 | 17 | /** Handling of a [[ResultEntity]] to perform an I/O operation to e.g. a file 18 | * or a database Should not be blocking but using futures internally to speed 19 | * up persisting 20 | * 21 | * @param resultEntity 22 | * the result entity that should be processed 23 | * @return 24 | * a future holding information about the handling process 25 | */ 26 | @throws(classOf[ProcessResultEventException]) 27 | def handleResultEntity(resultEntity: ResultEntity): Unit 28 | 29 | /** Contains all cleanup operations before closing this sink. Should be 30 | * blocking to ensure that everything inside a buffer or similar is written 31 | * out. 32 | */ 33 | def close(): Unit 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/result/plain/PlainResult.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.result.plain 8 | 9 | import java.util.UUID 10 | 11 | /** Results that are sent out with Kafka and avro should use this trait and 12 | * corresponding implementing classes, since these give more control over 13 | * attribute types and naming, and they include sim run id. Plain result 14 | * objects can be created by [[PlainWriter]]. 15 | */ 16 | sealed trait PlainResult 17 | 18 | object PlainResult { 19 | 20 | /** Plain result class for [[edu.ie3.datamodel.models.result.NodeResult]]. 21 | * 22 | * @param simRunId 23 | * the simulation run id 24 | * @param time 25 | * the current time, formatted by [[PlainWriter.createSimpleTimeStamp]] 26 | * @param inputModel 27 | * the uuid of the model that created this event 28 | * @param vMag 29 | * the voltage magnitude as a [[Double]] in 30 | * [[edu.ie3.util.quantities.PowerSystemUnits#PU]] 31 | * @param vAng 32 | * the voltage angle as a [[Double]] in 33 | * [[edu.ie3.util.quantities.PowerSystemUnits#DEGREE_GEOM]] 34 | */ 35 | final case class PlainNodeResult( 36 | simRunId: UUID, 37 | time: String, 38 | inputModel: UUID, 39 | vMag: Double, 40 | vAng: Double, 41 | ) extends PlainResult 42 | } 43 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/runtime/RuntimeEventQueueSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.runtime 8 | 9 | import edu.ie3.simona.event.RuntimeEvent 10 | import edu.ie3.simona.io.runtime.RuntimeEventSink.RuntimeStats 11 | 12 | import java.util.concurrent.BlockingQueue 13 | 14 | /** Runtime event sink that appends all received events to a queue. 15 | * @param queue 16 | * the queue that events are appended to 17 | */ 18 | final case class RuntimeEventQueueSink(queue: BlockingQueue[RuntimeEvent]) 19 | extends RuntimeEventSink { 20 | 21 | override def handleRuntimeEvent( 22 | runtimeEvent: RuntimeEvent, 23 | runtimeStats: RuntimeStats, 24 | ): Unit = 25 | queue.put(runtimeEvent) 26 | 27 | override def close(): Unit = { 28 | // nothing to close 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/io/runtime/RuntimeEventSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.io.runtime 8 | 9 | import edu.ie3.simona.event.RuntimeEvent 10 | import edu.ie3.simona.io.runtime.RuntimeEventSink.RuntimeStats 11 | 12 | /** Runtime event sinks are handling runtime events. More than one sink can 13 | * exist in parallel. 14 | */ 15 | trait RuntimeEventSink { 16 | 17 | /** Handling of a [[RuntimeEvent]], e.g. performing an I/O operation to a file 18 | * or a database. 19 | * 20 | * @param runtimeEvent 21 | * The runtime event that should be processed 22 | * @param runtimeStats 23 | * The runtime statistical data 24 | */ 25 | def handleRuntimeEvent( 26 | runtimeEvent: RuntimeEvent, 27 | runtimeStats: RuntimeStats, 28 | ): Unit 29 | 30 | /** Contains all cleanup operations before closing this sink. Should be 31 | * blocking to ensure that everything inside a buffer or similar is written 32 | * out. 33 | */ 34 | def close(): Unit 35 | } 36 | 37 | object RuntimeEventSink { 38 | 39 | /** Runtime object that keeps track of statistics 40 | * 41 | * @param failedPowerFlows 42 | * The number of failed power flow calculations so far 43 | */ 44 | final case class RuntimeStats( 45 | failedPowerFlows: Int = 0 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/InputModelContainer.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model 8 | 9 | import edu.ie3.datamodel.models.input.container.ThermalGrid 10 | import edu.ie3.datamodel.models.input.system.SystemParticipantInput 11 | 12 | sealed trait InputModelContainer[+I <: SystemParticipantInput] { 13 | val electricalInputModel: I 14 | } 15 | 16 | object InputModelContainer { 17 | 18 | final case class SimpleInputContainer[+I <: SystemParticipantInput]( 19 | override val electricalInputModel: I 20 | ) extends InputModelContainer[I] 21 | 22 | final case class WithHeatInputContainer[+I <: SystemParticipantInput]( 23 | override val electricalInputModel: I, 24 | thermalGrid: ThermalGrid, 25 | ) extends InputModelContainer[I] 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/control/GridControls.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.control 8 | 9 | /** Collection of grid-related control strategies 10 | * 11 | * @param transformerControlGroups 12 | * Transformer control groups 13 | */ 14 | final case class GridControls( 15 | transformerControlGroups: Set[TransformerControlGroupModel] 16 | ) 17 | 18 | object GridControls { 19 | 20 | /** Represents an empty GridControls group 21 | */ 22 | def empty: GridControls = GridControls(Set.empty) 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/em/EmAggregateFlex.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.em 8 | 9 | import edu.ie3.datamodel.models.input.AssetInput 10 | import edu.ie3.simona.ontology.messages.flex.MinMaxFlexOptions 11 | 12 | /** Offers method for aggregating flex options from connected agents which will 13 | * then be provided to a superior EmAgent or sent out as a flex result 14 | */ 15 | trait EmAggregateFlex { 16 | 17 | /** Aggregates flex options of connected devices to one flex options object 18 | * that describes the flexibility of this EmAgent. 19 | * 20 | * @param flexOptions 21 | * The flex options of all connected agents. 22 | * @return 23 | * The aggregated flex options. 24 | */ 25 | def aggregateFlexOptions( 26 | flexOptions: Iterable[ 27 | (_ <: AssetInput, MinMaxFlexOptions) 28 | ] 29 | ): MinMaxFlexOptions 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/em/EmAggregateSimpleSum.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.em 8 | 9 | import edu.ie3.datamodel.models.input.AssetInput 10 | import edu.ie3.simona.ontology.messages.flex.MinMaxFlexOptions 11 | 12 | /** Aggregates reference, minimum and maximum power by just simply summing up 13 | * each value. 14 | */ 15 | object EmAggregateSimpleSum extends EmAggregateFlex { 16 | 17 | override def aggregateFlexOptions( 18 | flexOptions: Iterable[ 19 | (_ <: AssetInput, MinMaxFlexOptions) 20 | ] 21 | ): MinMaxFlexOptions = 22 | flexOptions.map { case (_, flex: MinMaxFlexOptions) => 23 | flex 24 | }.flexSum 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/grid/VoltageLimits.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.grid 8 | 9 | import edu.ie3.util.quantities.QuantityUtils.asPu 10 | import tech.units.indriya.ComparableQuantity 11 | 12 | import javax.measure.quantity.Dimensionless 13 | 14 | /** Case class that holds information about the lower and upper voltage limit of 15 | * the grid. 16 | * @param vMin 17 | * minimal allowed voltage in the grid 18 | * @param vMax 19 | * maximal allowed voltage in the grid 20 | */ 21 | final case class VoltageLimits( 22 | vMin: ComparableQuantity[Dimensionless], 23 | vMax: ComparableQuantity[Dimensionless], 24 | ) { 25 | 26 | /** Checks if a given voltage magnitude is within the given limits. 27 | * @param voltage 28 | * to check 29 | * @return 30 | * true if the given voltage magnitude is within the limits 31 | */ 32 | def isInLimits(voltage: ComparableQuantity[Dimensionless]): Boolean = 33 | vMin.isLessThanOrEqualTo(voltage) && voltage.isLessThanOrEqualTo(vMax) 34 | } 35 | 36 | object VoltageLimits { 37 | def apply( 38 | vMin: Double, 39 | vMax: Double, 40 | ): VoltageLimits = VoltageLimits(vMin.asPu, vMax.asPu) 41 | } 42 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/evcs/ConstantPowerCharging.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.evcs 8 | 9 | import squants.{Power, Seconds} 10 | 11 | import java.util.UUID 12 | 13 | /** Determine scheduling for charging the EVs currently parked at the charging 14 | * station by charging with constant power from current time until departure. 15 | * If less than the maximum power is required to reach 100% SoC, the power is 16 | * reduced accordingly. 17 | */ 18 | object ConstantPowerCharging extends EvcsChargingStrategy { 19 | 20 | override def determineChargingPowers( 21 | evs: Iterable[EvModelWrapper], 22 | currentTick: Long, 23 | chargingProps: EvcsChargingProperties, 24 | ): Map[UUID, Power] = evs 25 | .filter(ev => ev.storedEnergy < ev.eStorage) 26 | .map { ev => 27 | val maxChargingPower = chargingProps.getMaxAvailableChargingPower(ev) 28 | val remainingParkingTime = Seconds(ev.departureTick - currentTick) 29 | 30 | val requiredEnergyUntilFull = ev.eStorage - ev.storedEnergy 31 | 32 | val chargingPower = 33 | maxChargingPower.min(requiredEnergyUntilFull / remainingParkingTime) 34 | 35 | ev.uuid -> chargingPower 36 | } 37 | .toMap 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/evcs/EvcsChargingProperties.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.evcs 8 | 9 | import edu.ie3.datamodel.models.ElectricCurrentType 10 | import squants.Power 11 | 12 | /** Provides some relevant EVCS properties to [[EvcsChargingStrategy]]. 13 | */ 14 | trait EvcsChargingProperties { 15 | 16 | /** The rated active power of the charging station. 17 | */ 18 | protected val pRated: Power 19 | 20 | /** The type of current used by the charging station. 21 | */ 22 | val currentType: ElectricCurrentType 23 | 24 | /** The lowest allowed SOC of all connected EVs. Below this threshold, 25 | * charging is mandatory. 26 | */ 27 | val lowestEvSoc: Double 28 | 29 | /** Returns the maximum available charging power for an EV, which depends on 30 | * EV and charging station limits for AC and DC current. 31 | * 32 | * @param ev 33 | * The EV for which the max charging power should be returned. 34 | * @return 35 | * The maximum charging power for the EV at this charging station. 36 | */ 37 | def getMaxAvailableChargingPower( 38 | ev: EvModelWrapper 39 | ): Power = { 40 | val evPower = currentType match { 41 | case ElectricCurrentType.AC => 42 | ev.pRatedAc 43 | case ElectricCurrentType.DC => 44 | ev.pRatedDc 45 | } 46 | /* Limit the charging power to the minimum of EV's and EVCS' permissible power */ 47 | evPower.min(pRated) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/evcs/EvcsChargingStrategy.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.evcs 8 | 9 | import edu.ie3.simona.exceptions.CriticalFailureException 10 | import squants.Power 11 | 12 | import java.util.UUID 13 | 14 | trait EvcsChargingStrategy { 15 | 16 | /** Determine scheduling for charging the EVs currently parked at the charging 17 | * station until their departure. 18 | * 19 | * @param evs 20 | * The currently parked EVs at the charging station. 21 | * @param currentTick 22 | * The current tick. 23 | * @param chargingProps 24 | * The interface that provides information on charging station. 25 | * @return 26 | * The scheduling for charging the EVs. 27 | */ 28 | def determineChargingPowers( 29 | evs: Iterable[EvModelWrapper], 30 | currentTick: Long, 31 | chargingProps: EvcsChargingProperties, 32 | ): Map[UUID, Power] 33 | 34 | } 35 | 36 | object EvcsChargingStrategy { 37 | 38 | def apply(token: String): EvcsChargingStrategy = 39 | "[-_]".r.replaceAllIn(token.trim.toLowerCase, "") match { 40 | case "maxpower" => MaximumPowerCharging 41 | case "constantpower" => ConstantPowerCharging 42 | case unknown => 43 | throw new CriticalFailureException( 44 | s"The token '$unknown' cannot be parsed to charging strategy." 45 | ) 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/evcs/MaximumPowerCharging.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.evcs 8 | 9 | import squants.Power 10 | 11 | import java.util.UUID 12 | 13 | /** Determine scheduling for charging the EVs currently parked at the charging 14 | * station by charging with maximum power from current time until it reaches 15 | * either 100% SoC or its departure time. 16 | */ 17 | object MaximumPowerCharging extends EvcsChargingStrategy { 18 | 19 | def determineChargingPowers( 20 | evs: Iterable[EvModelWrapper], 21 | currentTick: Long, 22 | chargingProps: EvcsChargingProperties, 23 | ): Map[UUID, Power] = evs 24 | .filter(ev => ev.storedEnergy < ev.eStorage) 25 | .map { ev => 26 | ev.uuid -> chargingProps.getMaxAvailableChargingPower(ev) 27 | } 28 | .toMap 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/load/LoadModelBehaviour.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.load 8 | 9 | import edu.ie3.simona.util.ParsableEnumeration 10 | 11 | /** Enumeration to describe all eligible load model behaviours 12 | */ 13 | object LoadModelBehaviour extends ParsableEnumeration { 14 | val FIX: Value = Value("fix") 15 | val PROFILE: Value = Value("profile") 16 | val RANDOM: Value = Value("random") 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/participant/load/LoadReferenceType.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.load 8 | 9 | import edu.ie3.simona.util.ParsableEnumeration 10 | 11 | /** Denoting difference referencing scenarios for scaling load model output 12 | */ 13 | object LoadReferenceType extends ParsableEnumeration { 14 | 15 | /** Scale the load model behaviour so that the rated power of the load model 16 | * serves as the maximum power consumption 17 | */ 18 | val ACTIVE_POWER: Value = Value("power") 19 | 20 | /** Scale the load model behaviour so that the aggregate annual energy 21 | * consumption corresponds to the energy set by the model input 22 | */ 23 | val ENERGY_CONSUMPTION: Value = Value("energy") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/thermal/ThermalSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.thermal 8 | 9 | import java.util.UUID 10 | 11 | import edu.ie3.datamodel.models.OperationTime 12 | import edu.ie3.datamodel.models.input.OperatorInput 13 | import edu.ie3.datamodel.models.input.thermal.ThermalBusInput 14 | 15 | /** Thermal sink model. 16 | * 17 | * @param uuid 18 | * the element's uuid 19 | * @param id 20 | * the element's human-readable id 21 | * @param operatorInput 22 | * Operator input 23 | * @param operationTime 24 | * Operation time 25 | * @param bus 26 | * Thermal bus input 27 | */ 28 | abstract class ThermalSink( 29 | uuid: UUID, 30 | id: String, 31 | operatorInput: OperatorInput, 32 | operationTime: OperationTime, 33 | bus: ThermalBusInput, 34 | ) 35 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/model/thermal/ThermalThreshold.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.thermal 8 | 9 | trait ThermalThreshold { 10 | val tick: Long 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/ontology/GridAgentHierarchy.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.ontology 8 | 9 | sealed trait GridAgentHierarchy 10 | 11 | /** Describes the hierarchical structure of 12 | * [[edu.ie3.simona.agent.grid.GridAgent]] s in a simulation, whereas 13 | * [[edu.ie3.simona.ontology.GridAgentHierarchy.Centrum]] might be existing 14 | * multiple times e.g. when multiple medium voltage levels are present 15 | */ 16 | object GridAgentHierarchy { 17 | 18 | final case object Superior extends GridAgentHierarchy 19 | 20 | final case object Centrum extends GridAgentHierarchy 21 | 22 | final case object Inferior extends GridAgentHierarchy 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/ontology/messages/Activation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.ontology.messages 8 | 9 | final case class Activation(tick: Long) 10 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/ontology/messages/SchedulerMessage.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.ontology.messages 8 | 9 | import org.apache.pekko.actor.typed.ActorRef 10 | import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey 11 | import edu.ie3.simona.scheduler.{Scheduler, TimeAdvancer} 12 | 13 | trait SchedulerMessage extends Scheduler.Request with TimeAdvancer.Request 14 | 15 | object SchedulerMessage { 16 | final case class Completion( 17 | actor: ActorRef[Activation], 18 | newTick: Option[Long] = None, 19 | ) extends SchedulerMessage 20 | 21 | final case class ScheduleActivation( 22 | actor: ActorRef[Activation], 23 | tick: Long, 24 | unlockKey: Option[ScheduleKey] = None, 25 | ) extends SchedulerMessage 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexOptions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.ontology.messages.flex 8 | 9 | /** Trait that all flex option types have to extend. */ 10 | trait FlexOptions {} 11 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/service/ServiceStateData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.service 8 | 9 | import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} 10 | import edu.ie3.util.scala.collection.immutable.SortedDistinctSeq 11 | import org.apache.pekko.actor.typed.ActorRef 12 | 13 | trait ServiceStateData 14 | 15 | object ServiceStateData { 16 | 17 | /** Data that is required to initialize a SimonaService 18 | */ 19 | trait InitializeServiceStateData extends ServiceStateData 20 | 21 | trait ServiceBaseStateData extends ServiceStateData 22 | 23 | final case class ServiceConstantStateData( 24 | scheduler: ActorRef[SchedulerMessage], 25 | activationAdapter: ActorRef[Activation], 26 | ) extends ServiceStateData 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/service/ServiceType.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.service 8 | 9 | sealed trait ServiceType 10 | 11 | object ServiceType { 12 | 13 | case object WeatherService extends ServiceType 14 | 15 | case object PriceService extends ServiceType 16 | 17 | case object EvMovementService extends ServiceType 18 | 19 | case object LoadProfileService extends ServiceType 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/util/EntityMapperUtil.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | import edu.ie3.datamodel.models.result.ResultEntity 10 | import edu.ie3.datamodel.models.result.system._ 11 | import edu.ie3.datamodel.models.result.thermal.{ 12 | CylindricalStorageResult, 13 | ThermalHouseResult, 14 | } 15 | import edu.ie3.simona.util.ConfigUtil.NotifierIdentifier 16 | import edu.ie3.simona.util.ConfigUtil.NotifierIdentifier._ 17 | 18 | object EntityMapperUtil { 19 | private val entityMapping 20 | : Map[NotifierIdentifier.Value, Class[_ <: ResultEntity]] = Map( 21 | PvPlant -> classOf[PvResult], 22 | Wec -> classOf[WecResult], 23 | Load -> classOf[LoadResult], 24 | FixedFeedIn -> classOf[FixedFeedInResult], 25 | BioMassPlant -> classOf[BmResult], 26 | Ev -> classOf[EvResult], 27 | Evcs -> classOf[EvcsResult], 28 | Storage -> classOf[StorageResult], 29 | Em -> classOf[EmResult], 30 | Hp -> classOf[HpResult], 31 | House -> classOf[ThermalHouseResult], 32 | CylindricalStorage -> classOf[CylindricalStorageResult], 33 | ) 34 | 35 | /** Get the classes of [[ResultEntity]], that are issued by the notifier, that 36 | * can be identified by the given id 37 | * 38 | * @param notifierId 39 | * Identifier of a certain [[edu.ie3.simona.event.notifier.Notifier]] 40 | * @return 41 | * An [[Option]] of classes that are childs of [[ResultEntity]] 42 | */ 43 | def getResultEntityClass( 44 | notifierId: NotifierIdentifier.Value 45 | ): Class[_ <: ResultEntity] = 46 | entityMapping.getOrElse( 47 | notifierId, 48 | throw new NoSuchElementException( 49 | s"Cannot determine result entity class of notifier $notifierId" 50 | ), 51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/util/ParsableEnumeration.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | import edu.ie3.util.StringUtils 10 | 11 | /** Abstract class, that offers enhanced functionality to parse an enum value 12 | * from a given String input. 13 | */ 14 | abstract class ParsableEnumeration extends Enumeration { 15 | 16 | /** Get a matching enum value from string input. If no matching behaviour can 17 | * be found, a NoSuchElementException is thrown. 18 | * 19 | * @param input 20 | * Input string 21 | * @return 22 | * Matching load model behaviour 23 | */ 24 | def apply(input: String): Value = { 25 | val cleanedInput = prepareInputString(input) 26 | withName(cleanedInput) 27 | } 28 | 29 | /** Checks, if the given input is an eligible description of an enum value 30 | * 31 | * @param input 32 | * Input string 33 | * @return 34 | * true, if it is eligible, false if not 35 | */ 36 | def isEligibleInput(input: String): Boolean = { 37 | val cleanedInput = prepareInputString(input) 38 | values.exists(_.toString == cleanedInput) 39 | } 40 | 41 | /** Uniform processing of Strings: Replaces all non word characters, trims it 42 | * and converts it to lower case 43 | * 44 | * @param input 45 | * String to prepare 46 | * @return 47 | * Processed String 48 | */ 49 | private def prepareInputString(input: String): String = 50 | StringUtils.cleanString(input.trim).toLowerCase 51 | } 52 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/util/ReceiveDataMap.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | /** Map that holds data that an actor is expected to receive over time and 10 | * efficiently determines if all expected data has been received. 11 | * @param expectedKeys 12 | * The keys for which data is expected 13 | * @param receivedData 14 | * The map holding all received data so far 15 | * @tparam K 16 | * The type of the key 17 | * @tparam V 18 | * The type of the value 19 | */ 20 | final case class ReceiveDataMap[K, V]( 21 | private val expectedKeys: Set[K], 22 | receivedData: Map[K, V], 23 | ) { 24 | def isComplete: Boolean = expectedKeys.isEmpty 25 | 26 | def nonComplete: Boolean = expectedKeys.nonEmpty 27 | 28 | def addData( 29 | key: K, 30 | value: V, 31 | ): ReceiveDataMap[K, V] = { 32 | 33 | if (!expectedKeys.contains(key)) 34 | throw new RuntimeException( 35 | s"Received value $value for key $key, but no data has been expected for this key." 36 | ) 37 | 38 | copy( 39 | expectedKeys = expectedKeys.excl(key), 40 | receivedData.updated(key, value), 41 | ) 42 | } 43 | 44 | } 45 | 46 | object ReceiveDataMap { 47 | 48 | def apply[K, V]( 49 | expectedKeys: Set[K] 50 | ): ReceiveDataMap[K, V] = 51 | ReceiveDataMap( 52 | expectedKeys = expectedKeys, 53 | receivedData = Map.empty, 54 | ) 55 | 56 | def empty[K, V]: ReceiveDataMap[K, V] = 57 | ReceiveDataMap( 58 | expectedKeys = Set.empty, 59 | receivedData = Map.empty, 60 | ) 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/simona/util/SimonaConstants.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | /** Defines several constants that are used as constant parameters in the whole 10 | * simulation 11 | * 12 | * @version 0.1 13 | * @since 12.01.20 14 | */ 15 | object SimonaConstants { 16 | 17 | @deprecated("This pattern is not used anywhere") 18 | val DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss" 19 | 20 | /** Tick before the initialization of the simulation shall take place 21 | */ 22 | val PRE_INIT_TICK: Long = -2L 23 | 24 | /** Tick, in which the initialization of the simulation shall take place 25 | */ 26 | val INIT_SIM_TICK: Long = -1L 27 | 28 | /** First tick, at which an actual simulation takes place 29 | */ 30 | val FIRST_TICK_IN_SIMULATION: Long = 0L 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/OperationInterval.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala 8 | 9 | import edu.ie3.util.interval.RightOpenInterval 10 | 11 | /** Wrapper class for an operation interval, as the superclass 12 | * [[RightOpenInterval]] only accepts [[java.lang.Long]] as type parameter 13 | * 14 | * @param start 15 | * Start of operation period (included) 16 | * @param end 17 | * End of operation period (included) 18 | */ 19 | final case class OperationInterval(start: Long, end: Long) 20 | extends RightOpenInterval[java.lang.Long](start, end) 21 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/Scope.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala 8 | 9 | /** Class that introduces functional ''mapping'' if there's an object that is 10 | * not wrapped in a monad, such as [[Either]] or [[Option]]. 11 | * 12 | * This class is useful when code should be divided into multiple pieces that 13 | * each have their own scope, so that objects of the same class are not 14 | * confused. For example, in the following code snippet, ''a'', ''b'', ''c'' 15 | * and ''d'' can be easily confused, which can lead to errors that are hard to 16 | * trace. 17 | * 18 | * {{{ 19 | * val a: Foo = create() 20 | * val b: Foo = transform(a) 21 | * val c: Foo = b.doStuff() 22 | * val d: Foo = maybeBar.calculate(c) 23 | * }}} 24 | * 25 | * When using a [[Scope]], the variables cannot be confused anymore: 26 | * 27 | * {{{ 28 | * val d: Foo = Scope(create()) 29 | * .map(transform) 30 | * .map(_.doStuff) 31 | * .map(maybeBar.calculate) 32 | * .get 33 | * }}} 34 | * 35 | * @param obj 36 | * The object that is held 37 | * @tparam T 38 | * The type of the object 39 | */ 40 | final case class Scope[T](private val obj: T) { 41 | def map[B](f: T => B): Scope[B] = Scope(f(obj)) 42 | 43 | def get: T = obj 44 | } 45 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/collection/immutable/SortedDistinctSeq.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala.collection.immutable 8 | 9 | import edu.ie3.util.scala.collection.immutable 10 | 11 | /** Simple wrapper around [[Seq]], that enforces the user to use the 12 | * [[SortedDistinctSeq#apply()]] builder. It ensures, that the sequence only 13 | * contains distinct entries and that it is sorted. 14 | * 15 | * @param internalSequence 16 | * The internal sequence with distinct, sorted entries 17 | * @tparam V 18 | * Type of value, the sequence may carry. 19 | */ 20 | final case class SortedDistinctSeq[V] private ( 21 | internalSequence: IndexedSeq[V] 22 | ) extends Seq[V] { 23 | override def apply(i: Int): V = internalSequence.apply(i) 24 | 25 | override def length: Int = internalSequence.length 26 | 27 | override def iterator: Iterator[V] = internalSequence.iterator 28 | 29 | def pop: (Option[V], SortedDistinctSeq[V]) = { 30 | val maybeHead = internalSequence.headOption 31 | val newSeq = new immutable.SortedDistinctSeq( 32 | maybeHead 33 | .map(head => internalSequence.filter(_ != head)) 34 | .getOrElse(IndexedSeq.empty[V]) 35 | ) 36 | (maybeHead, newSeq) 37 | } 38 | } 39 | 40 | case object SortedDistinctSeq { 41 | def apply[V]( 42 | entries: Seq[V] 43 | )(implicit ord: Ordering[V]): SortedDistinctSeq[V] = 44 | new SortedDistinctSeq(entries.toIndexedSeq.distinct.sorted) 45 | 46 | def empty[V] = new SortedDistinctSeq[V](IndexedSeq.empty[V]) 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/quantities/DefaultQuantities.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala.quantities 8 | 9 | import squants.energy.{KilowattHours, Kilowatts, MegawattHours, Megawatts} 10 | import squants.thermal.Celsius 11 | import squants.{Dimensionless, Each, Energy, Power, Temperature} 12 | 13 | object DefaultQuantities { 14 | 15 | val zeroKW: Power = Kilowatts(0d) 16 | val zeroMW: Power = Megawatts(0d) 17 | 18 | val zeroWPerSM: Irradiance = WattsPerSquareMeter(0d) 19 | 20 | val zeroKVAr: ReactivePower = Kilovars(0d) 21 | val zeroMVAr: ReactivePower = Megavars(0d) 22 | 23 | val zeroKWh: Energy = KilowattHours(0d) 24 | val zeroMWh: Energy = MegawattHours(0d) 25 | 26 | val zeroPU: Dimensionless = Each(0d) 27 | val zeroCelsius: Temperature = Celsius(0) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/quantities/EnergyPrice.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala.quantities 8 | 9 | import squants.energy.Energy 10 | import squants.market.{EUR, Money} 11 | import squants.{Dimension, PrimaryUnit, SiUnit, UnitConverter, UnitOfMeasure} 12 | 13 | import scala.util.Try 14 | 15 | /** Represents the price of one Kilowatthour in currency EURO 16 | */ 17 | 18 | final class EnergyPrice private ( 19 | val value: Double, 20 | val unit: EnergyPriceUnit, 21 | ) extends squants.Quantity[EnergyPrice] { 22 | 23 | def dimension: EnergyPrice.type = EnergyPrice 24 | 25 | def *(that: Energy): Money = EUR( 26 | this.toEuroPerKilowattHour * that.toKilowattHours 27 | ) 28 | 29 | def toEuroPerKilowattHour: Double = to(EuroPerKilowatthour) 30 | 31 | } 32 | 33 | object EnergyPrice extends Dimension[EnergyPrice] { 34 | def apply[A](n: A, unit: EnergyPriceUnit)(implicit num: Numeric[A]) = 35 | new EnergyPrice(num.toDouble(n), unit) 36 | def apply(value: Any): Try[EnergyPrice] = parse(value) 37 | def name = "EnergyPrice" 38 | def primaryUnit: EuroPerKilowatthour.type = EuroPerKilowatthour 39 | def siUnit: EuroPerKilowatthour.type = EuroPerKilowatthour 40 | def units: Set[UnitOfMeasure[EnergyPrice]] = Set( 41 | EuroPerKilowatthour 42 | ) 43 | } 44 | 45 | trait EnergyPriceUnit extends UnitOfMeasure[EnergyPrice] with UnitConverter { 46 | def apply[A](n: A)(implicit num: Numeric[A]): EnergyPrice = 47 | EnergyPrice(n, this) 48 | } 49 | 50 | object EuroPerKilowatthour 51 | extends EnergyPriceUnit 52 | with PrimaryUnit 53 | with SiUnit { 54 | val symbol: String = EUR.symbol + "/kWh" 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/quantities/Sq.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala.quantities 8 | 9 | import squants.{Quantity, UnitOfMeasure} 10 | 11 | object Sq { 12 | 13 | def create[A <: Quantity[A]](num: Number, unit: UnitOfMeasure[A]): A = { 14 | num match { 15 | case d: java.lang.Double => 16 | unit.apply(d.doubleValue()) 17 | case i: java.lang.Integer => 18 | unit.apply(i.intValue()) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/edu/ie3/util/scala/quantities/SquantsUtils.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.scala.quantities 8 | 9 | import squants.electro.{ElectricPotential, Volts} 10 | import squants.energy.Energy 11 | import squants.space.{CubicMeters, Volume} 12 | import squants.thermal.ThermalCapacity 13 | import squants.{Dimensionless, Each} 14 | 15 | object SquantsUtils { 16 | implicit class RichEnergy(energy: Energy) { 17 | def calcVolume(that: EnergyDensity): Volume = CubicMeters( 18 | energy.toKilowattHours / that.toKilowattHoursPerCubicMeter 19 | ) 20 | } 21 | implicit class RichPower(power: squants.Power) { 22 | def /(that: ReactivePower): Dimensionless = Each( 23 | power.toWatts / that.toVars 24 | ) 25 | } 26 | 27 | implicit class RichElectricPotential( 28 | electricPotential: ElectricPotential 29 | ) { 30 | def multiplyWithDimensionless( 31 | that: Dimensionless 32 | ): ElectricPotential = Volts( 33 | electricPotential.toVolts * that.toEach 34 | ) 35 | 36 | } 37 | 38 | implicit class RichThermalCapacity( 39 | thermalCapacity: ThermalCapacity 40 | ) { 41 | def toWattHoursPerKelvin: Double = 42 | this.thermalCapacity.toJoulesPerKelvin / 3600 43 | def toWattSecondsPerKelvin: Double = 44 | this.thermalCapacity.toJoulesPerKelvin // Joule == Ws 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/sh/deploy/README.md: -------------------------------------------------------------------------------- 1 | # Deployment Scripts 2 | This folder contains several scripts that are used to deploy simona on cloud server infrastructure. As these scripts 3 | are in an unstable state and currently not actively maintained, no documentation exists. If you want to set up your 4 | own simona run cloud server feel free to contact any of the responsible maintainers. 5 | -------------------------------------------------------------------------------- /src/main/sh/deploy/influxDb1x/docker/start_docker_grafana.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VIRTUAL_HOST_NAME=$1 4 | GRAFANA_ROOT_URL=$2 5 | PROVISIONING_PATH=$3 6 | STORAGE_PATH=$4 7 | RUN_NAME=$(echo "$5" | tr -dc '[a-zA-Z0-9]\n\r') 8 | 9 | docker run \ 10 | -d \ 11 | --rm \ 12 | -v "$PROVISIONING_PATH":/etc/grafana/provisioning \ 13 | -v "$STORAGE_PATH":/var/lib/grafana \ 14 | -e VIRTUAL_HOST="$VIRTUAL_HOST_NAME" \ 15 | -e GF_SERVER_ROOT_URL="$GRAFANA_ROOT_URL" \ 16 | -e GF_SERVER_SERVE_FROM_SUB_PATH=true \ 17 | --name "$RUN_NAME"_grafana \ 18 | grafana/grafana:latest 19 | -------------------------------------------------------------------------------- /src/main/sh/deploy/influxDb1x/docker/start_docker_influxdb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VOLUME_PATH=$1 4 | EXPOSED_PORT=$2 5 | SERVER_IP=$3 6 | DB_NAME=$4 7 | RUN_NAME=$(echo "$5" | tr -dc '[a-zA-Z0-9]\n\r') 8 | 9 | ABSOLUT_DIR_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 10 | 11 | DOCKER_HASH=$(docker run \ 12 | -d \ 13 | --rm \ 14 | -v "$VOLUME_PATH":/var/lib/influxdb \ 15 | -p "$EXPOSED_PORT":8086 \ 16 | -e INFLUXDB_DB="$DB_NAME" \ 17 | --name "$RUN_NAME"_influxDb \ 18 | influxdb:1.8.3) 19 | 20 | "$ABSOLUT_DIR_PATH"/wait-for.sh "$SERVER_IP":"$EXPOSED_PORT" -- echo "$DOCKER_HASH" -------------------------------------------------------------------------------- /src/main/sh/deploy/influxDb1x/docker/wait-for.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TIMEOUT=15 4 | QUIET=0 5 | 6 | echoerr() { 7 | if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi 8 | } 9 | 10 | usage() { 11 | exitcode="$1" 12 | cat <&2 13 | Usage: 14 | $cmdname host:port [-t timeout] [-- command args] 15 | -q | --quiet Do not output any status messages 16 | -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout 17 | -- COMMAND ARGS Execute command with args after the test finishes 18 | USAGE 19 | exit "$exitcode" 20 | } 21 | 22 | wait_for() { 23 | for i in $(seq $TIMEOUT); do 24 | nc -z "$HOST" "$PORT" >/dev/null 2>&1 25 | 26 | result=$? 27 | if [ $result -eq 0 ]; then 28 | if [ $# -gt 0 ]; then 29 | exec "$@" 30 | fi 31 | exit 0 32 | fi 33 | sleep 1 34 | done 35 | echo "Operation timed out" >&2 36 | exit 1 37 | } 38 | 39 | while [ $# -gt 0 ]; do 40 | case "$1" in 41 | *:*) 42 | HOST=$(printf "%s\n" "$1" | cut -d : -f 1) 43 | PORT=$(printf "%s\n" "$1" | cut -d : -f 2) 44 | shift 1 45 | ;; 46 | -q | --quiet) 47 | QUIET=1 48 | shift 1 49 | ;; 50 | -t) 51 | TIMEOUT="$2" 52 | if [ "$TIMEOUT" = "" ]; then break; fi 53 | shift 2 54 | ;; 55 | --timeout=*) 56 | TIMEOUT="${1#*=}" 57 | shift 1 58 | ;; 59 | --) 60 | shift 61 | break 62 | ;; 63 | --help) 64 | usage 0 65 | ;; 66 | *) 67 | echoerr "Unknown argument: $1" 68 | usage 1 69 | ;; 70 | esac 71 | done 72 | 73 | if [ "$HOST" = "" -o "$PORT" = "" ]; then 74 | echoerr "Error: you need to provide a host and port to test." 75 | usage 2 76 | fi 77 | 78 | wait_for "$@" 79 | -------------------------------------------------------------------------------- /src/main/sh/deploy/influxDb1x/grafana/provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: InfluxDB 4 | type: influxdb 5 | access: proxy 6 | database: simona 7 | user: admin 8 | password: admin 9 | url: http://influxdb:8086 10 | isDefault: true 11 | editable: true -------------------------------------------------------------------------------- /src/main/sh/deploy/run-simona-cmd.sh: -------------------------------------------------------------------------------- 1 | # rung simona server side with special parameters 2 | 3 | java -Xmx80g \ 4 | -Xms40g \ 5 | -Xss2048k \ 6 | -XX:+UseParallelGC \ 7 | -XX:+UseParallelOldGC \ 8 | -XX:MetaspaceSize=150M \ 9 | -Djava.awt.headless=true \ 10 | -cp build/libs/simona-2.1.0-SNAPSHOT-all.jar \ 11 | edu.ie3.simona.main.RunSimonaStandalone \ 12 | "$@" 13 | 14 | # cmds for remote control (requires firewall adaptions) 15 | # -Dcom.sun.management.jmxremote \ 16 | # -Dcom.sun.management.jmxremote.rmi.port=9198 \ 17 | # -Djava.rmi.server.hostname=129.217.187.244 \ 18 | # -Dcom.sun.management.jmxremote.port=9198 \ 19 | # -Dcom.sun.management.jmxremote.local.only=false \ 20 | # -Dcom.sun.management.jmxremote.authenticate=false \ 21 | # -Dcom.sun.management.jmxremote.ssl=false \ 22 | 23 | # cmd for additional logging config to be passed in 24 | # -Dlog4j.configurationFile=config/log4j2.xml \ 25 | -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/model/participant/_pv/it/results.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/model/participant/_pv/it/results.tar.gz -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/model/participant/_pv/it/weather.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/model/participant/_pv/it/weather.tar.gz -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/load/_it/lpts_g0.csv: -------------------------------------------------------------------------------- 1 | SuSa,SuSu,SuWd,TrSa,TrSu,TrWd,WiSa,WiSu,WiWd,quarterHour 2 | 74.6,68.8,71.5,75.8,68.3,73.0,70.0,63.2,65.5,0 3 | 76.2,67.4,69.0,76.7,66.5,70.1,73.0,61.0,62.6,1 -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_it/its_p_3fbfaa97-cff4-46d4-95ba-a95665e87c27.csv: -------------------------------------------------------------------------------- 1 | "time";"p_wrong_heading" 2 | 2020-01-01T00:00:00Z;1000.0 3 | 2020-01-01T00:15:00Z;1250.0 -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_it/its_p_9185b8c1-86ba-4a16-8dea-5ac898e8caa5.csv: -------------------------------------------------------------------------------- 1 | "time";"p" 2 | 2020-01-01T00:00:00Z;1000.0 3 | 2020-01-01T00:15:00Z;1250.0 4 | 2020-01-01T00:30:00Z;1500.0 -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_it/its_pq_3fbfaa97-cff4-46d4-95ba-a95665e87c26.csv: -------------------------------------------------------------------------------- 1 | "time";"p";"q" 2 | 2020-01-01T00:00:00Z;1000.0;329.0 3 | 2020-01-01T00:15:00Z;1250.0;411.0 -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_it/time_series_mapping.csv: -------------------------------------------------------------------------------- 1 | "asset";"time_series" 2 | "b86e95b0-e579-4a80-a534-37c7a470a409";"9185b8c1-86ba-4a16-8dea-5ac898e8caa5" 3 | "c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8";"3fbfaa97-cff4-46d4-95ba-a95665e87c26" 4 | "90a96daa-012b-4fea-82dc-24ba7a7ab81c";"3fbfaa97-cff4-46d4-95ba-a95665e87c26" -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_timeseries/time_series_mapping.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.time_series_mapping 2 | ( 3 | asset uuid PRIMARY KEY, 4 | time_series uuid 5 | ) 6 | WITHOUT OIDS 7 | TABLESPACE pg_default; 8 | 9 | INSERT INTO 10 | public.time_series_mapping (asset, time_series) 11 | VALUES 12 | ('b86e95b0-e579-4a80-a534-37c7a470a409', '9185b8c1-86ba-4a16-8dea-5ac898e8caa5'), 13 | ('c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8', '3fbfaa97-cff4-46d4-95ba-a95665e87c26'), 14 | ('90a96daa-012b-4fea-82dc-24ba7a7ab81c', '3fbfaa97-cff4-46d4-95ba-a95665e87c26'); 15 | -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_timeseries/time_series_p.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.time_series_p 2 | ( 3 | uuid uuid PRIMARY KEY, 4 | time_series uuid NOT NULL, 5 | time timestamp with time zone NOT NULL, 6 | p double precision NOT NULL 7 | ) 8 | WITHOUT OIDS 9 | TABLESPACE pg_default; 10 | 11 | CREATE INDEX time_series_p_series_id ON time_series_p USING hash (time_series); 12 | 13 | -- Order of columns is important when using btree: https://www.postgresql.org/docs/14/indexes-multicolumn.html 14 | -- Column time_series needs to placed as the first argument since we at most use an equality constraint on 15 | -- time_series and a range query on time. 16 | CREATE UNIQUE INDEX time_series_p_series_time ON time_series_p USING btree (time_series, time); 17 | 18 | INSERT INTO 19 | public.time_series_p (uuid, time_series, time, p) 20 | VALUES 21 | ('0245d599-9a5c-4c32-9613-5b755fac8ca0', '9185b8c1-86ba-4a16-8dea-5ac898e8caa5', '2020-01-01 00:00:00+0', 1000.0), 22 | ('a5e27652-9024-4a93-9d2a-590fbc3ab5a1', '9185b8c1-86ba-4a16-8dea-5ac898e8caa5', '2020-01-01 00:15:00+0', 1250.0), 23 | ('b4a2b3e0-7215-431b-976e-d8b41c7bc71b', 'b669e4bf-a351-4067-860d-d5f224b62247', '2020-01-01 00:00:00+0', 50.0), 24 | ('1c8f072c-c833-47da-a3e9-5f4d305ab926', 'b669e4bf-a351-4067-860d-d5f224b62247', '2020-01-01 00:15:00+0', 100.0); 25 | -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/service/primary/_timeseries/time_series_pqh.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.time_series_pqh 2 | ( 3 | uuid uuid PRIMARY KEY, 4 | time_series uuid NOT NULL, 5 | time timestamp with time zone NOT NULL, 6 | p double precision NOT NULL, 7 | q double precision NOT NULL, 8 | heat_demand double precision NOT NULL 9 | ) 10 | WITHOUT OIDS 11 | TABLESPACE pg_default; 12 | 13 | CREATE INDEX time_series_pqh_series_id ON time_series_pqh USING hash (time_series); 14 | 15 | -- Order of columns is important when using btree: https://www.postgresql.org/docs/14/indexes-multicolumn.html 16 | -- Column time_series needs to placed as the first argument since we at most use an equality constraint on 17 | -- time_series and a range query on time. 18 | CREATE UNIQUE INDEX time_series_pqh_series_time ON time_series_pqh USING btree (time_series, time); 19 | 20 | INSERT INTO 21 | public.time_series_pqh (uuid, time_series, time, p, q, heat_demand) 22 | VALUES 23 | ('661ac594-47f0-4442-8d82-bbeede5661f7', '46be1e57-e4ed-4ef7-95f1-b2b321cb2047', '2020-01-01 00:00:00+0', 1000.0, 329.0, 8.0), 24 | ('5adcd6c5-a903-433f-b7b5-5fe669a3ed30', '46be1e57-e4ed-4ef7-95f1-b2b321cb2047', '2020-01-01 00:15:00+0', 1250.0, 411.0, 12.0); 25 | -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/irrelevant.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/irrelevant.txt -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-2.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-empty_file.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-empty_file.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-missing_service_file.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-missing_service_file.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-two_implementations.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-two_implementations.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-wrong_implementation.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim-wrong_implementation.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_jars/mock_ext_sim.jar -------------------------------------------------------------------------------- /src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_no-jars/irrelevant.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ie3-institute/simona/84c3d8eaa27fc20e46ef7f6cf9e15f2dac7d8912/src/test/resources/edu/ie3/simona/sim/setup/ext-sim-loader/_no-jars/irrelevant.txt -------------------------------------------------------------------------------- /src/test/resources/log4j2-it.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/event/listener/RuntimeEventListenerSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event.listener 8 | 9 | import edu.ie3.simona.config.RuntimeConfig 10 | import edu.ie3.simona.event.RuntimeEvent 11 | import edu.ie3.simona.event.RuntimeEvent.{Done, Error, Initializing, Simulating} 12 | import edu.ie3.simona.test.common.UnitSpec 13 | import org.apache.pekko.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit 14 | 15 | import java.util.concurrent.{LinkedBlockingQueue, TimeUnit} 16 | 17 | class RuntimeEventListenerSpec 18 | extends ScalaTestWithActorTestKit 19 | with UnitSpec 20 | with RuntimeTestData { 21 | 22 | "A runtime event listener" must { 23 | "add a valid runtime event to the blocking queue for further processing" in { 24 | val eventQueue = new LinkedBlockingQueue[RuntimeEvent]() 25 | 26 | val listenerRef = spawn( 27 | RuntimeEventListener( 28 | RuntimeConfig.Listener( 29 | None, 30 | None, 31 | ), 32 | Some(eventQueue), 33 | startDateTimeString, 34 | ) 35 | ) 36 | 37 | // valid runtime events 38 | val eventsToQueue: Seq[RuntimeEvent] = List( 39 | Initializing, 40 | Simulating(currentTick, 0), 41 | Done(endTick, duration, errorInSim = false), 42 | Error(errMsg), 43 | ) 44 | 45 | for (event <- eventsToQueue) { 46 | listenerRef ! event 47 | val actualEvent = eventQueue.poll(10, TimeUnit.SECONDS) 48 | actualEvent match { 49 | case Initializing => 50 | case _: Simulating => 51 | case _: Done => 52 | case _: Error => 53 | case _ => fail() 54 | } 55 | } 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/event/listener/RuntimeTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.event.listener 8 | 9 | /** Test data used in multiple tests of [[RuntimeEventListener]] 10 | */ 11 | trait RuntimeTestData { 12 | 13 | protected val startDateTimeString: String = "2011-01-01T00:00:00Z" 14 | protected val endTick: Long = 3600 15 | 16 | /** Duration in milliseconds that is used in some of 17 | * [[edu.ie3.simona.event.RuntimeEvent]] 18 | */ 19 | protected val duration: Long = 10805000 20 | protected val errMsg: String = "testing error msg" 21 | 22 | protected val currentTick: Long = 0 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/integration/common/IntegrationSpecCommon.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.integration.common 8 | 9 | trait IntegrationSpecCommon { 10 | 11 | /* ATTENTION: Do not change this file to a path within "input". If you come to this point because the CI 12 | * or some of your tests are failing you very likely have altered the vn_simona.conf. This config although 13 | * is NOT meant to be altered. Instead, you should always use a delta config and only override the values and 14 | * files of vn_simona/vn_simona.conf. Delta configs can be created by including the config you want to change 15 | * parameters from via include (e.g. include "input/samples/vn_simona/vn_simona.conf") at the 16 | * beginning of your config file and then just override the parameters you want to change! */ 17 | val configFile: String = "input/samples/vn_simona/vn_simona.conf" 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/em/EmAggregateSimpleSumSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.em 8 | 9 | import edu.ie3.datamodel.models.input.system.SystemParticipantInput 10 | import edu.ie3.simona.ontology.messages.flex.MinMaxFlexOptions 11 | import edu.ie3.simona.test.common.UnitSpec 12 | import org.scalatestplus.mockito.MockitoSugar 13 | import squants.energy.Kilowatts 14 | 15 | class EmAggregateSimpleSumSpec extends UnitSpec with MockitoSugar { 16 | 17 | "The simple sum aggregating strategy" should { 18 | 19 | "calculate ref, min and max power correctly" in { 20 | val flexOptions1 = MinMaxFlexOptions( 21 | ref = Kilowatts(6.0), 22 | min = Kilowatts(4.0), 23 | max = Kilowatts(12.0), 24 | ) 25 | 26 | val flexOptions2 = MinMaxFlexOptions( 27 | ref = Kilowatts(2.0), 28 | min = Kilowatts(-2.0), 29 | max = Kilowatts(2.0), 30 | ) 31 | 32 | val actualResult = EmAggregateSimpleSum.aggregateFlexOptions( 33 | Iterable( 34 | (mock[SystemParticipantInput], flexOptions1), 35 | (mock[SystemParticipantInput], flexOptions2), 36 | ) 37 | ) 38 | 39 | actualResult shouldBe MinMaxFlexOptions( 40 | Kilowatts(8.0), 41 | Kilowatts(2.0), 42 | Kilowatts(14.0), 43 | ) 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/grid/TransformerTappingModelSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.grid 8 | 9 | import edu.ie3.simona.test.common.UnitSpec 10 | 11 | /** //ToDo: Class Description 12 | * 13 | * @version 0.1 14 | * @since 09.09.19 15 | */ 16 | class TransformerTappingModelSpec extends UnitSpec { 17 | 18 | // todo CK 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/participant/PvModelITSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant 8 | 9 | import edu.ie3.simona.test.common.UnitSpec 10 | import edu.ie3.simona.util.TickUtil.RichZonedDateTime 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.energy.{Megawatts, Power} 13 | 14 | /** A simple integration test that uses pre-calculated data to check if the pv 15 | * model works as expected. It uses 8 pv models located in GER. 16 | */ 17 | 18 | class PvModelITSpec extends Matchers with UnitSpec with PvModelITHelper { 19 | 20 | private implicit val tolerance: Power = Megawatts(1e-14) 21 | 22 | "The photovoltaic model" should { 23 | "match the expected results for all 8 PV panels over the whole year" in { 24 | val pvModels = createPvModels() 25 | val weatherMap = getWeatherData 26 | val resultsMap = getResultsData 27 | 28 | val modelIds = pvModels.keys.toList.sorted 29 | val keyList = weatherMap.keys.toList.sorted 30 | 31 | keyList.foreach { dateTime => 32 | val modelToWeatherMap = weatherMap(dateTime) 33 | 34 | modelIds.map { modelId => 35 | val model = pvModels(modelId) 36 | val weather = modelToWeatherMap(modelId) 37 | val pvState = PvModel.PvState( 38 | dateTime.toTick, 39 | dateTime, 40 | weather.diffIrr, 41 | weather.dirIrr, 42 | ) 43 | 44 | val calc = model.determineOperatingPoint(pvState) match { 45 | case (op, _) => op.activePower 46 | } 47 | 48 | val sol = resultsMap(dateTime)(modelId) 49 | 50 | calc should approximate(sol) 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/participant/evcs/MockEvcsChargingProperties.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.evcs 8 | import edu.ie3.datamodel.models.ElectricCurrentType 9 | import squants.Power 10 | import squants.energy.Kilowatts 11 | 12 | object MockEvcsChargingProperties extends EvcsChargingProperties { 13 | 14 | override protected val pRated: Power = Kilowatts(43) 15 | override val currentType: ElectricCurrentType = ElectricCurrentType.AC 16 | override val lowestEvSoc: Double = 0.2 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/participant/load/FixedLoadModelSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.participant.load 8 | 9 | import edu.ie3.simona.config.RuntimeConfig.LoadRuntimeConfig 10 | import edu.ie3.simona.model.participant.ParticipantModel.FixedState 11 | import edu.ie3.simona.test.common.UnitSpec 12 | import edu.ie3.simona.test.common.input.LoadInputTestData 13 | import squants.Power 14 | import squants.energy.Watts 15 | 16 | class FixedLoadModelSpec extends UnitSpec with LoadInputTestData { 17 | 18 | private implicit val tolerance: Power = Watts(1e-2) 19 | 20 | "A fixed load model" should { 21 | 22 | "return the desired power in 1,000 calculations" in { 23 | 24 | val cases = Table( 25 | ("reference", "expectedPower"), 26 | ("power", Watts(268.6)), 27 | ("energy", Watts(342.47)), 28 | ) 29 | 30 | forAll(cases) { (reference, expectedPower) => 31 | val config = LoadRuntimeConfig( 32 | modelBehaviour = "fixed", 33 | reference = reference, 34 | ) 35 | 36 | val model = FixedLoadModel 37 | .Factory( 38 | loadInput, 39 | config, 40 | ) 41 | .create() 42 | 43 | (0 until 1000).foreach { tick => 44 | val (operatingPoint, nextTick) = model.determineOperatingPoint( 45 | FixedState(tick) 46 | ) 47 | 48 | operatingPoint.activePower should approximate(expectedPower) 49 | operatingPoint.reactivePower shouldBe None 50 | nextTick shouldBe None 51 | } 52 | 53 | } 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.thermal 8 | 9 | import edu.ie3.datamodel.models.StandardUnits 10 | import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput 11 | import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseState 12 | import squants.thermal.Celsius 13 | import tech.units.indriya.quantity.Quantities.getQuantity 14 | import tech.units.indriya.unit.Units 15 | 16 | import java.util.UUID 17 | 18 | trait ThermalHouseTestData extends ThermalGridTestData { 19 | protected val thermalHouseInput: ThermalHouseInput = new ThermalHouseInput( 20 | UUID.randomUUID(), 21 | "Thermal House", 22 | thermalBusInput, 23 | getQuantity(0.05, StandardUnits.THERMAL_TRANSMISSION), 24 | getQuantity(15.0, StandardUnits.HEAT_CAPACITY), 25 | getQuantity(19d, Units.CELSIUS), 26 | getQuantity(21d, Units.CELSIUS), 27 | getQuantity(18d, Units.CELSIUS), 28 | "house", 29 | 2.0, 30 | ) 31 | 32 | protected val thermalHouse: ThermalHouse = ThermalHouse(thermalHouseInput) 33 | 34 | protected val expectedHouseStartingState: ThermalHouseState = 35 | ThermalHouseState( 36 | 0L, 37 | testGridAmbientTemperature, 38 | Celsius(19d), 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/model/thermal/ThermalStorageTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.model.thermal 8 | 9 | import edu.ie3.datamodel.models.StandardUnits 10 | import edu.ie3.datamodel.models.input.thermal.{ 11 | CylindricalStorageInput, 12 | ThermalBusInput, 13 | } 14 | import edu.ie3.util.quantities.PowerSystemUnits 15 | import tech.units.indriya.quantity.Quantities.getQuantity 16 | 17 | import java.util.UUID 18 | 19 | trait ThermalStorageTestData extends ThermalGridTestData { 20 | protected val thermalStorageInput: CylindricalStorageInput = 21 | new CylindricalStorageInput( 22 | UUID.randomUUID(), 23 | "ThermalStorage", 24 | new ThermalBusInput( 25 | UUID.fromString("ad2db5ab-8f90-4bc1-aa2c-30b31b843ab2"), 26 | "TestThermalBus", 27 | ), 28 | getQuantity(100, StandardUnits.VOLUME), 29 | getQuantity(30, StandardUnits.TEMPERATURE), 30 | getQuantity(40, StandardUnits.TEMPERATURE), 31 | getQuantity(1.15, StandardUnits.SPECIFIC_HEAT_CAPACITY), 32 | getQuantity(20.0, PowerSystemUnits.KILOWATT), 33 | ) 34 | 35 | protected val thermalStorage: CylindricalThermalStorage = 36 | CylindricalThermalStorage(thermalStorageInput) 37 | 38 | protected val expectedStorageStartingState 39 | : ThermalStorage.ThermalStorageState = thermalStorage.startingState 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/ontology/messages/flex/MinMaxFlexOptionsSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.ontology.messages.flex 8 | 9 | import edu.ie3.simona.exceptions.CriticalFailureException 10 | import edu.ie3.simona.test.common.UnitSpec 11 | import squants.energy.Watts 12 | 13 | class MinMaxFlexOptionsSpec extends UnitSpec { 14 | 15 | "Creating a ProvideMinMaxFlexibilityMessage" should { 16 | 17 | "succeed if there is no flexibility" in { 18 | val res = MinMaxFlexOptions.noFlexOption(power = Watts(1)) 19 | 20 | res.ref shouldBe Watts(1) 21 | res.min shouldBe Watts(1) 22 | res.max shouldBe Watts(1) 23 | } 24 | 25 | "succeed if minimum, reference and maximum power are in order" in { 26 | val res = MinMaxFlexOptions( 27 | ref = Watts(1), 28 | min = Watts(0), 29 | max = Watts(2), 30 | ) 31 | 32 | res.ref shouldBe Watts(1) 33 | res.min shouldBe Watts(0) 34 | res.max shouldBe Watts(2) 35 | } 36 | 37 | "throw an exception if minimum power is greater then reference power" in { 38 | intercept[CriticalFailureException] { 39 | MinMaxFlexOptions( 40 | ref = Watts(1), 41 | min = Watts(2), 42 | max = Watts(2), 43 | ) 44 | }.getMessage should include("is greater than reference power") 45 | } 46 | 47 | "throw an exception if reference power is greater then maximum power" in { 48 | intercept[CriticalFailureException] { 49 | MinMaxFlexOptions( 50 | ref = Watts(1), 51 | min = Watts(1), 52 | max = Watts(0), 53 | ) 54 | }.getMessage should include("is greater than maximum power") 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/service/DataSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.service 8 | 9 | import edu.ie3.simona.service.Data.PrimaryData._ 10 | import edu.ie3.simona.test.common.UnitSpec 11 | import edu.ie3.util.scala.quantities.DefaultQuantities._ 12 | import edu.ie3.util.scala.quantities.Kilovars 13 | import squants.energy.Kilowatts 14 | 15 | class DataSpec extends UnitSpec { 16 | 17 | "Meta functions for active power should work as expected" in { 18 | ActivePowerExtra.zero shouldBe ActivePower(zeroKW) 19 | 20 | ActivePowerExtra.scale( 21 | ActivePower(Kilowatts(5)), 22 | 2.5, 23 | ) shouldBe ActivePower(Kilowatts(12.5)) 24 | } 25 | 26 | "Meta functions for complex power should work as expected" in { 27 | ComplexPowerExtra.zero shouldBe ComplexPower(zeroKW, zeroKVAr) 28 | 29 | ComplexPowerExtra.scale( 30 | ComplexPower(Kilowatts(5), Kilovars(2)), 31 | 1.5, 32 | ) shouldBe ComplexPower(Kilowatts(7.5), Kilovars(3)) 33 | } 34 | 35 | "Meta functions for active power and heat should work as expected" in { 36 | ActivePowerAndHeatExtra.zero shouldBe ActivePowerAndHeat(zeroKW, zeroKW) 37 | 38 | ActivePowerAndHeatExtra.scale( 39 | ActivePowerAndHeat(Kilowatts(5), Kilowatts(2)), 40 | 2, 41 | ) shouldBe ActivePowerAndHeat(Kilowatts(10), Kilowatts(4)) 42 | } 43 | 44 | "Meta functions for complex power and heat should work as expected" in { 45 | ComplexPowerAndHeatExtra.zero shouldBe 46 | ComplexPowerAndHeat(zeroKW, zeroKVAr, zeroKW) 47 | 48 | ComplexPowerAndHeatExtra.scale( 49 | ComplexPowerAndHeat(Kilowatts(5), Kilovars(1), Kilowatts(2)), 50 | 3, 51 | ) shouldBe ComplexPowerAndHeat(Kilowatts(15), Kilovars(3), Kilowatts(6)) 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/service/load/LoadProfileSourcesSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2025. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.service.load 8 | 9 | import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile 10 | import edu.ie3.simona.config.ConfigParams.{BaseCsvParams, BaseSqlParams} 11 | import edu.ie3.simona.config.InputConfig.LoadProfile.Datasource 12 | import edu.ie3.simona.test.common.UnitSpec 13 | 14 | import java.nio.file.Paths 15 | 16 | class LoadProfileSourcesSpec extends UnitSpec { 17 | 18 | val baseDirectory: String = 19 | Paths.get(this.getClass.getResource("_it").toURI).toString 20 | 21 | "The LoadProfileSources" should { 22 | val sourceDefinition = Datasource(csvParams = 23 | Some(BaseCsvParams(",", baseDirectory, isHierarchic = false)) 24 | ) 25 | 26 | "build sources correctly" in { 27 | val profileSources = LoadProfileSources.buildSources(sourceDefinition) 28 | 29 | profileSources.size shouldBe 1 30 | profileSources.contains(BdewStandardLoadProfile.G0) shouldBe true 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/KafkaSpecLike.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test 8 | 9 | import com.dimafeng.testcontainers.KafkaContainer 10 | import edu.ie3.simona.test.KafkaSpecLike.Topic 11 | import org.apache.kafka.clients.admin.{Admin, NewTopic} 12 | import org.scalatest.{BeforeAndAfterAll, TestSuite} 13 | import org.testcontainers.utility.DockerImageName 14 | 15 | import java.util.concurrent.TimeUnit 16 | import scala.jdk.CollectionConverters._ 17 | 18 | /** Adapted from 19 | * https://kafka-tutorials.confluent.io/produce-consume-lang/scala.html 20 | */ 21 | trait KafkaSpecLike extends BeforeAndAfterAll { 22 | this: TestSuite => 23 | 24 | protected val testTopics: Seq[Topic] 25 | 26 | protected val kafka: KafkaContainer = KafkaContainer( 27 | DockerImageName.parse("confluentinc/cp-kafka:7.3.1") 28 | ) 29 | protected lazy val admin: Admin = Admin.create( 30 | Map[String, AnyRef]("bootstrap.servers" -> kafka.bootstrapServers).asJava 31 | ) 32 | 33 | override def beforeAll(): Unit = { 34 | super.beforeAll() 35 | kafka.start() 36 | val result = admin.createTopics( 37 | testTopics.map { topic => 38 | new NewTopic( 39 | topic.name, 40 | topic.partitions, 41 | topic.replicationFactor, 42 | ) 43 | }.asJava 44 | ) 45 | 46 | // wait for result, throw exception if applicable 47 | result.all().get(1, TimeUnit.MINUTES) 48 | } 49 | 50 | override def afterAll(): Unit = { 51 | admin.close() 52 | kafka.stop() 53 | super.afterAll() 54 | } 55 | } 56 | 57 | object KafkaSpecLike { 58 | final case class Topic( 59 | name: String, 60 | partitions: Int, 61 | replicationFactor: Short, 62 | ) 63 | } 64 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/ParticipantAgentSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test 8 | 9 | import edu.ie3.simona.test.common.AgentSpec 10 | import org.apache.pekko.actor.ActorSystem 11 | import org.apache.pekko.testkit.TestProbe 12 | 13 | /** Class to help building tests for 14 | * [[edu.ie3.simona.agent.participant.ParticipantAgent]]s 15 | * 16 | * @param actorSystem 17 | * The actor system to use for building actors 18 | */ 19 | class ParticipantAgentSpec(actorSystem: ActorSystem) 20 | extends AgentSpec(actorSystem) { 21 | protected val scheduler: TestProbe = TestProbe("schedulerProbe") 22 | protected val primaryServiceProxy: TestProbe = TestProbe( 23 | "primaryServiceProxyProbe" 24 | ) 25 | protected val weatherService: TestProbe = TestProbe("weatherServiceProbe") 26 | } 27 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/AgentSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import org.apache.pekko.actor.{ActorRef, ActorSystem} 10 | import org.apache.pekko.testkit.ImplicitSender 11 | import com.typesafe.scalalogging.LazyLogging 12 | import org.scalatest.PrivateMethodTester 13 | import org.scalatest.matchers.should 14 | import org.scalatest.wordspec.AnyWordSpecLike 15 | 16 | /** Class to help building tests for agents 17 | * 18 | * @param actorSystem 19 | * The actor system to use for building actors 20 | */ 21 | class AgentSpec(actorSystem: ActorSystem) 22 | extends TestKitWithShutdown(actorSystem) 23 | with ImplicitSender 24 | with AnyWordSpecLike 25 | with should.Matchers 26 | with PrivateMethodTester 27 | with LazyLogging { 28 | 29 | val systemListener: Iterable[ActorRef] = Iterable.empty 30 | } 31 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/EvTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import edu.ie3.simona.test.common.model.MockEvModel 10 | import edu.ie3.util.quantities.PowerSystemUnits 11 | import tech.units.indriya.quantity.Quantities 12 | 13 | import java.util.UUID 14 | 15 | trait EvTestData { 16 | protected val evA: MockEvModel = new MockEvModel( 17 | UUID.fromString("0-0-0-0-a"), 18 | "evA", 19 | Quantities.getQuantity(11d, PowerSystemUnits.KILOWATT), 20 | Quantities.getQuantity(11d, PowerSystemUnits.KILOWATT), 21 | Quantities.getQuantity(58d, PowerSystemUnits.KILOWATTHOUR), 22 | 200, 23 | ) 24 | protected val evB: MockEvModel = new MockEvModel( 25 | UUID.fromString("0-0-0-0-b"), 26 | "evB", 27 | Quantities.getQuantity(11d, PowerSystemUnits.KILOWATT), 28 | Quantities.getQuantity(11d, PowerSystemUnits.KILOWATT), 29 | Quantities.getQuantity(80d, PowerSystemUnits.KILOWATTHOUR), 30 | 200, 31 | ) 32 | protected val evC: MockEvModel = new MockEvModel( 33 | UUID.fromString("0-0-0-0-c"), 34 | "evC", 35 | Quantities.getQuantity(22d, PowerSystemUnits.KILOWATT), 36 | Quantities.getQuantity(22d, PowerSystemUnits.KILOWATT), 37 | Quantities.getQuantity(120d, PowerSystemUnits.KILOWATTHOUR), 38 | 200, 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/IOTestCommons.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import java.io.File 10 | 11 | /** Common I/O information that should be used for tests e.g. default 12 | * directories etc. 13 | * 14 | * @version 0.1 15 | * @since 05.03.20 16 | */ 17 | trait IOTestCommons { 18 | 19 | protected val testTmpDir: String = System.getProperty( 20 | "user.dir" 21 | ) + File.separator + "test" + File.separator + "tmp_" + this.getClass.getSimpleName 22 | 23 | def createDir(dir: String): Boolean = new File(dir).mkdirs() 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/SilentTestEventListener.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import org.apache.pekko.event.Logging.{Debug, Error, Info, Warning, simpleName} 10 | import org.apache.pekko.testkit.TestEventListener 11 | import com.typesafe.scalalogging.LazyLogging 12 | 13 | /** Does the same as TestEventListener but without polluting console logs. If 14 | * the log should be enabled for debug purposes adapt resources/log4j2-test.xml 15 | * and set '' level to the prefered log 16 | * level 17 | */ 18 | class SilentTestEventListener extends TestEventListener with LazyLogging { 19 | 20 | override def print(event: Any): Unit = 21 | event match { 22 | case e: Error => logger.error(e.logSource + ": {}", e.message) 23 | case e: Warning => logger.warn(e.logSource + ": {}", e.message) 24 | case e: Info => logger.info(e.logSource + ": {}", e.message) 25 | case e: Debug => logger.debug(e.logSource + ": {}", e.message) 26 | case e => 27 | warning( 28 | Warning( 29 | simpleName(this), 30 | this.getClass, 31 | "received unexpected event of class " + e.getClass + ": " + e, 32 | ) 33 | ) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/TestKitWithShutdown.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import edu.ie3.simona.event.listener.DeadLetterListener 10 | import org.apache.pekko.actor.{ActorSystem, DeadLetter} 11 | import org.apache.pekko.testkit.TestKit 12 | import org.scalatest.BeforeAndAfterAll 13 | 14 | class TestKitWithShutdown(actorSystem: ActorSystem) 15 | extends TestKit(actorSystem) 16 | with UnitSpec 17 | with BeforeAndAfterAll { 18 | 19 | override protected def beforeAll(): Unit = { 20 | super.beforeAll() 21 | // Listen to dead letter office 22 | val deadLetterListener = system.actorOf(DeadLetterListener.props()) 23 | system.eventStream.subscribe(deadLetterListener, classOf[DeadLetter]) 24 | } 25 | 26 | override protected def afterAll(): Unit = { 27 | TestKit.shutdownActorSystem(system) 28 | super.afterAll() 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/TestSpawnerTyped.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import org.apache.pekko.actor.testkit.typed.scaladsl.ActorTestKitBase 10 | import org.apache.pekko.actor.typed.{ActorRef, Behavior} 11 | import edu.ie3.simona.scheduler.ScheduleLock.Spawner 12 | 13 | trait TestSpawnerTyped { 14 | this: ActorTestKitBase => 15 | 16 | object TSpawner extends Spawner { 17 | override def spawn[T](behavior: Behavior[T]): ActorRef[T] = 18 | TestSpawnerTyped.this.spawn(behavior) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/UnitSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common 8 | 9 | import com.typesafe.scalalogging.LazyLogging 10 | import edu.ie3.simona.test.matchers.{ 11 | DoubleMatchers, 12 | QuantityMatchers, 13 | SquantsMatchers, 14 | } 15 | import edu.ie3.util.scala.quantities.{QuantityUtil => PSQuantityUtil} 16 | import org.apache.pekko.actor.testkit.typed.scaladsl.LogCapturing 17 | import org.scalatest._ 18 | import org.scalatest.matchers.should 19 | import org.scalatest.prop.TableDrivenPropertyChecks 20 | import org.scalatest.wordspec.AnyWordSpecLike 21 | 22 | import java.util.Locale 23 | 24 | /** Base class to be used with all scala unit tests. All data that should be 25 | * commonly available to all unit tests should be placed here instead of mixing 26 | * a lot of traits together. See 27 | * http://www.scalatest.org/user_guide/defining_base_classes 28 | * 29 | * @version 0.1 30 | * @since 2019-09-08 31 | */ 32 | trait UnitSpec 33 | extends should.Matchers 34 | with QuantityMatchers 35 | with SquantsMatchers 36 | with DoubleMatchers 37 | with AnyWordSpecLike 38 | with LogCapturing 39 | with OptionValues 40 | with Inside 41 | with Inspectors 42 | with PrivateMethodTester 43 | with TableDrivenPropertyChecks 44 | with LazyLogging 45 | with TryValues 46 | with AppendedClues { 47 | /* Set default locale in order to ensure proper number parsing - among others */ 48 | Locale.setDefault(Locale.ENGLISH) 49 | 50 | /* The quantity library cannot handle scala's BigDecimal by default. Therefore, adjust the number system to use */ 51 | PSQuantityUtil.adjustNumberSystem() 52 | } 53 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/exceptions/InvalidTestDataException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.exceptions 8 | 9 | /** Indicates an error with test data 10 | * 11 | * @param message 12 | * Error message to provide to the end user 13 | */ 14 | final case class InvalidTestDataException(message: String) 15 | extends Exception(message) { 16 | 17 | def this(message: String, cause: Throwable) = { 18 | this(message) 19 | initCause(cause) 20 | } 21 | 22 | def this(cause: Throwable) = { 23 | this(Option(cause).map(_.toString).orNull, cause) 24 | } 25 | 26 | def this() = { 27 | this(null: String) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/input/FixedFeedInputTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.input 8 | 9 | import java.util.UUID 10 | 11 | import edu.ie3.datamodel.models.OperationTime 12 | import edu.ie3.datamodel.models.input.OperatorInput 13 | import edu.ie3.datamodel.models.input.system.FixedFeedInInput 14 | import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed 15 | import edu.ie3.util.quantities.PowerSystemUnits.VOLTAMPERE 16 | import tech.units.indriya.quantity.Quantities 17 | 18 | /** //ToDo: Class Description 19 | * 20 | * @version 0.1 21 | * @since 23.06.20 22 | */ 23 | trait FixedFeedInputTestData extends NodeInputTestData { 24 | val fixedFeedInput = 25 | new FixedFeedInInput( 26 | UUID.fromString("9abe950d-362e-4efe-b686-500f84d8f368"), 27 | "testFixedFeed", 28 | OperatorInput.NO_OPERATOR_ASSIGNED, 29 | OperationTime.notLimited(), 30 | nodeInputNoSlackNs04KvA, 31 | new CosPhiFixed("cosPhiFixed:{(0.0,0.95)}"), 32 | null, 33 | Quantities.getQuantity(282.74d, VOLTAMPERE), 34 | 0.95, 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/input/StorageInputTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.input 8 | 9 | import edu.ie3.datamodel.models.OperationTime 10 | import edu.ie3.datamodel.models.input.OperatorInput 11 | import edu.ie3.datamodel.models.input.system.StorageInput 12 | import edu.ie3.datamodel.models.input.system.`type`.StorageTypeInput 13 | import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed 14 | import edu.ie3.simona.test.common.DefaultTestData 15 | import edu.ie3.util.quantities.PowerSystemUnits._ 16 | import tech.units.indriya.quantity.Quantities 17 | 18 | import java.util.UUID 19 | 20 | trait StorageInputTestData extends DefaultTestData with NodeInputTestData { 21 | 22 | protected val storageTypeInput = new StorageTypeInput( 23 | UUID.fromString("fbee4995-24dd-45e4-9c85-7d986fe99ff3"), 24 | "Dummy_StorageTypeInput", 25 | Quantities.getQuantity(15000d, EURO), 26 | Quantities.getQuantity(0.05d, EURO_PER_MEGAWATTHOUR), 27 | Quantities.getQuantity(200d, KILOWATTHOUR), 28 | Quantities.getQuantity(13d, KILOVOLTAMPERE), 29 | 0.997, 30 | Quantities.getQuantity(12.961, KILOWATT), 31 | Quantities.getQuantity(0.03, PU_PER_HOUR), 32 | Quantities.getQuantity(0.92, PU), 33 | ) 34 | 35 | protected val storageInput = new StorageInput( 36 | UUID.randomUUID(), 37 | "Dummy_StorageInput", 38 | new OperatorInput(UUID.randomUUID(), "NO_OPERATOR"), 39 | OperationTime.notLimited(), 40 | nodeInputNoSlackNs04KvA, 41 | CosPhiFixed.CONSTANT_CHARACTERISTIC, 42 | null, 43 | storageTypeInput, 44 | ) 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/input/SwitchInputTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.input 8 | 9 | import java.util.UUID 10 | 11 | import edu.ie3.datamodel.models.input.OperatorInput 12 | import edu.ie3.datamodel.models.input.connector.SwitchInput 13 | import edu.ie3.simona.test.common.DefaultTestData 14 | 15 | /** //ToDo: Class Description 16 | * 17 | * @version 0.1 18 | * @since 23.06.20 19 | */ 20 | trait SwitchInputTestData extends NodeInputTestData with DefaultTestData { 21 | 22 | protected val switchInput: SwitchInput = new SwitchInput( 23 | UUID.fromString("60b15606-cd88-4434-9f33-99fcf4fdafcc"), 24 | "SimpleTestSwitch", 25 | OperatorInput.NO_OPERATOR_ASSIGNED, 26 | defaultOperationTime, 27 | nodeInputNoSlackNs04KvA, 28 | nodeInputNoSlackNs04KvB, 29 | true, 30 | ) 31 | 32 | protected val loopSwitchInput: SwitchInput = new SwitchInput( 33 | UUID.fromString("60b15606-cd88-4434-9f33-99fcf4fdafcc"), 34 | "SimpleTestSwitch", 35 | OperatorInput.NO_OPERATOR_ASSIGNED, 36 | defaultOperationTime, 37 | nodeInputNoSlackNs04KvA, 38 | nodeInputNoSlackNs04KvA, 39 | true, 40 | ) 41 | 42 | protected val invalidSwitchInput: SwitchInput = new SwitchInput( 43 | UUID.fromString("a66e1c49-ca76-4f1e-9cce-a38da3ea7ace"), 44 | "SimpleTestSwitch", 45 | OperatorInput.NO_OPERATOR_ASSIGNED, 46 | defaultOperationTime, 47 | nodeInputNoSlackNs04KvA, 48 | nodeInputNoSlackMs10Kv, 49 | true, 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/input/TimeSeriesTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.input 8 | 9 | import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation 10 | import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme 11 | 12 | import java.nio.file.Paths 13 | import java.util.UUID 14 | 15 | trait TimeSeriesTestData { 16 | protected val uuidP: UUID = 17 | UUID.fromString("9185b8c1-86ba-4a16-8dea-5ac898e8caa5") 18 | protected val uuidPq: UUID = 19 | UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26") 20 | protected val uuidPqh: UUID = 21 | UUID.fromString("46be1e57-e4ed-4ef7-95f1-b2b321cb2047") 22 | 23 | protected val metaP: CsvIndividualTimeSeriesMetaInformation = 24 | new CsvIndividualTimeSeriesMetaInformation( 25 | uuidP, 26 | ColumnScheme.ACTIVE_POWER, 27 | Paths.get("its_p_" + uuidP), 28 | ) 29 | protected val metaPq: CsvIndividualTimeSeriesMetaInformation = 30 | new CsvIndividualTimeSeriesMetaInformation( 31 | uuidPq, 32 | ColumnScheme.APPARENT_POWER, 33 | Paths.get("its_pq_" + uuidPq), 34 | ) 35 | protected val metaPqh: CsvIndividualTimeSeriesMetaInformation = 36 | new CsvIndividualTimeSeriesMetaInformation( 37 | uuidPqh, 38 | ColumnScheme.APPARENT_POWER_AND_HEAT_DEMAND, 39 | Paths.get("its_pqh_" + uuidPqh), 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/input/WecInputTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.input 8 | 9 | import edu.ie3.datamodel.models.OperationTime 10 | import edu.ie3.datamodel.models.input.OperatorInput 11 | import edu.ie3.datamodel.models.input.system.WecInput 12 | import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed 13 | 14 | import java.util.UUID 15 | 16 | trait WecInputTestData extends WecTypeInputTestData { 17 | 18 | val wecInputModel = new WecInput( 19 | UUID.randomUUID(), 20 | "Dummy_WecInput", 21 | new OperatorInput(UUID.randomUUID(), "NO_OPERATOR"), 22 | OperationTime.notLimited(), 23 | nodeInputNoSlackNs04KvB, 24 | CosPhiFixed.CONSTANT_CHARACTERISTIC, 25 | null, 26 | wecTypeInputEnerconE82, 27 | false, 28 | ) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/model/participant/LoadTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.model.participant 8 | 9 | import edu.ie3.datamodel.models.OperationTime 10 | import edu.ie3.simona.model.SystemComponent 11 | 12 | import java.time.ZonedDateTime 13 | import edu.ie3.simona.test.common.input.LoadInputTestData 14 | import edu.ie3.util.TimeUtil 15 | import edu.ie3.util.scala.OperationInterval 16 | 17 | /** Trait to supply different test data environments for testing a load agent 18 | */ 19 | trait LoadTestData extends LoadInputTestData { 20 | protected implicit val simulationStartDate: ZonedDateTime = 21 | TimeUtil.withDefaults.toZonedDateTime("2020-01-01T00:00:00Z") 22 | protected val simulationEndDate: ZonedDateTime = 23 | TimeUtil.withDefaults.toZonedDateTime("2020-01-01T01:00:00Z") 24 | protected val operationTime: OperationTime = OperationTime 25 | .builder() 26 | .withStart(simulationStartDate) 27 | .withEnd(simulationEndDate) 28 | .build() 29 | protected val operationInterval: OperationInterval = 30 | SystemComponent.determineOperationInterval( 31 | simulationStartDate, 32 | simulationEndDate, 33 | operationTime, 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/common/model/system/CharacteristicTestData.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.common.model.system 8 | 9 | import edu.ie3.simona.model.system.Characteristic 10 | import edu.ie3.simona.model.system.Characteristic.XYPair 11 | import squants.{Dimensionless, Each} 12 | 13 | import scala.collection.SortedSet 14 | 15 | trait CharacteristicTestData { 16 | protected val xy1: XYPair[Dimensionless, Dimensionless] = 17 | XYPair(Each(1), Each(2)) 18 | protected val xy2: XYPair[Dimensionless, Dimensionless] = 19 | XYPair(Each(2), Each(4)) 20 | protected val xy3: XYPair[Dimensionless, Dimensionless] = 21 | XYPair(Each(3), Each(8)) 22 | protected val xy4: XYPair[Dimensionless, Dimensionless] = 23 | XYPair(Each(4), Each(16)) 24 | protected val xy5: XYPair[Dimensionless, Dimensionless] = 25 | XYPair(Each(5), Each(32)) 26 | 27 | object TestCharacteristic 28 | extends Characteristic[Dimensionless, Dimensionless] { 29 | override protected val xyCoordinates 30 | : SortedSet[XYPair[Dimensionless, Dimensionless]] = 31 | SortedSet.apply(xy1, xy2, xy3, xy4, xy5) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/helper/TableDrivenHelper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.helper 8 | 9 | trait TableDrivenHelper { 10 | 11 | /** Shortcut for Some type to make case tables more concise */ 12 | val S: Some.type = Some 13 | 14 | /** Shortcut for None type to make case tables more concise */ 15 | val N: None.type = None 16 | 17 | /** Shortcut for Seq type to make case tables more concise */ 18 | val L: Seq.type = Seq 19 | } 20 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/helper/TestContainerHelper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2022. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.helper 8 | 9 | import org.apache.pekko.testkit.TestException 10 | import org.testcontainers.utility.MountableFile 11 | 12 | import java.nio.file.Paths 13 | 14 | trait TestContainerHelper { 15 | 16 | /** Retrieve resource with the class' resource loader. In contrast to 17 | * [[org.testcontainers.utility.MountableFile#forClasspathResource(java.lang.String, java.lang.Integer)]], 18 | * this also works with paths relative to the current class (i.e. without 19 | * leading '/'). 20 | * @param resource 21 | * the resource directory or file path 22 | * @return 23 | * a MountableFile to use with test containers 24 | */ 25 | def getMountableFile(resource: String): MountableFile = { 26 | Option(getClass.getResource(resource)) 27 | .map(url => Paths.get(url.toURI)) 28 | .map(MountableFile.forHostPath) 29 | .getOrElse( 30 | throw TestException( 31 | "Resource '" + resource + "' was not found from " + getClass.toString 32 | ) 33 | ) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/matchers/DoubleMatchers.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.matchers 8 | 9 | import org.scalactic.TolerantNumerics 10 | import org.scalatest.matchers.{MatchResult, Matcher} 11 | 12 | trait DoubleMatchers extends TolerantNumerics { 13 | 14 | class DoubleMatcher(right: Double, implicit val tolerance: Double) 15 | extends Matcher[Double] { 16 | private val equality = tolerantDoubleEquality(tolerance) 17 | 18 | override def apply(left: Double): MatchResult = MatchResult( 19 | equality.areEqual(left, right), 20 | s"The values $left and $right differ more than $tolerance in value", 21 | s"The values $left and $right differ less than $tolerance in value", 22 | ) 23 | } 24 | 25 | def approximate(right: Double)(implicit tolerance: Double) = 26 | new DoubleMatcher(right, tolerance) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/matchers/QuantityMatchersSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2021. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.matchers 8 | 9 | import edu.ie3.simona.test.common.UnitSpec 10 | import tech.units.indriya.quantity.Quantities 11 | import tech.units.indriya.unit.Units 12 | 13 | class QuantityMatchersSpec extends UnitSpec { 14 | "Testing quantities with custom quantity matchers" when { 15 | val quant = Quantities.getQuantity(5d, Units.METRE) 16 | val toleranceQuantity = Quantities.getQuantity(1e-10, Units.METRE) 17 | 18 | given testTolerance: Double = 1e-10 19 | 20 | "testing for equality" should { 21 | "pass if quantities are exactly the same" in { 22 | quant should equalWithTolerance(quant) 23 | } 24 | 25 | "pass if quantities are approximately the same" in { 26 | quant should equalWithTolerance( 27 | quant.add(toleranceQuantity.multiply(0.9)) 28 | ) 29 | } 30 | 31 | "detect mismatch on tolerance exceeding" in { 32 | quant should not( 33 | equalWithTolerance(quant.add(toleranceQuantity.multiply(1.1))) 34 | ) 35 | } 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/test/matchers/SquantsMatchers.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2024. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.test.matchers 8 | 9 | import org.scalatest.matchers.{MatchResult, Matcher} 10 | import squants.Quantity 11 | 12 | /** Trait, to simplify test coding, that is reliant on squants */ 13 | trait SquantsMatchers { 14 | class SquantsMatcher[Q <: Quantity[Q]](right: Q, implicit val tolerance: Q) 15 | extends Matcher[Quantity[Q]] { 16 | override def apply(left: Quantity[Q]): MatchResult = MatchResult( 17 | left =~ right, 18 | s"The quantities $left and $right differ more than $tolerance in value", 19 | s"The quantities $left and $right differ less than $tolerance in value", 20 | ) 21 | } 22 | 23 | def approximate[Q <: Quantity[Q]](right: Q)(implicit tolerance: Q) = 24 | new SquantsMatcher(right, tolerance) 25 | } 26 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/util/ActorUtils.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | import org.apache.pekko.actor.testkit.typed.scaladsl.TestProbe 10 | import org.apache.pekko.actor.typed.ActorRef 11 | import edu.ie3.simona.ontology.messages.SchedulerMessage.Completion 12 | import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} 13 | import org.scalatest.matchers.should.Matchers.shouldBe 14 | 15 | object ActorUtils { 16 | implicit class RichActivatedActor( 17 | private val triggeredActor: TestProbe[Activation] 18 | ) { 19 | 20 | def expectActivationAndComplete( 21 | scheduler: ActorRef[SchedulerMessage], 22 | expectedTick: Long, 23 | newTick: Option[Long] = None, 24 | ): Unit = { 25 | val receivedTrigger = 26 | triggeredActor.expectMessageType[Activation] 27 | 28 | receivedTrigger.tick shouldBe expectedTick 29 | 30 | scheduler ! Completion( 31 | triggeredActor.ref, 32 | newTick, 33 | ) 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/simona/util/CollectionUtilsSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2020. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.simona.util 8 | 9 | import edu.ie3.simona.test.common.UnitSpec 10 | import edu.ie3.simona.util.CollectionUtils._ 11 | import squants.Each 12 | import squants.Dimensionless 13 | 14 | class CollectionUtilsSpec extends UnitSpec { 15 | 16 | "The collection utils are capable" should { 17 | "of detecting duplicate entries in a list" in { 18 | val input = List("a", "b", "c", "d", "b") 19 | isUniqueList(input) shouldBe false 20 | } 21 | 22 | "of detecting lists with unique entries" in { 23 | val input = List("a", "b", "c", "d", "e") 24 | isUniqueList(input) shouldBe true 25 | } 26 | 27 | "of computing the closest key-value pairs, given a map and a key" in { 28 | val map = Map.from( 29 | List( 30 | (Each(1d), Each(2d)), 31 | (Each(2d), Each(4d)), 32 | (Each(3d), Each(8d)), 33 | ) 34 | ) 35 | 36 | def returnedSequence1: Seq[ 37 | (Dimensionless, Dimensionless) 38 | ] = closestKeyValuePairs(map, Each(1.5)) 39 | def returnedSequence2: Seq[ 40 | (Dimensionless, Dimensionless) 41 | ] = closestKeyValuePairs(map, Each(2.5)) 42 | def returnedSequence3: Seq[ 43 | (Dimensionless, Dimensionless) 44 | ] = closestKeyValuePairs(map, Each(3d)) 45 | 46 | returnedSequence1 shouldBe Seq( 47 | (Each(1d), Each(2d)), 48 | (Each(2d), Each(4d)), 49 | ) 50 | returnedSequence2 shouldBe Seq( 51 | (Each(2d), Each(4d)), 52 | (Each(3d), Each(8d)), 53 | ) 54 | returnedSequence3 shouldBe Seq((Each(3d), Each(8d))) 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/EnergyDensitySpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.KilowattHoursPerCubicMeter 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.energy.KilowattHours 13 | import squants.space.CubicMeters 14 | 15 | class EnergyDensitySpec extends AnyFlatSpec with Matchers { 16 | 17 | behavior of "EnergyDensityCapacity and its Units of Measure" 18 | 19 | it should "create values using UOM factories" in { 20 | KilowattHoursPerCubicMeter( 21 | 1 22 | ).toKilowattHoursPerCubicMeter should be(1) 23 | } 24 | 25 | it should "properly convert to all supported Units of Measure" in { 26 | val x = KilowattHoursPerCubicMeter(1) 27 | 28 | x.toKilowattHoursPerCubicMeter should be(1) 29 | } 30 | 31 | it should "return properly formatted strings for all supported Units of Measure" in { 32 | KilowattHoursPerCubicMeter(1).toString( 33 | KilowattHoursPerCubicMeter 34 | ) should be("1.0 kWh/m³") 35 | } 36 | 37 | it should "return Energy when multiplied by Volume" in { 38 | KilowattHoursPerCubicMeter(1) * CubicMeters(10) should be( 39 | KilowattHours(10) 40 | ) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/EnergyPriceSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.EuroPerKilowatthour 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.energy.KilowattHours 13 | import squants.market.EUR 14 | 15 | class EnergyPriceSpec extends AnyFlatSpec with Matchers { 16 | 17 | behavior of "EnergyPrice and its Units of Measure" 18 | 19 | it should "create values using UOM factories" in { 20 | EuroPerKilowatthour( 21 | 1 22 | ).toEuroPerKilowattHour should be(1) 23 | } 24 | 25 | it should "properly convert to all supported Units of Measure" in { 26 | val x = EuroPerKilowatthour(1) 27 | 28 | x.toEuroPerKilowattHour should be(1) 29 | } 30 | 31 | it should "return properly formatted strings for all supported Units of Measure" in { 32 | EuroPerKilowatthour(1).toString( 33 | EuroPerKilowatthour 34 | ) should be("1.0 €/kWh") 35 | } 36 | 37 | it should "return Euro when multiplied by Kilowatthour" in { 38 | EuroPerKilowatthour(1) * KilowattHours(10) should be( 39 | EUR(10) 40 | ) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/IrradiationSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.{ 10 | WattHoursPerSquareMeter, 11 | WattsPerSquareMeter, 12 | } 13 | import org.scalatest.flatspec.AnyFlatSpec 14 | import org.scalatest.matchers.should.Matchers 15 | import squants.energy.WattHours 16 | import squants.space.SquareMeters 17 | import squants.time.Hours 18 | 19 | class IrradiationSpec extends AnyFlatSpec with Matchers { 20 | 21 | behavior of "Irradiation and its Units of Measure" 22 | 23 | it should "create values using UOM factories" in { 24 | WattHoursPerSquareMeter( 25 | 1 26 | ).toWattHoursPerSquareMeter should be(1) 27 | } 28 | 29 | it should "properly convert to all supported Units of Measure" in { 30 | val x = WattHoursPerSquareMeter(1) 31 | 32 | x.toWattHoursPerSquareMeter should be(1) 33 | } 34 | 35 | it should "return properly formatted strings for all supported Units of Measure" in { 36 | WattHoursPerSquareMeter(1).toString( 37 | WattHoursPerSquareMeter 38 | ) should be("1.0 Wh/m²") 39 | } 40 | 41 | it should "return Energy when multiplied by Area" in { 42 | WattHoursPerSquareMeter(1) * SquareMeters(10) should be( 43 | WattHours(10) 44 | ) 45 | } 46 | 47 | it should "return Irradiance when divided by Time" in { 48 | WattHoursPerSquareMeter(100) / Hours(10) should be( 49 | WattsPerSquareMeter(10) 50 | ) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/ReactivePowerSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.Vars 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.Each 13 | import squants.energy.Watts 14 | 15 | class ReactivePowerSpec extends AnyFlatSpec with Matchers { 16 | 17 | behavior of "ReactivePower and its Units of Measure" 18 | 19 | it should "create values using UOM factories" in { 20 | Vars( 21 | 1 22 | ).toVars should be(1) 23 | } 24 | 25 | it should "properly convert to all supported Units of Measure" in { 26 | val x = Vars(1) 27 | x.toVars should be(1) 28 | } 29 | 30 | it should "return properly formatted strings for all supported Units of Measure" in { 31 | Vars(1).toString( 32 | Vars 33 | ) should be("1.0 Var") 34 | } 35 | 36 | it should "return Dimensionless when divided by ActivePower" in { 37 | Vars(100) / Watts(10) should be( 38 | Each(10) 39 | ) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/SpecificHeatCapacitySpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.KilowattHoursPerKelvinCubicMeters 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.energy.KilowattHours 13 | import squants.space.CubicMeters 14 | import squants.thermal.{Celsius, Kelvin} 15 | 16 | class SpecificHeatCapacitySpec extends AnyFlatSpec with Matchers { 17 | 18 | behavior of "SpecificHeatCapacity and its Units of Measure" 19 | 20 | it should "create values using UOM factories" in { 21 | KilowattHoursPerKelvinCubicMeters( 22 | 1 23 | ).toKilowattHoursPerKelvinCubicMeters should be(1) 24 | } 25 | 26 | it should "properly convert to all supported Units of Measure" in { 27 | val x = KilowattHoursPerKelvinCubicMeters(1) 28 | 29 | x.toKilowattHoursPerKelvinCubicMeters should be(1) 30 | } 31 | 32 | it should "return properly formatted strings for all supported Units of Measure" in { 33 | KilowattHoursPerKelvinCubicMeters(1).toString( 34 | KilowattHoursPerKelvinCubicMeters 35 | ) should be("1.0 kWh/Km³") 36 | } 37 | 38 | it should "return Energy when multiplied by Temperature delta of 1 Kelvin and Volume" in { 39 | KilowattHoursPerKelvinCubicMeters(1000).calcEnergy( 40 | Kelvin(10), 41 | Kelvin(20), 42 | CubicMeters(5), 43 | ) should be(KilowattHours(50000.0)) 44 | } 45 | 46 | it should "return Energy when multiplied by Temperature delta of 1 degree Celsius and Volume" in { 47 | KilowattHoursPerKelvinCubicMeters(1000).calcEnergy( 48 | Celsius(100), 49 | Celsius(101), 50 | CubicMeters(5), 51 | ) should be(KilowattHours(5000)) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/scala/edu/ie3/util/quantities/ThermalConductanceSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * © 2023. TU Dortmund University, 3 | * Institute of Energy Systems, Energy Efficiency and Energy Economics, 4 | * Research group Distribution grid planning and operation 5 | */ 6 | 7 | package edu.ie3.util.quantities 8 | 9 | import edu.ie3.util.scala.quantities.WattsPerKelvin 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | import squants.Kelvin 13 | import squants.energy.KilowattHours 14 | import squants.thermal.Celsius 15 | import squants.time.Hours 16 | 17 | class ThermalConductanceSpec extends AnyFlatSpec with Matchers { 18 | 19 | behavior of "ThermalConductance and its Units of Measure" 20 | 21 | it should "create values using UOM factories" in { 22 | WattsPerKelvin(1).toWattsPerKelvin should be(1) 23 | } 24 | 25 | it should "properly convert to all supported Units of Measure" in { 26 | val x = WattsPerKelvin(1) 27 | 28 | x.toWattsPerKelvin should be(1) 29 | } 30 | 31 | it should "return properly formatted strings for all supported Units of Measure" in { 32 | WattsPerKelvin(1).toString(WattsPerKelvin) should be("1.0 W/K") 33 | } 34 | 35 | it should "return Energy when multiplied by Temperature in Kelvin and Time" in { 36 | WattsPerKelvin(1000).calcThermalEnergyChange( 37 | Kelvin(10), 38 | Kelvin(0), 39 | Hours(5), 40 | ) should be(KilowattHours(50d)) 41 | } 42 | 43 | it should "return Energy when multiplied by Temperature in Celsius and Time" in { 44 | WattsPerKelvin(1000).calcThermalEnergyChange( 45 | Celsius(10), 46 | Celsius(0), 47 | Hours(5), 48 | ) should be(KilowattHours(50d)) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /version.properties: -------------------------------------------------------------------------------- 1 | #Generated by the Semver Plugin for Gradle 2 | #Fri May 09 22:35:09 CEST 2025 3 | version.buildmeta= 4 | version.major=4 5 | version.minor=1 6 | version.patch=0 7 | version.prerelease= 8 | version.semver=4.1.0 9 | --------------------------------------------------------------------------------