Opened 7 years ago

Last modified 6 years ago

#4496 assigned defect

Complex 'sum' does not work

Reported by: Christian Kral <dr.christian.kral@…> Owned by: Per Östlund
Priority: blocker Milestone: 2.0.0
Component: New Instantiation Version:
Keywords: Cc: Lennart Ochel, Mahder Alemseged Gebremedhin

Description

Please consider the following example:

model TestComplexSum
  parameter Complex a[2]={Complex(1,2),Complex(2,3)};
  parameter Complex sum1 = Modelica.ComplexMath.'sum'(a);
  parameter Complex sum2 = Complex(sum(a.re),sum(a.im));
end TestComplexSum;

The sum of vector a is calculated in two different ways, so the results shall be equal. However, in OpenModelica sum2 is calculated correctly, whereas sum1 results in

sum1.re -> 0
sum2.re -> 0

Too bad: The application of function 'sum' is utilized in the actual trunk version of the MSL in order to calculate the the total apparent power in Modelica.Electrical.QuasiStationary.MultiPhase.Sensors.MultiSensor. I would not really like to switch to the alternative calculation of sum1...

Do you think there is a chance, that this issue is going to be fixed in OpenModelica 1.12? The reason I am asking is that I am planning to refer to OpenModelica in a publication so, so I am not sure if can include a related example or not.

Change History (21)

comment:1 by Adeel Asghar, 7 years ago

Cc: Lennart Ochel added
Component: OMEditRun-time
Owner: changed from Adeel Asghar to Willi Braun
Status: newassigned

comment:2 by Martin Sjölund, 7 years ago

Modifying ComplexMath.'sum' to be the same as sum2 instead causes the record equation to be lost... The problem is in the frontend.

comment:3 by Martin Sjölund, 7 years ago

Component: Run-timeFrontend

comment:4 by Martin Sjölund, 7 years ago

I had a look at this today, and part of the problem is that the binding can't be split due to it being a record. And if we move the binding to the initial equation section, there is a problem because the parameter is not fixed. Which means we would need to change that or introduce some new concept for handling bindings of initial record equations in a special way.

There is also a problem with v[:].re, which seems to return the empty array {} (which means a constant 0 as the sum).

And there is additionally a problem with the inline operation: it seems this becomes sum(v.re) rather than sum(a.re).

I would guess we can't fix all of these issues in time for 1.12 (especially considering we were supposed to feature freeze that and move it to the maintenance branch some month(s) ago).

comment:5 by Martin Sjölund, 7 years ago

There is also a problem with code generation for the expression v.re, and it looks like the problem there is that the code generator thinks v.re is a scalar. It's also not possible to rewrite the expression as sum(c.re for c in v).

in reply to:  4 comment:6 by massimo ceraolo, 7 years ago

I would guess we can't fix all of these issues in time for 1.12 (especially considering we were supposed to feature freeze that and move it to the maintenance branch some month(s) ago).

