Opened 6 years ago
Closed 6 years ago
#5116 closed task (fixed)
The NF does not constant-evaluate parameter binding equations in the MSL
Reported by: | Francesco Casella | Owned by: | Per Östlund |
---|---|---|---|
Priority: | high | Milestone: | 2.0.0 |
Component: | New Instantiation | Version: | |
Keywords: | Cc: |
Description
Please consider Modelica.Magnetic.FundamentalWave.Examples.BasicMachines.AIMC_Conveyor. When using the NF, the compilation of the C code fails with errors on expressions involving sine and cosine function calls on temp variables. One of them is
tmp6._re = (cos(tmp7)) * (tmp8._re) - ((sin(tmp12)) * (tmp13._im));
The root cause of the problem are these binding equations:
final parameter Complex N=effectiveTurns*Modelica.ComplexMath.exp(Complex( 0, orientation)) "Complex number of turns";
with both effectiveTurns
and orientation
having Evaluate=true
. The old FE correctly constant-evaluates them, producing
final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[3].N.re = -0.5000000000000004 "Real part of complex number"; final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[3].N.im = -0.8660254037844384 "Imaginary part of complex number"; final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[2].N.re = -0.4999999999999998 "Real part of complex number"; final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[2].N.im = 0.8660254037844387 "Imaginary part of complex number"; final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[1].N.re = 1.0 "Real part of complex number"; final parameter Real aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[1].N.im = 0.0 "Imaginary part of complex number";
The NF instead does not recognize that these binding equations should be constant-evaluated, so it adds fixed = false
to the parameter declaration and moves the binding equations to the initial equation section
aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[3].N = Complex.'*'.multiply(array(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal({1.0, 1.0, 1.0}[$i1], 0.0) for $i1 in 1:3), Modelica.ComplexMath.exp(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal(0.0, {0.0, 2.094395102393195, 4.188790204786391}))); aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[2].N = Complex.'*'.multiply(array(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal({1.0, 1.0, 1.0}[$i1], 0.0) for $i1 in 1:3), Modelica.ComplexMath.exp(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal(0.0, {0.0, 2.094395102393195, 4.188790204786391}))); aimc.rotorCage.electroMagneticConverter.singlePhaseElectroMagneticConverter[1].N = Complex.'*'.multiply(array(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal({1.0, 1.0, 1.0}[$i1], 0.0) for $i1 in 1:3), Modelica.ComplexMath.exp(Modelica.SIunits.ComplexMagneticFlux.'constructor'.fromReal(0.0, {0.0, 2.094395102393195, 4.188790204786391})));
Then, they ride through the whole back-end as
10/18 (2): aimc.stator.electroMagneticConverter.singlePhaseElectroMagneticConverter[3].N = Complex(cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re - sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im, sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re + cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im) [dynamic |0|0|0|0|] 11/20 (2): aimc.stator.electroMagneticConverter.singlePhaseElectroMagneticConverter[2].N = Complex(cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re - sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im, sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re + cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im) [dynamic |0|0|0|0|] 12/22 (2): aimc.stator.electroMagneticConverter.singlePhaseElectroMagneticConverter[1].N = Complex(cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re - sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im, sin({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.re + cos({0.0, 2.094395102393195, 4.188790204786391}) * {Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0)}.im) [dynamic |0|0|0|0|]
without being expanded, ultimately leading to the generation of wrong code.
Contrary to #5115, my understanding is that the NF should indeed constant-evaluate those binding equations because the parameter is final and it only depends on literal constants and parameters with Evaluate = true
Attachments (1)
Change History (6)
comment:1 by , 6 years ago
comment:2 by , 6 years ago
The issue is that orientation
is constant evaluated by the NF, but the evaluation is done before the flattening. This means that the scalar orientation
in the singlePhaseElectroMagneticConverter
instance is replaced with the array {0.0, 2.094395102393195, 4.188790204786391}
, since the instance is an array with an array modifier.
During the flattening we then have no information that the array value came from a modifier that should be split, resulting in a call (shortened) Modelica.ComplexMath.exp(Complex(0.0, {0.0, 2.094, 4.188}))
that the function evaluation fails on since the second field of the record argument shouldn't be an array at that point.
One solution is to introduce a new kind of expression that can store the information needed by the flattening to split it correctly. Another solution is to not evaluate constants/structural parameters during the typing, but rather after the flattening. I'm not sure which is best, and we might in fact need both.
follow-up: 4 comment:3 by , 6 years ago
Why not doing both, just in case? Is there a risk of significant overhead?
comment:4 by , 6 years ago
Replying to casella:
Why not doing both, just in case? Is there a risk of significant overhead?
Not really, just takes time to implement.
comment:5 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
This was fixed a while ago by cadad33. The model still fails to compile, but only due to the usual record issues it seems.
Related to #5084, which is still not yet solved. In that case, though, there was only one parameter in the function, while here there are many.