Просмотр исходного кода

support for hierarchical cosim

Claudio Gomes 7 лет назад
Родитель
Сommit
03aaa12511
26 измененных файлов с 1041 добавлено и 232 удалено
  1. 15 30
      HintCO/instances/execute_cosim_test_watertanks.xmi
  2. 110 0
      HintCO/instances/execute_deephier_cosim_test_watertanks.xmi
  3. 82 0
      HintCO/instances/execute_hier_cosim_test_watertanks.xmi
  4. 18 0
      HintCO/model/Candidates.xcore
  5. 181 10
      HintCO/src-gen/ua/ansymo/hintco/HintcoPackage.java
  6. 9 0
      HintCO/src-gen/ua/ansymo/hintco/InputPortInstance.java
  7. 9 0
      HintCO/src-gen/ua/ansymo/hintco/OutputPortInstance.java
  8. 9 0
      HintCO/src-gen/ua/ansymo/hintco/PortInstance.java
  9. 18 0
      HintCO/src-gen/ua/ansymo/hintco/UnitInstance.java
  10. 40 0
      HintCO/src-gen/ua/ansymo/hintco/impl/HierarchicalCosimUnitImpl.java
  11. 29 0
      HintCO/src-gen/ua/ansymo/hintco/impl/HierarchicalUnitPortImpl.java
  12. 61 1
      HintCO/src-gen/ua/ansymo/hintco/impl/HintcoPackageImpl.java
  13. 12 0
      HintCO/src-gen/ua/ansymo/hintco/impl/InputPortInstanceImpl.java
  14. 42 0
      HintCO/src-gen/ua/ansymo/hintco/impl/OutputPortInstanceImpl.java
  15. 11 0
      HintCO/src-gen/ua/ansymo/hintco/impl/PortInstanceImpl.java
  16. 42 0
      HintCO/src-gen/ua/ansymo/hintco/impl/UnitInstanceImpl.java
  17. 41 14
      HintCO/src/ua/ansymo/hintco/AdaptedFMUInstance.xtend
  18. 1 5
      HintCO/src/ua/ansymo/hintco/CandidatesGenerator.xtend
  19. 138 0
      HintCO/src/ua/ansymo/hintco/CosimRunUtils.xtend
  20. 20 120
      HintCO/src/ua/ansymo/hintco/CosimRunner.xtend
  21. 5 9
      HintCO/src/ua/ansymo/hintco/FmuInstance.xtend
  22. 0 1
      HintCO/src/ua/ansymo/hintco/FmuLoader.xtend
  23. 71 32
      HintCO/src/ua/ansymo/hintco/HierarchicalInstance.xtend
  24. 2 0
      HintCO/src/ua/ansymo/hintco/IFmuInstance.xtend
  25. 5 6
      HintCO/src/ua/ansymo/hintco/OutputProcessor.xtend
  26. 70 4
      HintCO/test/ua/ansymo/hintco/test/CosimRunnerTest.xtend

+ 15 - 30
HintCO/instances/execute_cosim_test_watertanks.xmi

@@ -9,80 +9,65 @@
       stopTime="10.0"
       stepSize="0.01"
       outputStepSize="0.01">
-    <cosimunits
- xsi:type="hintco:CosimUnitInstance"
+    <cosimunits
+        xsi:type="hintco:CosimUnitInstance"
         identifier="ctrl"
         declaration="//@csuDeclarations.0">
       <ports
           xsi:type="hintco:InputPortInstance"
           identifier="wt3_level"
-
           valueFrom="//@candidates.0/@cosimunits.2/@ports.2"/>
       <ports
           xsi:type="hintco:OutputPortInstance"
           identifier="wt3_valve"
-          valueTo="//@candidates.0/@cosimunits.2/@ports.4"
-          />
+          valueTo="//@candidates.0/@cosimunits.2/@ports.4"/>
     </cosimunits>
-    <cosimunits
- xsi:type="hintco:CosimUnitInstance"
+    <cosimunits
+        xsi:type="hintco:CosimUnitInstance"
         identifier="wt1"
         declaration="//@csuDeclarations.1">
       <ports
           xsi:type="hintco:OutputPortInstance"
-          identifier="Tank2WaterLevel"
-          />
+          identifier="Tank2WaterLevel"/>
       <ports
           xsi:type="hintco:OutputPortInstance"
           identifier="Tank2OutFlow"
-          valueTo="//@candidates.0/@cosimunits.2/@ports.3"
-          />
+          valueTo="//@candidates.0/@cosimunits.2/@ports.3"/>
     </cosimunits>
-    <cosimunits
- xsi:type="hintco:CosimUnitInstance"
+    <cosimunits
+        xsi:type="hintco:CosimUnitInstance"
         identifier="wt2"
         declaration="//@csuDeclarations.2">
       <ports
           xsi:type="hintco:OutputPortInstance"
-          identifier="puddle"
-          />
+          identifier="puddle"/>
       <ports
           xsi:type="hintco:OutputPortInstance"
-          identifier="Tank3OutFlow"
-          />
+          identifier="Tank3OutFlow"/>
       <ports
           xsi:type="hintco:OutputPortInstance"
           identifier="level"
-          valueTo="//@candidates.0/@cosimunits.0/@ports.0"
-          />
+          valueTo="//@candidates.0/@cosimunits.0/@ports.0"/>
       <ports
           xsi:type="hintco:InputPortInstance"
           identifier="inFlow"
-
           valueFrom="//@candidates.0/@cosimunits.1/@ports.1"/>
       <ports
           xsi:type="hintco:InputPortInstance"
           identifier="valveControl"
-
           valueFrom="//@candidates.0/@cosimunits.0/@ports.1"/>
     </cosimunits>
   </candidates>
   <csuDeclarations
       identifier="threewatertankcontroller2"
       path="resources/threewatertankcontroller2.fmu"
-      guid="{8c4e810f-3df3-4a00-8276-176fa3c9f003}">
-
-  </csuDeclarations>
+      guid="{8c4e810f-3df3-4a00-8276-176fa3c9f003}"/>
   <csuDeclarations
       identifier="threewatertank1"
       path="resources/threewatertank1.fmu"
-      guid="{dcd729ec-423a-4a0d-8030-4c42a840abba}">
-
-  </csuDeclarations>
+      guid="{dcd729ec-423a-4a0d-8030-4c42a840abba}"/>
   <csuDeclarations
       identifier="threewatertank2"
       path="resources/threewatertank2.fmu"
-      guid="{25941611-1350-4ca2-8fe8-85d9193c14fd}">
-
-  </csuDeclarations>
+      guid="{25941611-1350-4ca2-8fe8-85d9193c14fd}"/>
 </hintco:Candidates>

+ 110 - 0
HintCO/instances/execute_deephier_cosim_test_watertanks.xmi

@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="ASCII"?>
+<hintco:Candidates
+    xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:hintco="ua.ansymo.hintco">
+  <candidates
+      identifier="Original"
+      stopTime="10.0"
+      stepSize="0.01"
+      outputStepSize="0.01">
+    <cosimunits
+        xsi:type="hintco:HierarchicalCosimUnit"
+        identifier="tanks">
+      <cosimunits
+          xsi:type="hintco:CosimUnitInstance"
+          identifier="wt2"
+          declaration="//@csuDeclarations.2">
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="puddle"/>
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="Tank3OutFlow"/>
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="level"
+            valueTo="//@candidates.0/@cosimunits.0/@ports.0"/>
+        <ports
+            xsi:type="hintco:InputPortInstance"
+            identifier="inFlow"
+            valueFrom="//@candidates.0/@cosimunits.0/@cosimunits.1/@ports.0"/>
+        <ports
+            xsi:type="hintco:InputPortInstance"
+            identifier="valveControl"
+            valueFrom="//@candidates.0/@cosimunits.0/@ports.1"/>
+      </cosimunits>
+      <cosimunits
+          xsi:type="hintco:HierarchicalCosimUnit"
+          identifier="env">
+        <cosimunits
+            xsi:type="hintco:CosimUnitInstance"
+            identifier="wt1"
+            declaration="//@csuDeclarations.1">
+          <ports
+              xsi:type="hintco:OutputPortInstance"
+              identifier="Tank2WaterLevel"/>
+          <ports
+              xsi:type="hintco:OutputPortInstance"
+              identifier="Tank2OutFlow"
+              valueTo="//@candidates.0/@cosimunits.0/@cosimunits.1/@ports.0"/>
+        </cosimunits>
+        <ports
+            xsi:type="hintco:HierarchicalUnitPort"
+            identifier="envOut"
+            valueFrom="//@candidates.0/@cosimunits.0/@cosimunits.1/@cosimunits.0/@ports.1"
+            valueTo="//@candidates.0/@cosimunits.0/@cosimunits.0/@ports.3"/>
+      </cosimunits>
+      <ports
+          xsi:type="hintco:HierarchicalUnitPort"
+          identifier="plantOut"
+          valueFrom="//@candidates.0/@cosimunits.0/@cosimunits.0/@ports.2"
+          valueTo="//@candidates.0/@cosimunits.1/@ports.0"/>
+      <ports
+          xsi:type="hintco:HierarchicalUnitPort"
+          identifier="plantIn"
+          valueFrom="//@candidates.0/@cosimunits.1/@ports.1"
+          valueTo="//@candidates.0/@cosimunits.0/@cosimunits.0/@ports.4"/>
+    </cosimunits>
+    <cosimunits
+        xsi:type="hintco:HierarchicalCosimUnit"
+        identifier="controller">
+      <cosimunits
+          xsi:type="hintco:CosimUnitInstance"
+          identifier="ctrl"
+          declaration="//@csuDeclarations.0">
+        <ports
+            xsi:type="hintco:InputPortInstance"
+            identifier="wt3_level"
+            valueFrom="//@candidates.0/@cosimunits.1/@ports.0"/>
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="wt3_valve"
+            valueTo="//@candidates.0/@cosimunits.1/@ports.1"/>
+      </cosimunits>
+      <ports
+          xsi:type="hintco:HierarchicalUnitPort"
+          identifier="ctrlIn"
+          valueFrom="//@candidates.0/@cosimunits.0/@ports.0"
+          valueTo="//@candidates.0/@cosimunits.1/@cosimunits.0/@ports.0"/>
+      <ports
+          xsi:type="hintco:HierarchicalUnitPort"
+          identifier="ctrlOut"
+          valueFrom="//@candidates.0/@cosimunits.1/@cosimunits.0/@ports.1"
+          valueTo="//@candidates.0/@cosimunits.0/@ports.1"/>
+    </cosimunits>
+  </candidates>
+  <csuDeclarations
+      identifier="threewatertankcontroller2"
+      path="resources/threewatertankcontroller2.fmu"
+      guid="{8c4e810f-3df3-4a00-8276-176fa3c9f003}"/>
+  <csuDeclarations
+      identifier="threewatertank1"
+      path="resources/threewatertank1.fmu"
+      guid="{dcd729ec-423a-4a0d-8030-4c42a840abba}"/>
+  <csuDeclarations
+      identifier="threewatertank2"
+      path="resources/threewatertank2.fmu"
+      guid="{25941611-1350-4ca2-8fe8-85d9193c14fd}"/>
+</hintco:Candidates>

