@@ -3,7 +3,7 @@ Module for structural transformation of models including alias handling and size
33
44* Developer: Hilding Elmqvist, Mogram AB
55* First version: July-August 2016
6- * Copyright (c) 2016-2018 : Hilding Elmqvist, Toivo Henningsson, Martin Otter
6+ * Copyright (c) 2016-2019 : Hilding Elmqvist, Toivo Henningsson, Martin Otter
77* License: MIT (expat)
88"""
99module StructuralTransform
@@ -13,7 +13,7 @@ using ..BLTandPantelidesUtilities
1313using .. Utilities
1414using .. BasicStructuralTransform
1515using .. Instantiation
16- import .. Instantiation: GetField, This, Der, Symbolic, time_global, get_dims
16+ import .. Instantiation: GetField, This, Der, Symbolic, time_global, get_dims, parameter
1717import .. Execution: get_value, Subs, subs, Variable, split_variables, vars_of, GetField
1818using Base. Meta: quot, isexpr
1919using DataStructures
@@ -108,11 +108,76 @@ v1 := v2
108108v3 = v2 ->
109109=#
110110
111- function findAliases! (nonAliasEquations, aliases, eq:: Expr , unknowns)
111+ function equivalence (pairs)
112+ equ = []
113+ for p in pairs
114+ for e in equ
115+ if intersect (p, e) != []
116+ if p[1 ] in e && p[2 ] in e
117+ println (" Redundant equation: $(p[1 ]) = $(p[2 ]) " )
118+ end
119+ union! (p, e)
120+ setdiff! (e, e)
121+ end
122+ end
123+ push! (equ, p)
124+ end
125+ equivalenceClasses = []
126+ for e in equ
127+ if e != []
128+ push! (equivalenceClasses, e)
129+ end
130+ end
131+ equivalenceClasses
132+ end
133+
134+ function findAliases2! (nonAliasEquations, aliases, equations, variables, defined)
135+ equivalencePairs = []
136+ for eq in equations
137+ if ! isexpr (eq, :quote )
138+ if eq. head in [:(= ), :(:= )]
139+ e1 = eq. args[1 ]
140+ e2 = eq. args[2 ]
141+ if typeof (e1) == GetField && typeof (e2) == GetField
142+ push! (equivalencePairs, [e1. name, e2. name])
143+ else
144+ push! (nonAliasEquations, eq)
145+ end
146+ end
147+ end
148+ end
149+ equivalenceClasses = equivalence (equivalencePairs)
150+ for equiv in equivalenceClasses
151+ nonalias = nothing
152+ for v in equiv
153+ if typeof (variables[v]) != Variable || variables[v]. variability <= parameter
154+ nonalias = GetField (This (), v)
155+ break
156+ end
157+ end
158+ if nonalias == nothing
159+ nonalias = GetField (This (), equiv[1 ]) # No non-Variable or parameter to define as nonalias, pick first
160+ end
161+ for v in equiv
162+ if v != nonalias. name
163+ aliases[GetField (This (), v)] = nonalias
164+ if typeof (variables[v]) != Variable || variables[v]. variability <= parameter
165+ if " $(variables[v]) " != " $(variables[nonalias. name]) "
166+ println (" Non consistent constraint: $v = $(nonalias. name) : $(variables[v]) != $(variables[nonalias. name]) " )
167+ end
168+ end
169+ end
170+ end
171+ end
172+ end
173+
174+
175+ function findAliases! (nonAliasEquations, aliases, eq:: Expr , unknowns, defined)
112176 if ! isexpr (eq, :quote )
113177 if eq. head in [:(= ), :(:= )]
114178 e1 = eq. args[1 ]
115179 e2 = eq. args[2 ]
180+ @show e1 e2
116181 if typeof (e1) == GetField && typeof (e2) == GetField && haskey (unknowns, e1. name) && haskey (unknowns, e2. name) # && unknowns[e1.name].state && unknowns[e2.name].state
117182 # nonAliases = collect(values(aliases))
118183 # if ! haskey(aliases, e1) && ! (e1 in nonAliases) && ! haskey(aliases, e2) && ! (e2 in nonAliases)
@@ -121,15 +186,46 @@ function findAliases!(nonAliasEquations, aliases, eq::Expr, unknowns)
121186 aliases[e1] = e2
122187 unknowns[e2. name]. state = unknowns[e1. name]. state
123188 # @show e2.name, unknowns[e2.name].state
189+ println ()
124190 elseif ! haskey (aliases, e2) && getNonAliasVariable (aliases, e1, unknowns)[1 ] != e2 && if haskey (unknowns, e1. name); unknowns[e1. name]. state else false end
125191 aliases[e2] = e1
126192 unknowns[e1. name]. state = unknowns[e2. name]. state
127- # @show e1.name, unknowns[e1.name].state
128- else
193+ @show e1. name, unknowns[e1. name]. state
194+ else
129195 println (" Circular aliases between: $e1 and $e2 " )
130- error (" Aborting" )
196+ # error("Aborting")
131197 end
198+ elseif typeof (e1) == GetField && typeof (e2) == GetField && (haskey (unknowns, e1. name) || haskey (unknowns, e2. name))
199+ println (" One is unknown:" )
200+ println (eq)
201+ if haskey (unknowns, e1. name)
202+ var = e1. name
203+ val = e2. name
204+ else
205+ var = e2. name
206+ val = e1. name
207+ end
208+ @show var
209+ @show aliases
210+ if haskey (aliases, var)
211+ var = aliases[var]
212+ @show aliases[var]
213+ end
214+ @show defined
215+ if ! haskey (defined, var)
216+ defined[var] = val
217+ @show defined
218+ println (" Adding: " , eq)
219+ push! (nonAliasEquations, eq)
220+ elseif defined[var] != val
221+ println (" Non consistent overdetermined variable:" )
222+ println (" $var = $val " )
223+ println (" $var = $defined [var]" )
224+ else
225+ println (" Not added: " , eq)
226+ end
132227 else
228+ println (eq)
133229 push! (nonAliasEquations, eq)
134230 end
135231 end
@@ -182,11 +278,16 @@ function performAliasElimination!(flat_model, unknowns, params, equations)
182278 loglnModia (" \n ALIAS ELIMINATION" )
183279 aliases = AliasSubs ()
184280 nonAliasEquations = []
281+ defined = Dict ()
185282
283+ nonAliasEquations = []
284+ findAliases2! (nonAliasEquations, aliases, equations, merge (unknowns, params), defined)
285+
286+ #=
186287 for eq in equations
187- findAliases! (nonAliasEquations, aliases, eq, unknowns)
288+ findAliases!(nonAliasEquations, aliases, eq, unknowns, defined )
188289 end
189-
290+ =#
190291 loglnModia (" \n Alias equations" )
191292 for a in aliases
192293 loglnModia (prettyfy (a[1 ]), " = " , prettyfy (a[2 ]))
@@ -195,7 +296,7 @@ function performAliasElimination!(flat_model, unknowns, params, equations)
195296 loglnModia (" \n Alias definitions" )
196297 for a in aliases
197298 (nonAlias, state) = getNonAliasVariable (aliases, a[2 ], unknowns)
198- unknowns[nonAlias. name]. state = state
299+ # unknowns[nonAlias.name].state = state # Temporarily
199300 loglnModia (prettyfy (a[1 ]), " := " , prettyfy (nonAlias))
200301 end
201302
@@ -248,7 +349,7 @@ Types and sizes can be inferred from the start values provided. An outline of su
248349 - If only one remaining unknown, solve for it.
249350 - Check if the equation only has +/- operators and at least one variable has known size and type. If so, copy size and type to the other variables.
250351
251- Note: This function should be rewritten to ensure conssistency , etc.
352+ Note: This function should be rewritten to ensure consistency , etc.
252353"""
253354function deduceVariableAndEquationSizes (flat_model, unknowns, params, equations)
254355 loglnModia (" \n SIZE AND TYPE DEDUCTION" )
@@ -350,10 +451,10 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
350451 try
351452 E = eval (e)
352453 catch err
353- if isa (err, ErrorException) && contains (err . msg, " Unit mismatch" )
454+ if isa (err, ErrorException) && occursin ( " Unit mismatch" , err . msg )
354455 loglnModia (" Warning: " , err. msg,
355- " \n in expression: " , prettyPrint (e),
356- " \n in equation: " , prettyPrint (eq))
456+ " \n in expression: " , prettyPrint (e),
457+ " \n in equation: " , prettyPrint (eq))
357458 end
358459 E
359460 end
@@ -463,6 +564,7 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
463564 RHS = tryEval (rhs, eq)
464565 if RHS != nothing && typeof (RHS) != GetField && typeof (RHS) != Der
465566 if typeof (RHS) == String || fieldnames (typeof (RHS)) != emptyFieldNames || typeof (RHS) == Tuple{Array{Float64,2 },Array{Float64,2 }} # Special case for calling qr function
567+ # Using isstructtype(typeof(RHS)) did not work as expected so fieldnames(typeof(RHS)) != emptyFieldNames is used instead
466568 size_RHS = ()
467569 else
468570 size_RHS = size (RHS)
@@ -499,20 +601,27 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
499601 else
500602 size_RHS = size (RHS)
501603 end
502-
503- if size (LHS) != size_RHS
604+ #=
605+ if typeof(LHS) == String || typeof(LHS) != AbstractArray || fieldnames(typeof(LHS)) != emptyFieldNames
606+ size_LHS = ()
607+ else
608+ size_LHS = size(LHS)
609+ end
610+ =#
611+ size_LHS = size (LHS)
612+ if size_LHS != size_RHS
504613 loglnModia (" Warning: Not equal size of left and right hand side in equation $(prettyPrint (eq)) : $LHS = $RHS " )
505614 end
506615
507616 e = promote (LHS, RHS)
508617 t = typeof (e[1 ])
509618 # loglnModia("ASSERT: ", typeof(LHS), " == ", typeof(RHS))
510- loglnModia (" SIZE = " , size (LHS) , " \t TYPE = " , t, " \t " , prettyPrint (eq))
511- equSizes[i] = size (LHS)
619+ loglnModia (" SIZE = " , size_LHS , " \t TYPE = " , t, " \t " , prettyPrint (eq))
620+ equSizes[i] = size_LHS
512621 equTypes[i] = t
513622 equationSubs[i] = eqsubs
514623 #= Fix for call back function
515- elseif LHS != nothing && typeof(LHS) != Der
624+ elseif LHS != nothing && typeof(LHS) != Der
516625 t = typeof(LHS)
517626 loglnModia("SIZE = ", size(LHS), " \tTYPE = ", t, " \t", prettyPrint(eq))
518627 equSizes[i] = size(LHS)
0 commit comments