Skip to content

Commit

Permalink
Improve treatment of mutually dependent sub-clock relations
Browse files Browse the repository at this point in the history
Give signal flow relatonship preference over clock relationship
See: Modelica.Clocked.Examples.CascadeControlledDrive.SubClocked
  • Loading branch information
rfranke committed Sep 2, 2021
1 parent 9949e99 commit 3deb8ba
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 38 deletions.
10 changes: 9 additions & 1 deletion OMCompiler/Compiler/BackEnd/SynchronousFeatures.mo
Expand Up @@ -685,17 +685,25 @@ protected
list<tuple<Integer,BackendDAE.SubClock>> adjParts;
array<Integer> partitionParents;
array<Boolean> partitionParentsVisited;
array<Boolean> partitionInterfacesClockVars;
algorithm
//build adjacency matrix for subclock partitions and dependency (parent) graph
partAdjacency := arrayCreate(numPartitions,{});
partitionParents := arrayCreate(numPartitions,-1);
partitionInterfacesClockVars := arrayCreate(numPartitions,false);
for subPartEq in subPartitionInterfaceEqs loop
//part1,subClk1 is the output of the sub partition interface function calls, this is used for ordering
(infered,part1,var1,subClk1,part2,var2,subClk2) := getConnectedSubPartitions(BackendEquation.get(eqs,subPartEq),varPartMap,vars);
//for adjacency relations, check only concrete sub partition interfaces not infered ones
if not intEq(part1,0) and not intEq(part2,0) then
addPartAdjacencyEdge(part1,subClk1,part2,subClk2,partAdjacency);
end if;
//reset previously obtained opposite parent relation if it interfaces clock-variables
//this is to prefer signal flow relations over clock relations in case of conflicts
if partitionParents[part2] == part1 and partitionInterfacesClockVars[part2] then
partitionParents[part2] := -1;
end if;
partitionInterfacesClockVars[part1] := not (clockedVarsMask[var1] and clockedVarsMask[var2]);
//avoid mutually dependent parents that would result in stack overflow later on
if not intEq(partitionParents[part2], part1) then
partitionParents[part1] := part2;
Expand Down Expand Up @@ -985,7 +993,7 @@ algorithm
case(BackendDAE.SUBCLOCK(_,shift,_))
then shift;
else
then MMath.RAT1;
then MMath.RAT0;
end match;
end getSubClockShift;