+ 82 - 0
HintCO/instances/execute_hier_cosim_test_watertanks.xmi

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="ASCII"?>
+<hintco:Candidates
+    xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:hintco="ua.ansymo.hintco">
+  <candidates
+      identifier="Original"
+      stopTime="10.0"
+      stepSize="0.01"
+      outputStepSize="0.01">
+    <cosimunits
+        xsi:type="hintco:CosimUnitInstance"
+        identifier="ctrl"
+        declaration="//@csuDeclarations.0">
+      <ports
+          xsi:type="hintco:InputPortInstance"
+          identifier="wt3_level"
+          valueFrom="//@candidates.0/@cosimunits.1/@ports.2"/>
+      <ports
+          xsi:type="hintco:OutputPortInstance"
+          identifier="wt3_valve"
+          valueTo="//@candidates.0/@cosimunits.1/@ports.4"/>
+    </cosimunits>
+    <cosimunits
+        xsi:type="hintco:CosimUnitInstance"
+        identifier="wt2"
+        declaration="//@csuDeclarations.2">
+      <ports
+          xsi:type="hintco:OutputPortInstance"
+          identifier="puddle"/>
+      <ports
+          xsi:type="hintco:OutputPortInstance"
+          identifier="Tank3OutFlow"/>
+      <ports
+          xsi:type="hintco:OutputPortInstance"
+          identifier="level"
+          valueTo="//@candidates.0/@cosimunits.0/@ports.0"/>
+      <ports
+          xsi:type="hintco:InputPortInstance"
+          identifier="inFlow"
+          valueFrom="//@candidates.0/@cosimunits.2/@ports.0"/>
+      <ports
+          xsi:type="hintco:InputPortInstance"
+          identifier="valveControl"
+          valueFrom="//@candidates.0/@cosimunits.0/@ports.1"/>
+    </cosimunits>
+    <cosimunits
+        xsi:type="hintco:HierarchicalCosimUnit"
+        identifier="env">
+      <cosimunits
+          xsi:type="hintco:CosimUnitInstance"
+          identifier="wt1"
+          declaration="//@csuDeclarations.1">
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="Tank2WaterLevel"/>
+        <ports
+            xsi:type="hintco:OutputPortInstance"
+            identifier="Tank2OutFlow"
+            valueTo="//@candidates.0/@cosimunits.2/@ports.0"/>
+      </cosimunits>
+      <ports
+          xsi:type="hintco:HierarchicalUnitPort"
+          identifier="envOut"
+          valueFrom="//@candidates.0/@cosimunits.2/@cosimunits.0/@ports.1"
+          valueTo="//@candidates.0/@cosimunits.1/@ports.3"/>
+    </cosimunits>
+  </candidates>
+  <csuDeclarations
+      identifier="threewatertankcontroller2"
+      path="resources/threewatertankcontroller2.fmu"
+      guid="{8c4e810f-3df3-4a00-8276-176fa3c9f003}"/>
+  <csuDeclarations
+      identifier="threewatertank1"
+      path="resources/threewatertank1.fmu"
+      guid="{dcd729ec-423a-4a0d-8030-4c42a840abba}"/>
+  <csuDeclarations
+      identifier="threewatertank2"
+      path="resources/threewatertank2.fmu"
+      guid="{25941611-1350-4ca2-8fe8-85d9193c14fd}"/>
+</hintco:Candidates>

+ 18 - 0
HintCO/model/Candidates.xcore

@@ -90,6 +90,13 @@ abstract class UnitInstance extends IDed,PrecendenceNode{
 		
 		return new BasicEList(#[])
 	}
+	
+	op OutputPortInstance[] getOutputPorts(){
+		ports.filter(OutputPortInstance).filter[!it.isInput].toEList
+	}
+	op InputPortInstance[] getInputPorts(){
+		ports.filter(InputPortInstance).filter[it.isInput].toEList
+	}
 }
 
 class CosimUnitInstance extends UnitInstance {
@@ -114,6 +121,10 @@ abstract class PortInstance extends PrecendenceNode,IDed {
 		return new BasicEList(#[])
 	}
 	
+	op boolean isInput() {
+		false
+	}
+	
 	op boolean getsValueFrom(PortInstance p){
 		return false
 	}
@@ -167,10 +178,17 @@ class InputPortInstance extends PortInstance {
 			return false
 		}
 	}
+	
+	op boolean isInput() {
+		true
+	}
 }
 
 class OutputPortInstance extends PortInstance {
 	refers InputPortInstance[] valueTo opposite valueFrom
+	op boolean isInput() {
+		false
+	}
 }
 
 abstract class Alternative

+ 181 - 10
HintCO/src-gen/ua/ansymo/hintco/HintcoPackage.java

@@ -552,6 +552,24 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int HIERARCHICAL_COSIM_UNIT___SELECTED_ADAPTATIONS = SCENARIO_OPERATION_COUNT + 0;
 
+	/**
+	 * The operation id for the '<em>Get Output Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int HIERARCHICAL_COSIM_UNIT___GET_OUTPUT_PORTS = SCENARIO_OPERATION_COUNT + 1;
+
+	/**
+	 * The operation id for the '<em>Get Input Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int HIERARCHICAL_COSIM_UNIT___GET_INPUT_PORTS = SCENARIO_OPERATION_COUNT + 2;
+
 	/**
 	 * The operation id for the '<em>Valid</em>' operation.
 	 * <!-- begin-user-doc -->
@@ -559,7 +577,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int HIERARCHICAL_COSIM_UNIT___VALID = SCENARIO_OPERATION_COUNT + 1;
+	int HIERARCHICAL_COSIM_UNIT___VALID = SCENARIO_OPERATION_COUNT + 3;
 
 	/**
 	 * The number of operations of the '<em>Hierarchical Cosim Unit</em>' class.
@@ -568,7 +586,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int HIERARCHICAL_COSIM_UNIT_OPERATION_COUNT = SCENARIO_OPERATION_COUNT + 2;
+	int HIERARCHICAL_COSIM_UNIT_OPERATION_COUNT = SCENARIO_OPERATION_COUNT + 4;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.CosimUnitDeclarationImpl <em>Cosim Unit Declaration</em>}' class.
@@ -725,6 +743,24 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int UNIT_INSTANCE___SELECTED_ADAPTATIONS = IDED_OPERATION_COUNT + 0;
 
+	/**
+	 * The operation id for the '<em>Get Output Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int UNIT_INSTANCE___GET_OUTPUT_PORTS = IDED_OPERATION_COUNT + 1;
+
+	/**
+	 * The operation id for the '<em>Get Input Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int UNIT_INSTANCE___GET_INPUT_PORTS = IDED_OPERATION_COUNT + 2;
+
 	/**
 	 * The number of operations of the '<em>Unit Instance</em>' class.
 	 * <!-- begin-user-doc -->
@@ -732,7 +768,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int UNIT_INSTANCE_OPERATION_COUNT = IDED_OPERATION_COUNT + 1;
+	int UNIT_INSTANCE_OPERATION_COUNT = IDED_OPERATION_COUNT + 3;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.CosimUnitInstanceImpl <em>Cosim Unit Instance</em>}' class.
@@ -843,6 +879,24 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int COSIM_UNIT_INSTANCE___SELECTED_ADAPTATIONS = UNIT_INSTANCE___SELECTED_ADAPTATIONS;
 
+	/**
+	 * The operation id for the '<em>Get Output Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int COSIM_UNIT_INSTANCE___GET_OUTPUT_PORTS = UNIT_INSTANCE___GET_OUTPUT_PORTS;
+
+	/**
+	 * The operation id for the '<em>Get Input Ports</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int COSIM_UNIT_INSTANCE___GET_INPUT_PORTS = UNIT_INSTANCE___GET_INPUT_PORTS;
+
 	/**
 	 * The number of operations of the '<em>Cosim Unit Instance</em>' class.
 	 * <!-- begin-user-doc -->
@@ -943,6 +997,15 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int PORT_INSTANCE___SELECTED_ADAPTATIONS = PRECENDENCE_NODE_OPERATION_COUNT + 0;
 
+	/**
+	 * The operation id for the '<em>Is Input</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int PORT_INSTANCE___IS_INPUT = PRECENDENCE_NODE_OPERATION_COUNT + 1;
+
 	/**
 	 * The operation id for the '<em>Gets Value From</em>' operation.
 	 * <!-- begin-user-doc -->
@@ -950,7 +1013,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE = PRECENDENCE_NODE_OPERATION_COUNT + 1;
+	int PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE = PRECENDENCE_NODE_OPERATION_COUNT + 2;
 
 	/**
 	 * The number of operations of the '<em>Port Instance</em>' class.
@@ -959,7 +1022,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int PORT_INSTANCE_OPERATION_COUNT = PRECENDENCE_NODE_OPERATION_COUNT + 2;
+	int PORT_INSTANCE_OPERATION_COUNT = PRECENDENCE_NODE_OPERATION_COUNT + 3;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.InputPortInstanceImpl <em>Input Port Instance</em>}' class.
@@ -1079,6 +1142,15 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int INPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE = PORT_INSTANCE_OPERATION_COUNT + 1;
 
+	/**
+	 * The operation id for the '<em>Is Input</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int INPUT_PORT_INSTANCE___IS_INPUT = PORT_INSTANCE_OPERATION_COUNT + 2;
+
 	/**
 	 * The number of operations of the '<em>Input Port Instance</em>' class.
 	 * <!-- begin-user-doc -->
@@ -1086,7 +1158,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int INPUT_PORT_INSTANCE_OPERATION_COUNT = PORT_INSTANCE_OPERATION_COUNT + 2;
+	int INPUT_PORT_INSTANCE_OPERATION_COUNT = PORT_INSTANCE_OPERATION_COUNT + 3;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.HierarchicalUnitPortImpl <em>Hierarchical Unit Port</em>}' class.
@@ -1222,7 +1294,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int HIERARCHICAL_UNIT_PORT___IS_INPUT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 0;
+	int HIERARCHICAL_UNIT_PORT___IS_INPUT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 1;
 
 	/**
 	 * The operation id for the '<em>Alt Is Input</em>' operation.
@@ -1231,7 +1303,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int HIERARCHICAL_UNIT_PORT___ALT_IS_INPUT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 1;
+	int HIERARCHICAL_UNIT_PORT___ALT_IS_INPUT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 2;
 
 	/**
 	 * The number of operations of the '<em>Hierarchical Unit Port</em>' class.
@@ -1240,7 +1312,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int HIERARCHICAL_UNIT_PORT_OPERATION_COUNT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 2;
+	int HIERARCHICAL_UNIT_PORT_OPERATION_COUNT = INPUT_PORT_INSTANCE_OPERATION_COUNT + 3;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.OutputPortInstanceImpl <em>Output Port Instance</em>}' class.
@@ -1351,6 +1423,15 @@ public interface HintcoPackage extends EPackage {
 	 */
 	int OUTPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE = PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE;
 
