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: casella Owned by: perost
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)

test.mo (2.7 KB) - added by perost 6 years ago.
Minimal model

Download all attachments as: .zip

Change History (6)

comment:1 Changed 6 years ago by casella

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.

comment:2 Changed 6 years ago by perost

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.

Changed 6 years ago by perost

Minimal model

comment:3 follow-up: Changed 6 years ago by casella

Why not doing both, just in case? Is there a risk of significant overhead?

comment:4 in reply to: ↑ 3 Changed 6 years ago by perost

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 Changed 6 years ago by perost

  • Resolution set to fixed
  • Status changed from new to 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.

Note: See TracTickets for help on using tickets.