There are sevetal tickets open on complex numbers.
Maybe a plan can be made after 1.12 release to address most of them?
It seems that better complex nmber support is wished by many (I'm one of them)

Version 0, edited 7 years ago by massimo ceraolo (next)

comment:7 by Christian Kral <dr.christian.kral@…>, 7 years ago

Thanks for the feedback.

An improved complex number support is quite important to me and the classes I am teaching. I use OpenModelica a lot on quasi static analysis.

comment:8 by Francesco Casella, 7 years ago

Cc: Mahder Alemseged Gebremedhin added

It would be good to be sure that at least the new front-end deals with this correctly.

Maybe Mahder could have a look?

comment:10 by Christian Kral <dr.christian.kral@…>, 7 years ago

This is a workaround to overcome issues of Modelica.Electrical.QuasiStationary.MultiPhase.Sensors.MultiSensor

comment:11 by Martin Sjölund, 7 years ago

The following would work in v1.13 (not 1.12), but would give additional messages:

function 'sum' "Return sum of complex vector"
  input Complex v[:] "Vector";
  output Complex result "Complex sum of vector elements";
algorithm
  result:=Complex(sum(v[i].re for i in 1:size(v,1)), sum(v[i].im for i in 1:size(v,1)));
  annotation(Inline=true);
end 'sum';

model TestComplexSum1
  parameter Complex a[2]={Complex(1,2),Complex(2,3)};
  parameter Complex sum1 = 'sum'(a);
  parameter Complex sum2 = Complex(sum(a.re),sum(a.im));
end TestComplexSum1;
Notification: Moving binding to equation section and setting fixed attribute of sum1.re to false. This is done to work around a compiler design flaw (there is no good way to represent bindings that span multiple variables).
Notification: Moving binding to equation section and setting fixed attribute of sum1.im to false. This is done to work around a compiler design flaw (there is no good way to represent bindings that span multiple variables).

comment:12 by Francesco Casella, 7 years ago

Wow. I think we should remove the phrase:

This is done to work around a compiler design flaw (there is no good way to
represent bindings that span multiple variables).

as it may scare off the user unnecessarily. Also, there's no need to advertise compiler design flaws if there are good workarounds; moving a parameter binding equation to the initial equation section is ok.

Last but not least, I guess you should write "Moving binding to *initial* equation section...".

comment:14 by Christian Kral <dr.christian.kral@…>, 7 years ago

comment:15 by dr.christian.kral@…, 7 years ago

Due to a wrong calculation of the complex sum in the quasi static current sensor (was calculated to be zero in OM, even though it shall be non-zero) in model https://github.com/christiankral/HanserModelica/blob/master/HanserModelica/InductionMachines/IMC_DOL.mo I changed the implementation of the calculation of the complex sum in:

This is a workaround for now, even though the next release of OM may not be affected by changes of the MSL trunk or maint/3.2.2.

Does anyone have a suggestion how this issue can be targeted in a better way?

comment:16 by Francesco Casella, 6 years ago

Component: FrontendNew Instantiation
Milestone: Future2.0.0

I gave a fresh look at this issue with the new front end. If you run the TestComplexSum model with -d=newInst, the result is a compile-time error:

TestComplexSum_functions.c: In function 'omc_Modelica_ComplexMath__omcQuot_73756D':
TestComplexSum_functions.c:54:154: error: expected expression before ')' token
   tmp3 = omc_Complex__omcQuot_636F6E7374727563746F72_fromReal(threadData, sum_real_array(((Complex*)(generic_array_element_addr(&_v, sizeof(Complex), 1, )))->_re), sum_real_array(((Complex*)(generic_array_element_addr(&_v, sizeof(Complex), 1, )))->_im));

The flattened model contains calls to functions that are meant to be inlined:

class TestComplexSum
  parameter Real a[1].re(fixed = false) "Real part of complex number";
  parameter Real a[1].im(fixed = false) "Imaginary part of complex number";
  parameter Real a[2].re(fixed = false) "Real part of complex number";
  parameter Real a[2].im(fixed = false) "Imaginary part of complex number";
  parameter Real sum1.re(fixed = false) "Real part of complex number";
  parameter Real sum1.im(fixed = false) "Imaginary part of complex number";
  parameter Real sum2.re(fixed = false) "Real part of complex number";
  parameter Real sum2.im(fixed = false) "Imaginary part of complex number";
initial equation
  sum2 = Complex.'constructor'.fromReal(sum(a.re), sum(a.im));
  sum1 = Modelica.ComplexMath.'sum'(a);
  a[2] = Complex.'constructor'.fromReal(2.0, 3.0);
  a[1] = Complex.'constructor'.fromReal(1.0, 2.0);
end TestComplexSum;

Unfortunately, the inlining does not take place, as it is apparent from the output of -d=optdaedump

Equations (4, 8) 
======================================== 
1/1 (2): sum2 = Complex(sum(a.re), sum(a.im))   [dynamic |0|0|0|0|] 
2/3 (2): sum1 = Modelica.ComplexMath.'sum'(a)   [dynamic |0|0|0|0|] 
3/5 (2): a[2] = Complex(2.0, 3.0)   [dynamic |0|0|0|0|] 
4/7 (2): a[1] = Complex(1.0, 2.0)   [dynamic |0|0|0|0|] 

I understand in this case the backend should inline the function calls, eventually reducing the initial equations for the parameter values to eight scalar equations. Maybe the inline annotation gets lost, @perost can you please check?

comment:17 by Francesco Casella, 6 years ago

One of the reasons of this failure could be #4354: initial equations are not inlined, and this causes issues.

comment:18 by Francesco Casella, 6 years ago

See also #5236

comment:19 by Francesco Casella, 6 years ago

Owner: changed from Willi Braun to Per Östlund

Running this model with the latest nightly an the NF I now obtain this NF error:

[1] 23:52:32 Translation Error
[C:/dev/OM64bit/OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo: 387:9-388:53]:
Internal error NFEvalFunction.applyReplacementCref could not find
replacement for v[:].re

comment:20 by Francesco Casella, 6 years ago

Priority: highblocker

I now get the following error during C compilation

TestComplexSum_functions.c: In function 'omc_Modelica_ComplexMath__omcQuot_2773756D27':
TestComplexSum_functions.c:55:158: error: expected expression before ')' token
   tmp3 = omc_Complex__omcQuot_27636F6E7374727563746F7227_fromReal(threadData, sum_real_array(((Complex*)(generic_array_element_addr(&_v, sizeof(Complex), 1, )))->_re), sum_real_array(((Complex*)(generic_array_element_addr(&_v, sizeof(Complex), 1, )))->_im));
                                                                                                                                                              ^

comment:21 by Francesco Casella, 6 years ago

The flattened model is:

class TestComplexSum
  parameter Real a[1].re = 1.0 "Real part of complex number";
  parameter Real a[1].im = 2.0 "Imaginary part of complex number";
  parameter Real a[2].re = 2.0 "Real part of complex number";
  parameter Real a[2].im = 3.0 "Imaginary part of complex number";
  parameter Real sum1.re(fixed = false) "Real part of complex number";
  parameter Real sum1.im(fixed = false) "Imaginary part of complex number";
  parameter Real sum2.re(fixed = false) "Real part of complex number";
  parameter Real sum2.im(fixed = false) "Imaginary part of complex number";
initial equation
  sum1 = Modelica.ComplexMath.'sum'(a);
  sum2 = Complex.'constructor'.fromReal(a[1].re + a[2].re, a[1].im + a[2].im);
end TestComplexSum;

I guess with the current BE we need the NF to expand the two initial equations, particularly the first one. In the future, the array-preserving BE should be capable to handle these equations right away.

Note: See TracTickets for help on using tickets.