+	/**
+	 * The operation id for the '<em>Is Input</em>' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int OUTPUT_PORT_INSTANCE___IS_INPUT = PORT_INSTANCE_OPERATION_COUNT + 0;
+
 	/**
 	 * The number of operations of the '<em>Output Port Instance</em>' class.
 	 * <!-- begin-user-doc -->
@@ -1358,7 +1439,7 @@ public interface HintcoPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int OUTPUT_PORT_INSTANCE_OPERATION_COUNT = PORT_INSTANCE_OPERATION_COUNT + 0;
+	int OUTPUT_PORT_INSTANCE_OPERATION_COUNT = PORT_INSTANCE_OPERATION_COUNT + 1;
 
 	/**
 	 * The meta object id for the '{@link ua.ansymo.hintco.impl.AlternativeImpl <em>Alternative</em>}' class.
@@ -3059,6 +3140,26 @@ public interface HintcoPackage extends EPackage {
 	 */
 	EOperation getUnitInstance__SelectedAdaptations();
 
+	/**
+	 * Returns the meta object for the '{@link ua.ansymo.hintco.UnitInstance#getOutputPorts() <em>Get Output Ports</em>}' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the '<em>Get Output Ports</em>' operation.
+	 * @see ua.ansymo.hintco.UnitInstance#getOutputPorts()
+	 * @generated
+	 */
+	EOperation getUnitInstance__GetOutputPorts();
+
+	/**
+	 * Returns the meta object for the '{@link ua.ansymo.hintco.UnitInstance#getInputPorts() <em>Get Input Ports</em>}' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the '<em>Get Input Ports</em>' operation.
+	 * @see ua.ansymo.hintco.UnitInstance#getInputPorts()
+	 * @generated
+	 */
+	EOperation getUnitInstance__GetInputPorts();
+
 	/**
 	 * Returns the meta object for class '{@link ua.ansymo.hintco.CosimUnitInstance <em>Cosim Unit Instance</em>}'.
 	 * <!-- begin-user-doc -->
@@ -3122,6 +3223,16 @@ public interface HintcoPackage extends EPackage {
 	 */
 	EOperation getPortInstance__SelectedAdaptations();
 
+	/**
+	 * Returns the meta object for the '{@link ua.ansymo.hintco.PortInstance#isInput() <em>Is Input</em>}' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the '<em>Is Input</em>' operation.
+	 * @see ua.ansymo.hintco.PortInstance#isInput()
+	 * @generated
+	 */
+	EOperation getPortInstance__IsInput();
+
 	/**
 	 * Returns the meta object for the '{@link ua.ansymo.hintco.PortInstance#getsValueFrom(ua.ansymo.hintco.PortInstance) <em>Gets Value From</em>}' operation.
 	 * <!-- begin-user-doc -->
@@ -3203,6 +3314,16 @@ public interface HintcoPackage extends EPackage {
 	 */
 	EOperation getInputPortInstance__GetsValueFrom__PortInstance();
 
+	/**
+	 * Returns the meta object for the '{@link ua.ansymo.hintco.InputPortInstance#isInput() <em>Is Input</em>}' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the '<em>Is Input</em>' operation.
+	 * @see ua.ansymo.hintco.InputPortInstance#isInput()
+	 * @generated
+	 */
+	EOperation getInputPortInstance__IsInput();
+
 	/**
 	 * Returns the meta object for class '{@link ua.ansymo.hintco.OutputPortInstance <em>Output Port Instance</em>}'.
 	 * <!-- begin-user-doc -->
@@ -3224,6 +3345,16 @@ public interface HintcoPackage extends EPackage {
 	 */
 	EReference getOutputPortInstance_ValueTo();
 
+	/**
+	 * Returns the meta object for the '{@link ua.ansymo.hintco.OutputPortInstance#isInput() <em>Is Input</em>}' operation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the '<em>Is Input</em>' operation.
+	 * @see ua.ansymo.hintco.OutputPortInstance#isInput()
+	 * @generated
+	 */
+	EOperation getOutputPortInstance__IsInput();
+
 	/**
 	 * Returns the meta object for class '{@link ua.ansymo.hintco.Alternative <em>Alternative</em>}'.
 	 * <!-- begin-user-doc -->
@@ -3949,6 +4080,22 @@ public interface HintcoPackage extends EPackage {
 		 */
 		EOperation UNIT_INSTANCE___SELECTED_ADAPTATIONS = eINSTANCE.getUnitInstance__SelectedAdaptations();
 
+		/**
+		 * The meta object literal for the '<em><b>Get Output Ports</b></em>' operation.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EOperation UNIT_INSTANCE___GET_OUTPUT_PORTS = eINSTANCE.getUnitInstance__GetOutputPorts();
+
+		/**
+		 * The meta object literal for the '<em><b>Get Input Ports</b></em>' operation.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EOperation UNIT_INSTANCE___GET_INPUT_PORTS = eINSTANCE.getUnitInstance__GetInputPorts();
+
 		/**
 		 * The meta object literal for the '{@link ua.ansymo.hintco.impl.CosimUnitInstanceImpl <em>Cosim Unit Instance</em>}' class.
 		 * <!-- begin-user-doc -->
@@ -4001,6 +4148,14 @@ public interface HintcoPackage extends EPackage {
 		 */
 		EOperation PORT_INSTANCE___SELECTED_ADAPTATIONS = eINSTANCE.getPortInstance__SelectedAdaptations();
 
+		/**
+		 * The meta object literal for the '<em><b>Is Input</b></em>' operation.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EOperation PORT_INSTANCE___IS_INPUT = eINSTANCE.getPortInstance__IsInput();
+
 		/**
 		 * The meta object literal for the '<em><b>Gets Value From</b></em>' operation.
 		 * <!-- begin-user-doc -->
@@ -4069,6 +4224,14 @@ public interface HintcoPackage extends EPackage {
 		 */
 		EOperation INPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE = eINSTANCE.getInputPortInstance__GetsValueFrom__PortInstance();
 
+		/**
+		 * The meta object literal for the '<em><b>Is Input</b></em>' operation.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EOperation INPUT_PORT_INSTANCE___IS_INPUT = eINSTANCE.getInputPortInstance__IsInput();
+
 		/**
 		 * The meta object literal for the '{@link ua.ansymo.hintco.impl.OutputPortInstanceImpl <em>Output Port Instance</em>}' class.
 		 * <!-- begin-user-doc -->
@@ -4087,6 +4250,14 @@ public interface HintcoPackage extends EPackage {
 		 */
 		EReference OUTPUT_PORT_INSTANCE__VALUE_TO = eINSTANCE.getOutputPortInstance_ValueTo();
 
+		/**
+		 * The meta object literal for the '<em><b>Is Input</b></em>' operation.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EOperation OUTPUT_PORT_INSTANCE___IS_INPUT = eINSTANCE.getOutputPortInstance__IsInput();
+
 		/**
 		 * The meta object literal for the '{@link ua.ansymo.hintco.impl.AlternativeImpl <em>Alternative</em>}' class.
 		 * <!-- begin-user-doc -->

+ 9 - 0
HintCO/src-gen/ua/ansymo/hintco/InputPortInstance.java

@@ -66,4 +66,13 @@ public interface InputPortInstance extends PortInstance {
 	 */
 	boolean getsValueFrom(PortInstance p);
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @model kind="operation" unique="false"
+	 *        annotation="http://www.eclipse.org/emf/2002/GenModel body='return true;'"
+	 * @generated
+	 */
+	boolean isInput();
+
 } // InputPortInstance

+ 9 - 0
HintCO/src-gen/ua/ansymo/hintco/OutputPortInstance.java

@@ -39,4 +39,13 @@ public interface OutputPortInstance extends PortInstance {
 	 */
 	EList<InputPortInstance> getValueTo();
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @model kind="operation" unique="false"
+	 *        annotation="http://www.eclipse.org/emf/2002/GenModel body='return false;'"
+	 * @generated
+	 */
+	boolean isInput();
+
 } // OutputPortInstance

