|
|
@@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory
|
|
|
|
|
|
class CosimRunner implements ICosimRunner, Closeable {
|
|
|
|
|
|
- val HashMap<CosimUnitInstance, IFmuInstance> fmuInstanceMap = newHashMap()
|
|
|
+ val HashMap<UnitInstance, IFmuInstance> fmuInstanceMap = newHashMap()
|
|
|
|
|
|
IOutputProcessor outProcessor
|
|
|
|
|
|
@@ -24,37 +24,51 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
fmuLoader = l
|
|
|
}
|
|
|
|
|
|
- override run(RootCandidateScenario scenario, Map<Scenario, List<PrecendenceNode>> scenarioNodesMap, String variantID) {
|
|
|
- Assert.isTrue(scenarioNodesMap.values.forall[sortedNodes | sortedNodes.forall[n1 | scenario.eAllContents.exists[n2 | n1===n2]]])
|
|
|
+ override run(RootCandidateScenario rootScenario, Map<Scenario, List<PrecendenceNode>> scenarioNodesMap, String variantID) {
|
|
|
+ Assert.isTrue(scenarioNodesMap.values.forall[sortedNodes | sortedNodes.forall[n1 | rootScenario.eAllContents.exists[n2 | n1===n2]]])
|
|
|
|
|
|
- val rootScenario = scenarioNodesMap.keySet.filter(RootCandidateScenario).head
|
|
|
val nodes = scenarioNodesMap.get(rootScenario)
|
|
|
|
|
|
- val units = nodes.filter(CosimUnitInstance).toList
|
|
|
+ val units = nodes.filter(UnitInstance).toList
|
|
|
|
|
|
- // Instantiate each fmu, and record the instance reference.
|
|
|
- for (unit : units) {
|
|
|
- val fmuInstance = fmuLoader.instantiate(unit)
|
|
|
+ // Instantiate each unit, and record the instance reference.
|
|
|
+ for (unit : units) {
|
|
|
+ val fmuInstance = fmuLoader.instantiate(unit, scenarioNodesMap)
|
|
|
logger.debug("Unit {} instantiated", unit)
|
|
|
|
|
|
+ fmuInstanceMap.put(unit, fmuInstance)
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO Mode these to protected methods of this class.
|
|
|
+ // setup experiment
|
|
|
+ for (unit: units){
|
|
|
+ val fmuInstance = fmuInstanceMap.get(unit)
|
|
|
fmuInstance.setupExperiment()
|
|
|
logger.debug("Unit {} experiment setup", unit)
|
|
|
|
|
|
// TODO Set the configured parameter values.
|
|
|
-
|
|
|
- // Go into init mode
|
|
|
+ }
|
|
|
+
|
|
|
+ // Go into init mode
|
|
|
+ for (unit: units){
|
|
|
+ val fmuInstance = fmuInstanceMap.get(unit)
|
|
|
fmuInstance.enterInitializationMode()
|
|
|
logger.debug("Unit {} enter initialization mode", unit)
|
|
|
-
|
|
|
- fmuInstanceMap.put(unit, fmuInstance)
|
|
|
}
|
|
|
|
|
|
// Fixpoint initial values, by following the same order of get.values as specified in nodes.
|
|
|
// Uses a map to store the previous value of each output. Then, whenever a new value of that output is obtained, checks if is the same as the previous value.
|
|
|
val outVals = newHashMap()
|
|
|
- val outputPorts = nodes.filter(OutputPortInstance).toList
|
|
|
+ // Takes into account hierarchical unit ports.
|
|
|
+ val childOutputPorts = nodes.filter(OutputPortInstance).filter[
|
|
|
+ if (it instanceof HierarchicalUnitPort){
|
|
|
+ ! it.isInput
|
|
|
+ } else {
|
|
|
+ true
|
|
|
+ }
|
|
|
+ ].toList
|
|
|
// Initialize
|
|
|
- for (out : outputPorts){
|
|
|
+ for (out : childOutputPorts){
|
|
|
outVals.put(out, Double.POSITIVE_INFINITY)
|
|
|
logger.debug("Output port {}.{} initialized to infinity", out.unit.identifier, out.identifier)
|
|
|
}
|
|
|
@@ -68,7 +82,8 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
while (!converged && i<MAX_IT){
|
|
|
logger.debug("Iteration {} start.", i)
|
|
|
converged = true
|
|
|
- for (out : outputPorts){
|
|
|
+ for (out : childOutputPorts){
|
|
|
+ // TODO The getReal method of the hierarchical units needs to pull the latest value from the internal unit.
|
|
|
val outV = fmuInstanceMap.get(out.unit).getReal(out.identifier)
|
|
|
logger.debug("GetReal {}.{} at iteration {} yields {}.", out.unit.identifier, out.identifier, i, outV)
|
|
|
// Check if outV has changed.
|
|
|
@@ -81,6 +96,7 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
// Propagate outV to inputs.
|
|
|
// TODO: Take types into account. For now we assume everything is real.
|
|
|
for (trgPort : out.valueTo){
|
|
|
+ // TODO The set real method of the hierarchical unit will propagate the values to the internal units, and trigger a full propagation of the effects. This is only during the init mode
|
|
|
fmuInstanceMap.get(trgPort.unit).setReal(trgPort.identifier, outV)
|
|
|
logger.debug("SetReal {}.{} to {} at iteration {}.", trgPort.unit.identifier, trgPort.identifier, outV, i)
|
|
|
}
|
|
|
@@ -94,10 +110,11 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
}
|
|
|
|
|
|
// Init output processor with experiment parameters
|
|
|
- outProcessor.initialize(scenario, variantID)
|
|
|
+ outProcessor.initialize(rootScenario, variantID)
|
|
|
logger.debug("Output processor initialized.")
|
|
|
|
|
|
// Add first line
|
|
|
+ // TODO gather all the outputs from ALL output ports.
|
|
|
outProcessor.setOutputs(0, 0.0, outVals)
|
|
|
logger.debug("Output line recorded for time {}.", 0.0)
|
|
|
|
|
|
@@ -109,8 +126,8 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
|
|
|
// Run the co-sim scenario
|
|
|
var time = 0.0d
|
|
|
- val stepSize = scenario.stepSize
|
|
|
- val stopTime = scenario.stopTime
|
|
|
+ val stepSize = rootScenario.stepSize
|
|
|
+ val stopTime = rootScenario.stopTime
|
|
|
i = 0
|
|
|
while (time < stopTime || MathUtils.isApproximatelyEqual(time, stopTime, stepSize*1e-3)){
|
|
|
logger.debug("Co-simulation step start at time {} -> {}.", time, time + stepSize)
|
|
|
@@ -156,7 +173,8 @@ class CosimRunner implements ICosimRunner, Closeable {
|
|
|
// If traceOutput is enabled, we print every value set to the fmu, and the time at which it was set.
|
|
|
|
|
|
// Refresh outputs
|
|
|
- for (n : outputPorts) {
|
|
|
+ // TODO Get ALL OUTPUT Ports.
|
|
|
+ for (n : childOutputPorts) {
|
|
|
val outV = fmuInstanceMap.get(n.unit).getReal(n.identifier)
|
|
|
logger.debug("GetReal {}.{} at time {} yields {}.", n.unit.identifier, n.identifier, time, outV)
|
|
|
outVals.put(n, outV)
|