Expand Down
120 changes: 83 additions & 37 deletions testsuite/simulation/modelica/synchronous/MutuallyDependentClocks.mos
Expand Up @@ -10,13 +10,16 @@ setCommandLineOptions("+d=dumpSynchronous"); getErrorString();
loadString("
model MutuallyDependentClocks
Clock c = Clock(0.1);
Clock cs = subSample(c, 5); // c is parent of cs
Real x, y, z, w;
Clock cf = superSample(c, 5); // c is parent of faster cf
Clock cs = subSample(c, 5); // c is parent of slower cs
Real u, v, w, x, y, z;
equation
x = sample(time, c);
v = sample(time, c);
w = sample(time, cf);
x = subSample(w, 5); // cf becomes parent of c
y = sample(time, cs);
z = superSample(y, 5); // cs becomes parent of c
w = x + z;
u = v + x + z;
end MutuallyDependentClocks;
"); getErrorString();

Expand All @@ -30,42 +33,43 @@ translateModel(MutuallyDependentClocks); getErrorString();
// ""
// "class MutuallyDependentClocks
// Clock c = Clock(0.1);
// Clock cf = superSample(c, 5);
// Clock cs = subSample(c, 5);
// Real u;
// Real v;
// Real w;
// Real x;
// Real y;
// Real z;
// Real w;
// equation
// x = sample(time, c);
// v = sample(time, c);
// w = sample(time, cf);
// x = subSample(w, 5);
// y = sample(time, cs);
// z = superSample(y, 5);
// w = x + z;
// u = v + x + z;
// end MutuallyDependentClocks;
// "
// ""
// synchronous features pre-phase: synchronousFeatures
//
//
// ########################################
// clock partitioning (2 partitions)
// clock partitioning (3 partitions)
// ########################################
//
//
// clocked partition(1)
// ========================================
//
// Variables (3)
// Variables (1)
// ========================================
// 1: w:VARIABLE() type: Real
// 2: z:VARIABLE() type: Real
// 3: x:VARIABLE() type: Real
// 1: y:VARIABLE() type: Real
//
//
// Equations (3, 3)
// Equations (1, 1)
// ========================================
// 1/1 (1): x = $getPart(time) [dynamic |0|0|0|0|]
// 2/2 (1): z = $getPart(y) [dynamic |0|0|0|0|]
// 3/3 (1): w = x + z [dynamic |0|0|0|0|]
// 1/1 (1): y = $getPart(time) [dynamic |0|0|0|0|]
//
//
// no matching
Expand All @@ -76,12 +80,34 @@ translateModel(MutuallyDependentClocks); getErrorString();
//
// Variables (1)
// ========================================
// 1: y:VARIABLE() type: Real
// 1: w:VARIABLE() type: Real
//
//
// Equations (1, 1)
// ========================================
// 1/1 (1): y = $getPart(time) [dynamic |0|0|0|0|]
// 1/1 (1): w = $getPart(time) [dynamic |0|0|0|0|]
//
//
// no matching
//
//
// clocked partition(3)
// ========================================
//
// Variables (4)
// ========================================
// 1: z:VARIABLE() type: Real
// 2: x:VARIABLE() type: Real
// 3: v:VARIABLE() type: Real
// 4: u:VARIABLE() type: Real
//
//
// Equations (4, 4)
// ========================================
// 1/1 (1): v = $getPart(time) [dynamic |0|0|0|0|]
// 2/2 (1): x = $getPart(w) [dynamic |0|0|0|0|]
// 3/3 (1): z = $getPart(y) [dynamic |0|0|0|0|]
// 4/4 (1): u = v + x + z [dynamic |0|0|0|0|]
//
//
// no matching
Expand All @@ -90,37 +116,34 @@ translateModel(MutuallyDependentClocks); getErrorString();
//
// Base clocks (1)
// ========================================
// 1: Clock(0.1)[2]
// 1: Clock(0.1)[3]
//
//
// Sub clocks (2)
// Sub clocks (3)
// ========================================
// 1: factor(1/1) shift(0/1) event(false)
// 2: factor(5/1) shift(0/1) event(false)
// 1: factor(5/1) shift(0/1) event(false)
// 2: factor(1/5) shift(0/1) event(false)
// 3: factor(1/1) shift(0/1) event(false)
//
// synchronous features post-phase: synchronousFeatures
//
//
// ########################################
// clock partitioning (2 partitions)
// clock partitioning (3 partitions)
// ########################################
//
//
// clocked partition(1)
// ========================================
//
// Variables (3)
// Variables (1)
// ========================================
// 1: w:VARIABLE() type: Real
// 2: z:VARIABLE() type: Real
// 3: x:VARIABLE() type: Real
// 1: y:VARIABLE() type: Real
//
//
// Equations (3, 3)
// Equations (1, 1)
// ========================================
// 1/1 (1): x = $getPart(time) [dynamic |0|0|0|0|]
// 2/2 (1): z = $getPart(y) [dynamic |0|0|0|0|]
// 3/3 (1): w = x + z [dynamic |0|0|0|0|]
// 1/1 (1): y = $getPart(time) [dynamic |0|0|0|0|]
//
//
// no matching
Expand All @@ -131,12 +154,34 @@ translateModel(MutuallyDependentClocks); getErrorString();
//
// Variables (1)
// ========================================
// 1: y:VARIABLE() type: Real
// 1: w:VARIABLE() type: Real
//
//
// Equations (1, 1)
// ========================================
// 1/1 (1): y = $getPart(time) [dynamic |0|0|0|0|]
// 1/1 (1): w = $getPart(time) [dynamic |0|0|0|0|]
//
//
// no matching
//
//
// clocked partition(3)
// ========================================
//
// Variables (4)
// ========================================
// 1: z:VARIABLE() type: Real
// 2: x:VARIABLE() type: Real
// 3: v:VARIABLE() type: Real
// 4: u:VARIABLE() type: Real
//
//
// Equations (4, 4)
// ========================================
// 1/1 (1): v = $getPart(time) [dynamic |0|0|0|0|]
// 2/2 (1): x = $getPart(w) [dynamic |0|0|0|0|]
// 3/3 (1): z = $getPart(y) [dynamic |0|0|0|0|]
// 4/4 (1): u = v + x + z [dynamic |0|0|0|0|]
//
//
// no matching
Expand All @@ -145,13 +190,14 @@ translateModel(MutuallyDependentClocks); getErrorString();
//
// Base clocks (1)
// ========================================
// 1: Clock(0.1)[2]
// 1: Clock(0.1)[3]
//
//
// Sub clocks (2)
// Sub clocks (3)
// ========================================
// 1: factor(1/1) shift(0/1) event(false)
// 2: factor(5/1) shift(0/1) event(false)
// 1: factor(5/1) shift(0/1) event(false)
// 2: factor(1/5) shift(0/1) event(false)
// 3: factor(1/1) shift(0/1) event(false)
//
// true
// ""
Expand Down

0 comments on commit 3deb8ba

Please sign in to comment.