+ 9 - 0
HintCO/src-gen/ua/ansymo/hintco/PortInstance.java

@@ -87,6 +87,15 @@ public interface PortInstance extends PrecendenceNode, IDed {
 	 */
 	EList<PortAdaptation> selectedAdaptations();
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @model kind="operation" unique="false"
+	 *        annotation="http://www.eclipse.org/emf/2002/GenModel body='return false;'"
+	 * @generated
+	 */
+	boolean isInput();
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->

Разница между файлами не показана из-за своего большого размера
+ 18 - 0
HintCO/src-gen/ua/ansymo/hintco/UnitInstance.java


+ 40 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/HierarchicalCosimUnitImpl.java

@@ -2,6 +2,8 @@
  */
 package ua.ansymo.hintco.impl;
 
+import com.google.common.collect.Iterables;
+
 import java.lang.reflect.InvocationTargetException;
 
 import java.util.Collection;
@@ -10,6 +12,7 @@ import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 
 import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.ECollections;
 import org.eclipse.emf.common.util.EList;
 
 import org.eclipse.emf.ecore.EClass;
@@ -30,6 +33,8 @@ import ua.ansymo.hintco.DecompositionUnitAdaptation;
 import ua.ansymo.hintco.HierarchicalCosimUnit;
 import ua.ansymo.hintco.HierarchicalUnitPort;
 import ua.ansymo.hintco.HintcoPackage;
+import ua.ansymo.hintco.InputPortInstance;
+import ua.ansymo.hintco.OutputPortInstance;
 import ua.ansymo.hintco.PortInstance;
 import ua.ansymo.hintco.PrecendenceNode;
 import ua.ansymo.hintco.Scenario;
@@ -423,6 +428,35 @@ public class HierarchicalCosimUnitImpl extends ScenarioImpl implements Hierarchi
 		return new BasicEList<UnitAdaptation>(java.util.Collections.<UnitAdaptation>unmodifiableList(org.eclipse.xtext.xbase.lib.CollectionLiterals.<UnitAdaptation>newArrayList()));
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<OutputPortInstance> getOutputPorts() {
+		final Function1<OutputPortInstance, Boolean> _function = new Function1<OutputPortInstance, Boolean>() {
+			public Boolean apply(final OutputPortInstance it) {
+				boolean _isInput = it.isInput();
+				return Boolean.valueOf((!_isInput));
+			}
+		};
+		return ECollections.<OutputPortInstance>toEList(IterableExtensions.<OutputPortInstance>filter(Iterables.<OutputPortInstance>filter(this.getPorts(), OutputPortInstance.class), _function));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<InputPortInstance> getInputPorts() {
+		final Function1<InputPortInstance, Boolean> _function = new Function1<InputPortInstance, Boolean>() {
+			public Boolean apply(final InputPortInstance it) {
+				return Boolean.valueOf(it.isInput());
+			}
+		};
+		return ECollections.<InputPortInstance>toEList(IterableExtensions.<InputPortInstance>filter(Iterables.<InputPortInstance>filter(this.getPorts(), InputPortInstance.class), _function));
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -692,6 +726,8 @@ public class HierarchicalCosimUnitImpl extends ScenarioImpl implements Hierarchi
 		if (baseClass == UnitInstance.class) {
 			switch (baseOperationID) {
 				case HintcoPackage.UNIT_INSTANCE___SELECTED_ADAPTATIONS: return HintcoPackage.HIERARCHICAL_COSIM_UNIT___SELECTED_ADAPTATIONS;
+				case HintcoPackage.UNIT_INSTANCE___GET_OUTPUT_PORTS: return HintcoPackage.HIERARCHICAL_COSIM_UNIT___GET_OUTPUT_PORTS;
+				case HintcoPackage.UNIT_INSTANCE___GET_INPUT_PORTS: return HintcoPackage.HIERARCHICAL_COSIM_UNIT___GET_INPUT_PORTS;
 				default: return -1;
 			}
 		}
@@ -710,6 +746,10 @@ public class HierarchicalCosimUnitImpl extends ScenarioImpl implements Hierarchi
 				return valid();
 			case HintcoPackage.HIERARCHICAL_COSIM_UNIT___SELECTED_ADAPTATIONS:
 				return selectedAdaptations();
+			case HintcoPackage.HIERARCHICAL_COSIM_UNIT___GET_OUTPUT_PORTS:
+				return getOutputPorts();
+			case HintcoPackage.HIERARCHICAL_COSIM_UNIT___GET_INPUT_PORTS:
+				return getInputPorts();
 		}
 		return super.eInvoke(operationID, arguments);
 	}

+ 29 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/HierarchicalUnitPortImpl.java

@@ -29,6 +29,7 @@ import ua.ansymo.hintco.HierarchicalUnitPort;
 import ua.ansymo.hintco.HintcoPackage;
 import ua.ansymo.hintco.InputPortInstance;
 import ua.ansymo.hintco.OutputPortInstance;
+import ua.ansymo.hintco.PortInstance;
 import ua.ansymo.hintco.UnitInstance;
 
 /**
@@ -280,6 +281,34 @@ public class HierarchicalUnitPortImpl extends InputPortInstanceImpl implements H
 		return super.eDerivedStructuralFeatureID(baseFeatureID, baseClass);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) {
+		if (baseClass == PortInstance.class) {
+			switch (baseOperationID) {
+				case HintcoPackage.PORT_INSTANCE___IS_INPUT: return HintcoPackage.HIERARCHICAL_UNIT_PORT___IS_INPUT;
+				default: return super.eDerivedOperationID(baseOperationID, baseClass);
+			}
+		}
+		if (baseClass == InputPortInstance.class) {
+			switch (baseOperationID) {
+				case HintcoPackage.INPUT_PORT_INSTANCE___IS_INPUT: return HintcoPackage.HIERARCHICAL_UNIT_PORT___IS_INPUT;
+				default: return super.eDerivedOperationID(baseOperationID, baseClass);
+			}
+		}
+		if (baseClass == OutputPortInstance.class) {
+			switch (baseOperationID) {
+				case HintcoPackage.OUTPUT_PORT_INSTANCE___IS_INPUT: return HintcoPackage.HIERARCHICAL_UNIT_PORT___IS_INPUT;
+				default: return -1;
+			}
+		}
+		return super.eDerivedOperationID(baseOperationID, baseClass);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->

+ 61 - 1
HintCO/src-gen/ua/ansymo/hintco/impl/HintcoPackageImpl.java

@@ -614,6 +614,24 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		return unitInstanceEClass.getEOperations().get(0);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EOperation getUnitInstance__GetOutputPorts() {
+		return unitInstanceEClass.getEOperations().get(1);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EOperation getUnitInstance__GetInputPorts() {
+		return unitInstanceEClass.getEOperations().get(2);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -673,10 +691,19 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
-	public EOperation getPortInstance__GetsValueFrom__PortInstance() {
+	public EOperation getPortInstance__IsInput() {
 		return portInstanceEClass.getEOperations().get(1);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EOperation getPortInstance__GetsValueFrom__PortInstance() {
+		return portInstanceEClass.getEOperations().get(2);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -740,6 +767,15 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		return inputPortInstanceEClass.getEOperations().get(1);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EOperation getInputPortInstance__IsInput() {
+		return inputPortInstanceEClass.getEOperations().get(2);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -758,6 +794,15 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		return (EReference)outputPortInstanceEClass.getEStructuralFeatures().get(0);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EOperation getOutputPortInstance__IsInput() {
+		return outputPortInstanceEClass.getEOperations().get(0);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -1187,6 +1232,8 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		createEReference(unitInstanceEClass, UNIT_INSTANCE__ADAPTATION);
 		createEReference(unitInstanceEClass, UNIT_INSTANCE__PORTS);
 		createEOperation(unitInstanceEClass, UNIT_INSTANCE___SELECTED_ADAPTATIONS);
+		createEOperation(unitInstanceEClass, UNIT_INSTANCE___GET_OUTPUT_PORTS);
+		createEOperation(unitInstanceEClass, UNIT_INSTANCE___GET_INPUT_PORTS);
 
 		cosimUnitInstanceEClass = createEClass(COSIM_UNIT_INSTANCE);
 		createEReference(cosimUnitInstanceEClass, COSIM_UNIT_INSTANCE__DECLARATION);
@@ -1195,6 +1242,7 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		createEReference(portInstanceEClass, PORT_INSTANCE__UNIT);
 		createEReference(portInstanceEClass, PORT_INSTANCE__ADAPTATION);
 		createEOperation(portInstanceEClass, PORT_INSTANCE___SELECTED_ADAPTATIONS);
+		createEOperation(portInstanceEClass, PORT_INSTANCE___IS_INPUT);
 		createEOperation(portInstanceEClass, PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE);
 
 		hierarchicalUnitPortEClass = createEClass(HIERARCHICAL_UNIT_PORT);
@@ -1205,9 +1253,11 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		createEReference(inputPortInstanceEClass, INPUT_PORT_INSTANCE__VALUE_FROM);
 		createEOperation(inputPortInstanceEClass, INPUT_PORT_INSTANCE___GET_REAL_VALUE_FROM);
 		createEOperation(inputPortInstanceEClass, INPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE);
+		createEOperation(inputPortInstanceEClass, INPUT_PORT_INSTANCE___IS_INPUT);
 
 		outputPortInstanceEClass = createEClass(OUTPUT_PORT_INSTANCE);
 		createEReference(outputPortInstanceEClass, OUTPUT_PORT_INSTANCE__VALUE_TO);
+		createEOperation(outputPortInstanceEClass, OUTPUT_PORT_INSTANCE___IS_INPUT);
 
 		alternativeEClass = createEClass(ALTERNATIVE);
 		createEAttribute(alternativeEClass, ALTERNATIVE__WEIGHT);
@@ -1373,6 +1423,10 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 
 		initEOperation(getUnitInstance__SelectedAdaptations(), this.getUnitAdaptation(), "selectedAdaptations", 0, -1, !IS_UNIQUE, IS_ORDERED);
 
+		initEOperation(getUnitInstance__GetOutputPorts(), this.getOutputPortInstance(), "getOutputPorts", 0, -1, !IS_UNIQUE, IS_ORDERED);
+
+		initEOperation(getUnitInstance__GetInputPorts(), this.getInputPortInstance(), "getInputPorts", 0, -1, !IS_UNIQUE, IS_ORDERED);
+
 		initEClass(cosimUnitInstanceEClass, CosimUnitInstance.class, "CosimUnitInstance", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEReference(getCosimUnitInstance_Declaration(), this.getCosimUnitDeclaration(), null, "declaration", null, 1, 1, CosimUnitInstance.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 
@@ -1382,6 +1436,8 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 
 		initEOperation(getPortInstance__SelectedAdaptations(), this.getPortAdaptation(), "selectedAdaptations", 0, -1, !IS_UNIQUE, IS_ORDERED);
 
+		initEOperation(getPortInstance__IsInput(), theEcorePackage.getEBoolean(), "isInput", 0, 1, !IS_UNIQUE, IS_ORDERED);
+
 		EOperation op = initEOperation(getPortInstance__GetsValueFrom__PortInstance(), theEcorePackage.getEBoolean(), "getsValueFrom", 0, 1, !IS_UNIQUE, IS_ORDERED);
 		addEParameter(op, this.getPortInstance(), "p", 0, 1, !IS_UNIQUE, IS_ORDERED);
 
@@ -1399,9 +1455,13 @@ public class HintcoPackageImpl extends EPackageImpl implements HintcoPackage {
 		op = initEOperation(getInputPortInstance__GetsValueFrom__PortInstance(), theEcorePackage.getEBoolean(), "getsValueFrom", 0, 1, !IS_UNIQUE, IS_ORDERED);
 		addEParameter(op, this.getPortInstance(), "p", 0, 1, !IS_UNIQUE, IS_ORDERED);
 
+		initEOperation(getInputPortInstance__IsInput(), theEcorePackage.getEBoolean(), "isInput", 0, 1, !IS_UNIQUE, IS_ORDERED);
+
 		initEClass(outputPortInstanceEClass, OutputPortInstance.class, "OutputPortInstance", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEReference(getOutputPortInstance_ValueTo(), this.getInputPortInstance(), this.getInputPortInstance_ValueFrom(), "valueTo", null, 0, -1, OutputPortInstance.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 
+		initEOperation(getOutputPortInstance__IsInput(), theEcorePackage.getEBoolean(), "isInput", 0, 1, !IS_UNIQUE, IS_ORDERED);
+
 		initEClass(alternativeEClass, Alternative.class, "Alternative", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEAttribute(getAlternative_Weight(), theEcorePackage.getEInt(), "weight", null, 0, 1, Alternative.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, !IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 		initEAttribute(getAlternative_Selected(), theEcorePackage.getEBoolean(), "selected", null, 0, 1, Alternative.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, !IS_UNIQUE, !IS_DERIVED, IS_ORDERED);

+ 12 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/InputPortInstanceImpl.java

@@ -164,6 +164,15 @@ public class InputPortInstanceImpl extends PortInstanceImpl implements InputPort
 		}
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public boolean isInput() {
+		return true;
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -262,6 +271,7 @@ public class InputPortInstanceImpl extends PortInstanceImpl implements InputPort
 	public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) {
 		if (baseClass == PortInstance.class) {
 			switch (baseOperationID) {
+				case HintcoPackage.PORT_INSTANCE___IS_INPUT: return HintcoPackage.INPUT_PORT_INSTANCE___IS_INPUT;
 				case HintcoPackage.PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE: return HintcoPackage.INPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE;
 				default: return super.eDerivedOperationID(baseOperationID, baseClass);
 			}
@@ -281,6 +291,8 @@ public class InputPortInstanceImpl extends PortInstanceImpl implements InputPort
 				return getRealValueFrom();
 			case HintcoPackage.INPUT_PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE:
 				return getsValueFrom((PortInstance)arguments.get(0));
+			case HintcoPackage.INPUT_PORT_INSTANCE___IS_INPUT:
+				return isInput();
 		}
 		return super.eInvoke(operationID, arguments);
 	}

+ 42 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/OutputPortInstanceImpl.java

@@ -2,6 +2,8 @@
  */
 package ua.ansymo.hintco.impl;
 
+import java.lang.reflect.InvocationTargetException;
+
 import java.util.Collection;
 
 import org.eclipse.emf.common.notify.NotificationChain;
@@ -17,6 +19,7 @@ import org.eclipse.emf.ecore.util.InternalEList;
 import ua.ansymo.hintco.HintcoPackage;
 import ua.ansymo.hintco.InputPortInstance;
 import ua.ansymo.hintco.OutputPortInstance;
+import ua.ansymo.hintco.PortInstance;
 
 /**
  * <!-- begin-user-doc -->
@@ -73,6 +76,15 @@ public class OutputPortInstanceImpl extends PortInstanceImpl implements OutputPo
 		return valueTo;
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public boolean isInput() {
+		return false;
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -162,4 +174,34 @@ public class OutputPortInstanceImpl extends PortInstanceImpl implements OutputPo
 		return super.eIsSet(featureID);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) {
+		if (baseClass == PortInstance.class) {
+			switch (baseOperationID) {
+				case HintcoPackage.PORT_INSTANCE___IS_INPUT: return HintcoPackage.OUTPUT_PORT_INSTANCE___IS_INPUT;
+				default: return super.eDerivedOperationID(baseOperationID, baseClass);
+			}
+		}
+		return super.eDerivedOperationID(baseOperationID, baseClass);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException {
+		switch (operationID) {
+			case HintcoPackage.OUTPUT_PORT_INSTANCE___IS_INPUT:
+				return isInput();
+		}
+		return super.eInvoke(operationID, arguments);
+	}
+
 } //OutputPortInstanceImpl

+ 11 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/PortInstanceImpl.java

@@ -228,6 +228,15 @@ public abstract class PortInstanceImpl extends PrecendenceNodeImpl implements Po
 		return new BasicEList<PortAdaptation>(java.util.Collections.<PortAdaptation>unmodifiableList(org.eclipse.xtext.xbase.lib.CollectionLiterals.<PortAdaptation>newArrayList()));
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public boolean isInput() {
+		return false;
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -408,6 +417,8 @@ public abstract class PortInstanceImpl extends PrecendenceNodeImpl implements Po
 		switch (operationID) {
 			case HintcoPackage.PORT_INSTANCE___SELECTED_ADAPTATIONS:
 				return selectedAdaptations();
+			case HintcoPackage.PORT_INSTANCE___IS_INPUT:
+				return isInput();
 			case HintcoPackage.PORT_INSTANCE___GETS_VALUE_FROM__PORTINSTANCE:
 				return getsValueFrom((PortInstance)arguments.get(0));
 		}

+ 42 - 0
HintCO/src-gen/ua/ansymo/hintco/impl/UnitInstanceImpl.java

@@ -2,6 +2,8 @@
  */
 package ua.ansymo.hintco.impl;
 
+import com.google.common.collect.Iterables;
+
 import java.lang.reflect.InvocationTargetException;
 
 import java.util.Collection;
@@ -10,6 +12,7 @@ import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 
 import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.ECollections;
 import org.eclipse.emf.common.util.EList;
 
 import org.eclipse.emf.ecore.EClass;
@@ -22,8 +25,14 @@ import org.eclipse.emf.ecore.util.EObjectWithInverseResolvingEList;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.emf.ecore.util.InternalEList;
 
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+
 import ua.ansymo.hintco.DecompositionUnitAdaptation;
 import ua.ansymo.hintco.HintcoPackage;
+import ua.ansymo.hintco.InputPortInstance;
+import ua.ansymo.hintco.OutputPortInstance;
 import ua.ansymo.hintco.PortInstance;
 import ua.ansymo.hintco.PrecendenceNode;
 import ua.ansymo.hintco.Scenario;
@@ -403,6 +412,35 @@ public abstract class UnitInstanceImpl extends IDedImpl implements UnitInstance
 		return new BasicEList<UnitAdaptation>(java.util.Collections.<UnitAdaptation>unmodifiableList(org.eclipse.xtext.xbase.lib.CollectionLiterals.<UnitAdaptation>newArrayList()));
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<OutputPortInstance> getOutputPorts() {
+		final Function1<OutputPortInstance, Boolean> _function = new Function1<OutputPortInstance, Boolean>() {
+			public Boolean apply(final OutputPortInstance it) {
+				boolean _isInput = it.isInput();
+				return Boolean.valueOf((!_isInput));
+			}
+		};
+		return ECollections.<OutputPortInstance>toEList(IterableExtensions.<OutputPortInstance>filter(Iterables.<OutputPortInstance>filter(this.getPorts(), OutputPortInstance.class), _function));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<InputPortInstance> getInputPorts() {
+		final Function1<InputPortInstance, Boolean> _function = new Function1<InputPortInstance, Boolean>() {
+			public Boolean apply(final InputPortInstance it) {
+				return Boolean.valueOf(it.isInput());
+			}
+		};
+		return ECollections.<InputPortInstance>toEList(IterableExtensions.<InputPortInstance>filter(Iterables.<InputPortInstance>filter(this.getPorts(), InputPortInstance.class), _function));
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -651,6 +689,10 @@ public abstract class UnitInstanceImpl extends IDedImpl implements UnitInstance
 		switch (operationID) {
 			case HintcoPackage.UNIT_INSTANCE___SELECTED_ADAPTATIONS:
 				return selectedAdaptations();
+			case HintcoPackage.UNIT_INSTANCE___GET_OUTPUT_PORTS:
+				return getOutputPorts();
+			case HintcoPackage.UNIT_INSTANCE___GET_INPUT_PORTS:
+				return getInputPorts();
 		}
 		return super.eInvoke(operationID, arguments);
 	}

+ 41 - 14
HintCO/src/ua/ansymo/hintco/AdaptedFMUInstance.xtend

@@ -1,11 +1,19 @@
 package ua.ansymo.hintco
 
+import java.util.List
 import java.util.Map
 import org.eclipse.core.runtime.Assert
 import org.intocps.fmi.Fmi2Status
 import org.intocps.fmi.FmuInvocationException
 import org.intocps.fmi.IFmiComponent
-import java.util.List
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+enum MODE {
+  NOT_INIT,
+  INITING,
+  INITED
+}
 
 class AdaptedFMUInstance extends FmuInstance {
 	
@@ -13,20 +21,24 @@ class AdaptedFMUInstance extends FmuInstance {
 	val Map<String, List<IAdaptedInputPort>> adaptedInPorts = newHashMap()
 	val Map<String, IAdaptedOutputPort> adaptedOutPorts = newHashMap()
 	
-	val INITIALIZING = 1
-	val INITIALIZED = 2
-	val INSTANTIATED = 0
+	Logger logger = LoggerFactory.getLogger(typeof(CosimRunner))
 	
-	int currentMode
+	protected MODE currentMode
 	
-	new(IFmiComponent f, UnitInstance unit) {
+	UnitInstance unit
+	
+	List<OutputPortInstance> outputPorts
+	
+	new(IFmiComponent f, UnitInstance u) {
 		super(f)
+		unit = u
 		instantiateAdaptations(unit)
-		currentMode = INSTANTIATED
+		currentMode = MODE.NOT_INIT
+		outputPorts = unit.outputPorts
 	}
 	
 	new(UnitInstance unit) {
-		instantiateAdaptations(unit)
+		this(null, unit)
 	}
 	
 	def instantiateAdaptations(UnitInstance unit) {
@@ -81,12 +93,12 @@ class AdaptedFMUInstance extends FmuInstance {
 	}
 	
 	override enterInitializationMode() throws FmuInvocationException {
-		currentMode = INITIALIZING
+		currentMode = MODE.INITING
 		super.enterInitializationMode()
 	}
 	
 	override exitInitializationMode() throws FmuInvocationException {
-		currentMode = INITIALIZED
+		currentMode = MODE.INITED
 		super.exitInitializationMode()
 	}
 	
@@ -114,7 +126,7 @@ class AdaptedFMUInstance extends FmuInstance {
 			}
 			
 			// doStep
-			status = super.doStep(inner_time, micro_step)
+			status = doInnerStep(inner_time, micro_step)
 			
 			// Update inner time
 			inner_time = inner_time + micro_step
@@ -138,30 +150,40 @@ class AdaptedFMUInstance extends FmuInstance {
 		return status
 	}
 	
+	def doInnerStep(double inner_time, double micro_step) {
+		super.doStep(inner_time, micro_step)
+	}
+	
 	override setReal(String portName, double v) {
+		logger.debug(">{}.setReal({},{})", unit.identifier, portName, v)
 		val adaptedPorts = adaptedInPorts.get(portName)
 		if (adaptedPorts !== null){
+			logger.debug("Going through adapted ports.")
 			for (p : adaptedPorts){
 				p.setReal(v)
 				// In initialization mode, the values of the adaptation must be propagated to the internal fmus.
-				if (currentMode == INITIALIZING){
+				if (currentMode == MODE.INITING){
 					p.computeReal(0.0, 0.0, 0.0, 0.0)	
 				}
 			}
 		} else {
+			logger.debug("No adaptations used.")
 			setInnerReal(portName, v)
 		}
 	}
 	
 	override getReal(String portName){
+		logger.debug(">{}.getReal({})", unit.identifier, portName)
 		val adaptedPort = adaptedOutPorts.get(portName)
 		if (adaptedPort !== null){
+			logger.debug("Going through adapted port.")
 			// In initialization mode, the values of the adaptation must be obtained from the internal fmus.
-			if (currentMode == INITIALIZING){
+			if (currentMode == MODE.INITING){
 				adaptedPort.recordReal(0.0,0.0,0.0,0.0)
 			}
 			adaptedPort.getReal()
 		} else {
+			logger.debug("No adaptation used.")
 			getInnerReal(portName)
 		}
 	}
@@ -173,7 +195,12 @@ class AdaptedFMUInstance extends FmuInstance {
 	def getInnerReal(String portName){
 		super.getReal(portName)
 	}
-	
+
+	override outputSnapshot(Map<OutputPortInstance, Double> outVals) {
+		for (outP : outputPorts){
+			outVals.put(outP, getReal(outP.identifier))
+		}
+	}
 	
 	// Utility methods to deal with adaptedPort structures
 	

+ 1 - 5
HintCO/src/ua/ansymo/hintco/CandidatesGenerator.xtend

@@ -126,11 +126,7 @@ class CandidatesGenerator {
 					
 					// Create I/DoStep constraints: inputs should be set before doStep.
 					for (inP : scenario.eAllContents.filter(InputPortInstance)
-													.filter[ip | if (ip instanceof HierarchicalUnitPort)
-																	ip.isInput()
-																else
-																	true
-															] // ip can be a hierarchical port, 
+													.filter[it.isInput] // ip can be a hierarchical port, 
 													.toIterable // therefore we need to make sure it is connected to an internal unit. 
 																//Otherwise it is not an input port.
 													

+ 138 - 0
HintCO/src/ua/ansymo/hintco/CosimRunUtils.xtend

@@ -0,0 +1,138 @@
+package ua.ansymo.hintco
+
+import java.util.List
+import java.util.Map
+import java.util.Set
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+class CosimRunUtils {
+	
+	static Logger logger = LoggerFactory.getLogger(typeof(CosimRunUtils))
+	
+	def static instantiateUnits(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap, IFmuLoader fmuLoader, Map<Scenario, List<PrecendenceNode>> scenarioNodesMap) {
+		for (unit : units) {
+			val fmuInstance = fmuLoader.instantiate(unit, scenarioNodesMap)
+			logger.debug("Unit {} instantiated", unit)
+			
+			fmuInstanceMap.put(unit, fmuInstance)
+		}
+	}
+	
+	def static exitInitMode(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap) {
+		// Exit init mode
+		for (unit : units) {
+			fmuInstanceMap.get(unit).exitInitializationMode()
+			logger.debug("Unit {} exit initialization mode.", unit)
+		}
+	}
+	
+	def static intoInitMode(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap) {
+		for (unit: units){
+			val fmuInstance = fmuInstanceMap.get(unit)
+			fmuInstance.enterInitializationMode()
+			logger.debug("Unit {} enter initialization mode", unit)
+		}
+	}
+	
+	def static setupExperiment(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap) {
+		for (unit: units){
+			val fmuInstance = fmuInstanceMap.get(unit)
+			fmuInstance.setupExperiment()
+			logger.debug("Unit {} experiment setup", unit)
+			
+			// TODO Set the configured parameter values.
+		}
+	}
+	
+	def static getOutputSnapshot(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap, Map<OutputPortInstance, Double> outVals) {
+		logger.debug("Getting output snapshot.")
+		for (u : units) {
+			val fmu = fmuInstanceMap.get(u)
+			fmu.outputSnapshot(outVals)
+		}
+		return outVals
+	}
+	
+	def static freeUnits(List<UnitInstance> units, Map<UnitInstance, IFmuInstance> fmuInstanceMap) {
+		for (unit : units) {
+			fmuInstanceMap.get(unit).free()
+			logger.debug("Unit {} free.", unit)
+		}
+	}
+	
+	def static fixPointOutputs(List<OutputPortInstance> childOutputPorts, Map<UnitInstance, IFmuInstance> fmuInstanceMap, int maxIt) {
+		// 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()
+		
+		// Initialize
+		for (out : childOutputPorts){
+			outVals.put(out, Double.POSITIVE_INFINITY)
+			logger.debug("Output port {}.{} initialized to infinity", out.unit.identifier, out.identifier)
+		}
+		
+		var converged=false
+		var i = 0
+		
+		logger.debug("Starting fixed point iteration for time 0.0.")
+		while (!converged && i<maxIt){
+			logger.debug("Iteration {} start.", i)
+			converged = true
+			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.
+				if (! MathUtils.isApproximatelyEqual(outV, outVals.get(out), 1e-8)){
+					converged = false
+				}
+				// Store the new value, for next iteration
+				outVals.put(out, outV)
+				
+				// Propagate outV to inputs.
+				// TODO: Take types into account. For now we assume everything is real.
+				for (trgPort : out.valueTo){
+					fmuInstanceMap.get(trgPort.unit).setReal(trgPort.identifier, outV)
+					logger.debug("SetReal {}.{} to {} at iteration {}.", trgPort.unit.identifier, trgPort.identifier, outV, i)
+				}
+			}
+			if (!converged){
+				logger.debug("Iteration {} end. Not Converged.", i)
+			} else {
+				logger.debug("Iteration {} end. Converged.", i)
+			}
+			i++
+		}
+		
+		return outVals
+	}
+	
+	def static executeStep(double time, double stepSize, List<PrecendenceNode> nodes, Set<InputPortInstance> inPorts, Map<UnitInstance, IFmuInstance> fmuInstanceMap) {
+		logger.debug("Co-simulation step start at time {} -> {}.", time, time + stepSize)
+		for (n : nodes) {
+			switch (n) {
+				UnitInstance: {
+					// doStep
+					fmuInstanceMap.get(n).doStep(time,stepSize)
+					logger.debug("DoStep {} at time {}.", n.identifier, time)
+				}
+				OutputPortInstance case !inPorts.contains(n):{ // Ignore input ports, as these are set after the get output ports
+					// Propagate values
+					val outV = fmuInstanceMap.get(n.unit).getReal(n.identifier)
+					logger.debug("GetReal {}.{} at time {} yields {}.", n.unit.identifier, n.identifier, time, outV)
+					
+					// Propagate outV to the selected inputs (not all inputs need to be set because of Hierarchical units).
+					for (trgPort : n.valueTo.filter[inPorts.contains(it)]){
+						fmuInstanceMap.get(trgPort.unit).setReal(trgPort.identifier, outV)
+						logger.debug("SetReal {}.{} to {} at time {}.", trgPort.unit.identifier, trgPort.identifier, outV, time)
+					}
+				}
+				default: {
+					// Do Nothing for InputPort instances.
+				}
+			}
+		}
+		logger.debug("Co-simulation step end at time {} -> {}.", time, time + stepSize)
+	}
+}

+ 20 - 120
HintCO/src/ua/ansymo/hintco/CosimRunner.xtend

@@ -2,16 +2,17 @@ package ua.ansymo.hintco
 
 import java.io.Closeable
 import java.io.IOException
-import java.util.HashMap
 import java.util.List
 import java.util.Map
 import org.eclipse.core.runtime.Assert
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
+import static ua.ansymo.hintco.CosimRunUtils.*
+
 class CosimRunner implements ICosimRunner, Closeable {
 	
-	val HashMap<UnitInstance, IFmuInstance> fmuInstanceMap = newHashMap()
+	val Map<UnitInstance, IFmuInstance> fmuInstanceMap = newHashMap()
 	
 	IOutputProcessor outProcessor
 	
@@ -31,135 +32,44 @@ class CosimRunner implements ICosimRunner, Closeable {
 		
 		val units = nodes.filter(UnitInstance).toList
 		
+		val outVals = newHashMap() // Will store output values
+		
 		// 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)
-		}
+		instantiateUnits(units, fmuInstanceMap, fmuLoader, scenarioNodesMap)
 		
-		// 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.
-		}
+		setupExperiment(units, fmuInstanceMap)
 		
 		// Go into init mode
-		for (unit: units){
-			val fmuInstance = fmuInstanceMap.get(unit)
-			fmuInstance.enterInitializationMode()
-			logger.debug("Unit {} enter initialization mode", unit)
-		}
-		
-		// 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()
-		// Takes into account hierarchical unit ports.
-		val childOutputPorts = nodes.filter(OutputPortInstance).filter[
-			if (it instanceof HierarchicalUnitPort){
-				! it.isInput
-			} else {
-				true
-			}
-		].toList
-		// Initialize
-		for (out : childOutputPorts){
-			outVals.put(out, Double.POSITIVE_INFINITY)
-			logger.debug("Output port {}.{} initialized to infinity", out.unit.identifier, out.identifier)
-		}
+		intoInitMode(units, fmuInstanceMap)
 		
 		val MAX_IT = 10 // TODO: refactor. Should be a configuration parameter.
 		
-		var converged=false
-		var i = 0
+		// Takes into account hierarchical unit ports.
+		val childOutputPorts = nodes.filter(OutputPortInstance).filter[!it.isInput].toList
+		val childInputPorts = nodes.filter(InputPortInstance).filter[it.isInput].toSet
 		
-		logger.debug("Starting fixed point iteration for time 0.0.")
-		while (!converged && i<MAX_IT){
-			logger.debug("Iteration {} start.", i)
-			converged = true
-			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.
-				if (! MathUtils.isApproximatelyEqual(outV, outVals.get(out), 1e-8)){
-					converged = false
-				}
-				// Store the new value, for next iteration
-				outVals.put(out, outV)
-				
-				// 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)
-				}
-			}
-			if (!converged){
-				logger.debug("Iteration {} end. Not Converged.", i)
-			} else {
-				logger.debug("Iteration {} end. Converged.", i)
-			}
-			i++
-		}
+		fixPointOutputs(childOutputPorts, fmuInstanceMap, MAX_IT)
 		
 		// Init output processor with experiment parameters
 		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)
+		outVals.clear()
+		outProcessor.setOutputs(0, 0.0, getOutputSnapshot(units, fmuInstanceMap, outVals))
 		logger.debug("Output line recorded for time {}.", 0.0)
 		
-		// Exit init mode
-		for (unit : units) {
-			fmuInstanceMap.get(unit).exitInitializationMode()
-			logger.debug("Unit {} exit initialization mode.", unit)
-		}
+		exitInitMode(units, fmuInstanceMap)
 		
 		// Run the co-sim scenario
 		var time = 0.0d
 		val stepSize = rootScenario.stepSize
 		val stopTime = rootScenario.stopTime
-		i = 0
+		var i = 0
 		while (time < stopTime || MathUtils.isApproximatelyEqual(time, stopTime, stepSize*1e-3)){
-			logger.debug("Co-simulation step start at time {} -> {}.", time, time + stepSize)
-			// Reset map, so we can keep track of outputs produced.
-			outVals.clear()
 			
-			for (n : nodes) {
-				switch (n) {
-					CosimUnitInstance: {
-						// doStep
-						fmuInstanceMap.get(n).doStep(time,stepSize)
-						logger.debug("DoStep {} at time {}.", n.identifier, time)
-					}
-					OutputPortInstance:{
-						// Propagate values
-						val outV = fmuInstanceMap.get(n.unit).getReal(n.identifier)
-						logger.debug("GetReal {}.{} at time {} yields {}.", n.unit.identifier, n.identifier, time, outV)
-						
-						Assert.isTrue(! outVals.containsKey(n))
-						outVals.put(n, outV)
-						
-						// Propagate outV to inputs.
-						for (trgPort : n.valueTo){
-							fmuInstanceMap.get(trgPort.unit).setReal(trgPort.identifier, outV)
-							logger.debug("SetReal {}.{} to {} at time {}.", trgPort.unit.identifier, trgPort.identifier, outV, time)
-						}
-					}
-					default: {
-						// Do Nothing for InputPort instances.
-					}
-				}
-			}
+			executeStep(time, stepSize, nodes, childInputPorts, fmuInstanceMap)
 			
 			// Advance time
 			logger.debug("Time advance: {} -> {}", time, time + stepSize)
@@ -173,25 +83,15 @@ 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
-			// 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)					
-			}
-			outProcessor.setOutputs(i, time, outVals)
+			outVals.clear()
+			outProcessor.setOutputs(i, time, getOutputSnapshot(units, fmuInstanceMap, outVals))
 			logger.debug("Output line recorded for time {}.", 0.0)
-			
-			logger.debug("Co-simulation step end at time {} -> {}", time-stepSize, time)
 		}
 		
 		// Cleanup
 		outProcessor.terminate()
 		logger.debug("Output processor terminated.")
-		for (unit : units) {
-			fmuInstanceMap.get(unit).free()
-			logger.debug("Unit {} free.", unit)
-		}
+		freeUnits(units, fmuInstanceMap)
 	}
 	
 	override close() throws IOException {

+ 5 - 9
HintCO/src/ua/ansymo/hintco/FmuInstance.xtend

@@ -9,17 +9,15 @@ import org.intocps.orchestration.coe.modeldefinition.ModelDescription
 import org.intocps.orchestration.coe.modeldefinition.ModelDescription.ScalarVariable
 
 	
-class FmuInstance implements IFmuInstance  {
+abstract class FmuInstance implements IFmuInstance  {
 	var IFmiComponent f
 	var Map<String, ScalarVariable> varsByName = newHashMap()
 	
 	new (IFmiComponent f){
-		this.f = f
-		loadVariables()
-	}
-	
-	new(){
-		this.f = null
+		if (f !== null){
+			this.f = f
+			loadVariables()			
+		}
 	}
 	
 	def loadVariables(){
@@ -61,6 +59,4 @@ class FmuInstance implements IFmuInstance  {
 		f.freeInstance()
 	}
 	
-	
-	
 }

+ 0 - 1
HintCO/src/ua/ansymo/hintco/FmuLoader.xtend

@@ -10,7 +10,6 @@ import org.intocps.fmi.IFmuCallback
 import org.intocps.fmi.jnifmuapi.Factory
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
-import org.intocps.fmi.IFmiComponent
 
 class FmuLoader implements IFmuLoader {
 	

+ 71 - 32
HintCO/src/ua/ansymo/hintco/HierarchicalInstance.xtend

@@ -8,6 +8,9 @@ import org.intocps.fmi.FmuInvocationException
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
+import static ua.ansymo.hintco.CosimRunUtils.*
+import java.util.Set
+
 // TODO Possible reuse mechanism: extends CosimRunner
 class HierarchicalInstance extends AdaptedFMUInstance {
 	
@@ -20,72 +23,108 @@ class HierarchicalInstance extends AdaptedFMUInstance {
 	
 	List<UnitInstance> units
 	
+	List<OutputPortInstance> childOutputPorts
+	
+	Set<InputPortInstance> inPorts
+	
 	new(HierarchicalCosimUnit u, Map<Scenario, List<PrecendenceNode>> scenarioNodesMap, FmuLoader l) {
 		super(u)
 		loader = l
 		unit = u
 		Assert.isTrue(scenarioNodesMap.containsKey(unit))
-		nodes = scenarioNodesMap.get(unit)
 		
-		// Instantiate subunits.
-		// TODO Can be refactored from the cosim runner.
-		units = nodes.filter(UnitInstance).toList
+		// Ignore units own output ports 
+		nodes = scenarioNodesMap.get(unit).filter[!unit.ports.contains(it)].toList
 		
-		// Instantiate each unit, and record the instance reference.
-		for (subUnit : units) {
-			val fmuInstance = loader.instantiate(subUnit, scenarioNodesMap)
-			logger.debug("Unit {} instantiated", subUnit)
-			
-			fmuInstanceMap.put(subUnit, fmuInstance)
-		}
+		inPorts = nodes.filter(InputPortInstance).filter[it.input].toSet
+		
+		// Ignore hierarchyports that are inputs.
+		childOutputPorts = nodes.filter(OutputPortInstance).filter[!it.isInput].toList
+		
+		// Instantiate subunits.
+		units = nodes.filter(UnitInstance).toList		
+		instantiateUnits(units, fmuInstanceMap, loader, scenarioNodesMap)
 	}
 
 	override setupExperiment() {
 		// setup experiment
-		for (unit: units){
-			val fmuInstance = fmuInstanceMap.get(unit)
-			fmuInstance.setupExperiment()
-			logger.debug("Unit {} experiment setup", unit)
-			
-			// TODO Set the configured parameter values.
-		}
+		setupExperiment(units, fmuInstanceMap)
 		return Fmi2Status.OK
 	}
 	
 	override enterInitializationMode() throws FmuInvocationException {
-		// Go into init mode
-		for (unit: units){
-			val fmuInstance = fmuInstanceMap.get(unit)
-			fmuInstance.enterInitializationMode()
-			logger.debug("Unit {} enter initialization mode", unit)
-		}
+		intoInitMode(units, fmuInstanceMap)
 		return Fmi2Status.OK
 	}
 	
 	override exitInitializationMode() throws FmuInvocationException {
 		// Go into init mode
-		for (unit: units){
-			val fmuInstance = fmuInstanceMap.get(unit)
-			fmuInstance.exitInitializationMode()
-			logger.debug("Unit {} enter initialization mode", unit)
-		}
+		exitInitMode(units, fmuInstanceMap)
 		return Fmi2Status.OK
 	}
 	
-	override setInnerReal(String portName, double v){
+	override setInnerReal(String portName, double v) {
 		/*
 		 * This method is called after the adaptations are processed.
 		 * If we are in initialization mode, then we need to propagate the values to the internal units, and trigger their propagation.
 		 * Otherwise, just set the value on the internal ports.
 		 */
+		logger.debug(">{}.setInnerReal({},{})", unit.identifier, portName, v)
+		
+		val unitPort = unit.ports.findFirst[it.identifier == portName]
+		Assert.isNotNull(unitPort)
+		Assert.isTrue(unitPort instanceof HierarchicalUnitPort)
+		val hUnitPort = unitPort as HierarchicalUnitPort
+		Assert.isTrue(hUnitPort.input)
+		
+		for (trgPort : hUnitPort.valueTo) {
+			val trgUnit = fmuInstanceMap.get(trgPort.unit)
+			trgUnit.setReal(trgPort.identifier, v)
+		}
+
+		// trigger value propagation
+		if (currentMode == MODE.INITING) {
+			val MAX_IT = 10 // TODO Should be a config parameter.
+			fixPointOutputs(childOutputPorts, fmuInstanceMap, MAX_IT)
+		}
 	}
 	
-	override getInnerReal(String portName){
+	override getInnerReal(String portName) {
 		/*
 		 * This method is called after the adaptations are processed.
 		 * Just get the value on the internal ports.
 		 */
-		 return 0.0
+		val unitPort = unit.ports.findFirst[it.identifier == portName]
+		Assert.isNotNull(unitPort)
+		Assert.isTrue(unitPort instanceof HierarchicalUnitPort)
+		val hUnitPort = unitPort as HierarchicalUnitPort
+		Assert.isTrue(! hUnitPort.input)
+		
+		val srcPort = hUnitPort.valueFrom
+		Assert.isNotNull(srcPort)
+		
+		val srcUnit = fmuInstanceMap.get(srcPort.unit)
+		
+		return srcUnit.getReal(srcPort.identifier)
+	}
+	
+	override doInnerStep(double inner_time, double micro_step){
+		/*
+		 * This method is called after the adaptations are processed.
+		 * The input values have been propagated.
+		 * All we have to do now is step the inner units, and propagate their values in order.
+		 */
+		 executeStep(inner_time, micro_step, nodes, inPorts, fmuInstanceMap)
+		 return Fmi2Status.OK
+	}
+	
+	override outputSnapshot(Map<OutputPortInstance, Double> outVals) {
+		getOutputSnapshot(units, fmuInstanceMap, outVals)
+		super.outputSnapshot(outVals)
+	}
+	
+	override free(){
+		freeUnits(units, fmuInstanceMap)
 	}
 	
 }

+ 2 - 0
HintCO/src/ua/ansymo/hintco/IFmuInstance.xtend

@@ -2,6 +2,7 @@ package ua.ansymo.hintco
 
 import org.intocps.fmi.Fmi2Status
 import org.intocps.fmi.FmuInvocationException
+import java.util.Map
 
 interface IFmuInstance {
 	def Fmi2Status doStep(double currentCommunicationPoint, double communicationStepSize) throws FmuInvocationException
@@ -11,4 +12,5 @@ interface IFmuInstance {
 	def double getReal(String varName)
 	def void setReal(String varName, double v)
 	def void free()	
+	def void outputSnapshot(Map<OutputPortInstance, Double> outVals)
 }

+ 5 - 6
HintCO/src/ua/ansymo/hintco/OutputProcessor.xtend

@@ -10,7 +10,7 @@ import org.eclipse.core.runtime.Assert
 class OutputProcessor implements IOutputProcessor {
 	
 	var String outDirPrefix;
-	var Map<CosimUnitInstance, CSVWriter> fmuFileMap 
+	var Map<UnitInstance, CSVWriter> fmuFileMap 
 	var String outDirPath;
 	var long outputInterval;
 	var long outputCounter;
@@ -46,14 +46,13 @@ class OutputProcessor implements IOutputProcessor {
 		Assert.isTrue(outDir.mkdirs())
 		
 		// Open csv files
-		// TODO Has to include Hierarchical Units as well.
-		for (u : scenario.eAllContents.filter(CosimUnitInstance).toIterable){
+		for (u : scenario.eAllContents.filter(UnitInstance).toIterable){
 			val f = new CSVWriter(new FileWriter(new File(outDirPath + "/" + u.identifier + ".csv")), ";", CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END) 
 			// Write header
-			f.writeNext(#["time"] + u.ports.filter(OutputPortInstance).map[p | p.identifier])
+			f.writeNext(#["time"] + u.outputPorts.map[p | p.identifier])
 			
 			// Record file handler
-			fmuFileMap.put(u as CosimUnitInstance, f)
+			fmuFileMap.put(u as UnitInstance, f)
 		}
 	}
 	
@@ -64,7 +63,7 @@ class OutputProcessor implements IOutputProcessor {
 			outputCounter = outputInterval
 			for (u : fmuFileMap.keySet){
 				val file = fmuFileMap.get(u)
-				val outVsString = u.ports.filter(OutputPortInstance)
+				val outVsString = u.outputPorts
 								.map[p | 
 										Assert.isTrue(values.containsKey(p))
 										Assert.isNotNull(values.get(p)) 

+ 70 - 4
HintCO/test/ua/ansymo/hintco/test/CosimRunnerTest.xtend

@@ -18,6 +18,11 @@ import ua.ansymo.hintco.VariantValidator
 
 import static org.junit.Assert.*
 import org.apache.commons.io.FileUtils
+import ua.ansymo.hintco.IOutputProcessor
+import ua.ansymo.hintco.RootCandidateScenario
+import java.util.Map
+import ua.ansymo.hintco.OutputPortInstance
+import static ua.ansymo.hintco.ModelQuery.*
 
 class CosimRunnerTest {
 	@Test
@@ -135,12 +140,73 @@ class CosimRunnerTest {
 	}
 	
 	@Test
-	def void executeCosimulationTest(){
-		val resultsDirPath = "results-gen/cosimTest"
+	def void executeCosimulationWaterTankTest(){
+		//val resultsDirPath = "results-gen/cosimTest"
 		val loader = new ModelStorage()
-		val runner = new CosimRunner(new OutputProcessor(resultsDirPath), new FmuLoader)
-		val generator = new CandidatesGenerator(new ConstraintChecker,new VariantValidator, new VariantProcessor(runner))
 		val src = loader.loadCandidates("instances/execute_cosim_test_watertanks.xmi")
+		
+		val Tank2WaterLevel = findIded("Tank2WaterLevel",src)
+		
+		val runner = new CosimRunner(new IOutputProcessor{
+			override initialize(RootCandidateScenario scenario, String variantID) {}
+			override terminate() {}
+			override setOutputs(int step, double time, Map<OutputPortInstance, Double> outVals) {
+				if (time > 4.0){
+					assertTrue(outVals.get(Tank2WaterLevel) > 0.5)
+				}
+			}
+		}, new FmuLoader)
+		val generator = new CandidatesGenerator(new ConstraintChecker,new VariantValidator, new VariantProcessor(runner))
+		generator.createVariantTree(src)
+		generator.generateVariants(src, 1)
+		runner.close()
+	}
+	
+	
+	@Test
+	def void executeSimpleHierCosimulationWaterTankTest(){
+//		val resultsDirPath = "results-gen/cosimHierarTest"
+		val loader = new ModelStorage()
+		val src = loader.loadCandidates("instances/execute_hier_cosim_test_watertanks.xmi")
+		
+		val envOut = findIded("envOut",src)
+		
+		val runner = new CosimRunner(new IOutputProcessor{
+			override initialize(RootCandidateScenario scenario, String variantID) {}
+			override terminate() {}
+			override setOutputs(int step, double time, Map<OutputPortInstance, Double> outVals) {
+				if (time > 4.0){
+					assertTrue(outVals.get(envOut) > 0.05)
+				}
+			}
+		}, new FmuLoader)
+//		val runner = new CosimRunner(new OutputProcessor(resultsDirPath), new FmuLoader)
+		val generator = new CandidatesGenerator(new ConstraintChecker,new VariantValidator, new VariantProcessor(runner))
+		generator.createVariantTree(src)
+		generator.generateVariants(src, 1)
+		runner.close()
+	}
+	
+	
+	@Test
+	def void executeDeepHierCosimulationWaterTankTest(){
+//		val resultsDirPath = "results-gen/cosimHierarTest"
+		val loader = new ModelStorage()
+		val src = loader.loadCandidates("instances/execute_deephier_cosim_test_watertanks.xmi")
+		
+		val envOut = findIded("envOut",src)
+		
+		val runner = new CosimRunner(new IOutputProcessor{
+			override initialize(RootCandidateScenario scenario, String variantID) {}
+			override terminate() {}
+			override setOutputs(int step, double time, Map<OutputPortInstance, Double> outVals) {
+				if (time > 4.0){
+					assertTrue(outVals.get(envOut) > 0.05)
+				}
+			}
+		}, new FmuLoader)
+//		val runner = new CosimRunner(new OutputProcessor(resultsDirPath), new FmuLoader)
+		val generator = new CandidatesGenerator(new ConstraintChecker,new VariantValidator, new VariantProcessor(runner))
 		generator.createVariantTree(src)
 		generator.generateVariants(src, 1)
 		runner.close()