marco-compiler / marco

Modelica Advanced Research COmpiler
GNU Lesser General Public License v3.0
18 stars 5 forks source link

Test cases for Complex operator record support in MARCO #8

Open casella opened 10 months ago

casella commented 10 months ago

Here is a bunch of tests for the support of the Complex operator record in MARCO, borrowed from OpenModelica/OpenModelica#11504:

package ComplexTest
  model T01
    parameter Complex z1 = Complex(1);
    parameter Complex z2 = Complex(0, 1);
    parameter Complex z3 = z1 + z2;
    Complex z4, z5;
  equation
    z4 = z1*z2;
    z5 = z1/z2;
  end T01;

  model T02
    Complex z1 = Complex(1);
    Complex z2 = Complex(0, 1);
    Complex z3, z4, z5;
  equation
    z3 = z1 + z2;
    z4 = z1*z2;
    z5 = z1/z2;
  end T02;

  model T03
    Complex z1;
    Complex z2;
    Complex z3, z4, z5;
  equation
    z1 = Complex(1);
    z2 = Complex(0, 1);
    z3 = z1 + z2;
    z4 = z1*z2;
    z5 = z1/z2;
  end T03;

  model T04
    Complex z1, z2, z3, z4, z5;
  equation
    z1 = Complex(time,0);
    z2 = Complex(0,1);
    z3 = z1 + z2;
    z4 = z1*z2;
    z5 = z1/z2;
  end T04; 

  model T05
    Complex z1;
  equation
    z1  = Complex(time,0);
  end T05;

  model T06
    Complex z1 = Complex(time,0);
  equation
  end T06;

  model T07
    Complex z1 = Complex(time,0);
    Complex z2 = Complex(0, 1);
    Complex z3, z4, z5;
  equation
    z3 = z1 + z2;
    z4 = z1*z2;
    z5 = z1/z2;
  end T07;

  model T08
    parameter Real v_re_start = 1;
    parameter Real v_im_start = 0;
    parameter Real i_re_start = 1;
    parameter Real i_im_start = -0.3;
    parameter Complex Z = Complex(0.03,0.1);
    Complex v0 = Complex(1);
    Complex v(re(start = v_re_start), im(start = v_im_start));
    Complex i(re(start = i_re_start), im(start = i_im_start));
  equation
    v = v0 - Z*i;
    v*Modelica.ComplexMath.conj(i) = Complex(1,0.2);
  end T08;

  model T09
    parameter Real v_re_start = 1;
    parameter Real v_im_start = 0;
    parameter Real i_re_start = 1;
    parameter Real i_im_start = -0.3;
    parameter Complex Z = Complex(0.03,0.1);
    Complex v0 = Complex(1);
    Complex v(re(start = v_re_start), im(start = v_im_start));
    Complex i(re(start = i_re_start), im(start = i_im_start));
    Real P,Q;
  equation
    v = v0 - Z*i;
    P = 1 + 0.1*time;
    Q = 0.2 + 0.1*time;
    v*Modelica.ComplexMath.conj(i) = Complex(P, Q);
  end T09;
  model T10
    Real a = 1;
    Real b = 1;
    Complex z(re = a, im = b);
  end T10;

annotation(uses(Complex));
end ComplexTest;

@mscuttari, can you please report on the current status with the latest development version of the compiler?

mscuttari commented 10 months ago
- `T05` compiles and simulates successfully. The output of the simulation is the following:

"time","z1.im","z1.re" 0.000000000,0.000000000,0.000000000 0.100000000,0.000000000,0.100000000 0.200000000,0.000000000,0.200000000 ... 9.800000000,0.000000000,9.800000000 9.900000000,0.000000000,9.900000000 10.000000000,0.000000000,10.000000000

- `T06` compiles and simulates successfully. The output of the simulation is the following:

"time","z1.im","z1.re" 0.000000000,0.000000000,0.000000000 0.100000000,0.000000000,0.100000000 0.200000000,0.000000000,0.200000000 ... 9.800000000,0.000000000,9.800000000 9.900000000,0.000000000,9.900000000 10.000000000,0.000000000,10.000000000

- `T07` compiles and simulates successfully. The output of the simulation is the following:

"time","z1.im","z1.re","z2.im","z2.re","z3.im","z3.re","z4.im","z4.re","z5.im","z5.re" 0.000000000,0.000000000,0.000000000,1.000000000,0.000000000,1.000000000,0.000000000,0.000000000,0.000000000,0.000000000,0.000000000 0.100000000,0.000000000,0.100000000,1.000000000,0.000000000,1.000000000,0.100000000,0.100000000,0.000000000,-0.100000000,0.000000000 0.200000000,0.000000000,0.200000000,1.000000000,0.000000000,1.000000000,0.200000000,0.200000000,0.000000000,-0.200000000,0.000000000 ... 9.800000000,0.000000000,9.800000000,1.000000000,0.000000000,1.000000000,9.800000000,9.800000000,0.000000000,-9.800000000,0.000000000 9.900000000,0.000000000,9.900000000,1.000000000,0.000000000,1.000000000,9.900000000,9.900000000,0.000000000,-9.900000000,0.000000000 10.000000000,0.000000000,10.000000000,1.000000000,0.000000000,1.000000000,10.000000000,10.000000000,0.000000000,-10.000000000,0.000000000


- `T08` currently does not link due to problems with the SUNDIALS libraries on my local machine. I will investigate.
- `T09` has the same problem of `T08`
mscuttari commented 10 months ago

T08 (and possibly T09) also leads to problems during the equation explicitation phase. However, the record expansion and function inlining work correctly, so this is not a problem strictly related to record handling.

casella commented 10 months ago

Very good news, the results reported for T01-T07 are indeed correct 😃

For power system models to work, we also need to get IDA to work, so that last part is also required.

casella commented 10 months ago

@mscuttari I added T10 to the test cases, this is another pattern used by PowerGrids, please check that it works.

I would suggest to add the updated version of ComplexTest to the marco testsuite, so we make sure these features do not get broken.

mscuttari commented 9 months ago

Regarding the problems about T08 using IDA, I've been checking the Jacobian matrix computed by MARCO and it is indeed coherent with its input data. The problem, instead, relies in OpenModelica not properly handling the start attributes:

omc Record.mo -f -i=ComplexTest.T08 -d=nonfScalarize,arrayConnect,combineSubscripts,printRecordTypes,evaluateAllParameters,vectorizeBindings --showStructuralAnnotations

model 'ComplexTest.T08'
function 'Complex.\'*\'.multiply' "Multiply two complex numbers"
  input 'Complex' 'c1';
  input 'Complex' 'c2';
  output 'Complex' 'c3';
algorithm
  'c3' := 'Complex.\'constructor\'.fromReal'('c1'.'re' * 'c2'.'re' - 'c1'.'im' * 'c2'.'im', 'c1'.'re' * 'c2'.'im' + 'c1'.'im' * 'c2'.'re');
  annotation(Inline = true);
end 'Complex.\'*\'.multiply';

function 'Complex.\'-\'.subtract' "Subtract two complex numbers"
  input 'Complex' 'c1';
  input 'Complex' 'c2';
  output 'Complex' 'c3';
algorithm
  'c3' := 'Complex.\'constructor\'.fromReal'('c1'.'re' - 'c2'.'re', 'c1'.'im' - 'c2'.'im');
  annotation(Inline = true);
end 'Complex.\'-\'.subtract';

function 'Complex.\'constructor\'.fromReal' "Construct Complex from Real"
  input Real 're';
  input Real 'im' = 0.0;
  output 'Complex' 'result';
algorithm
  annotation(Inline = true);
end 'Complex.\'constructor\'.fromReal';

function 'Modelica.ComplexMath.conj' "Conjugate of complex number"
  input 'Complex' 'c1';
  output 'Complex' 'c2';
algorithm
  'c2' := 'Complex.\'constructor\'.fromReal'('c1'.'re', -'c1'.'im');
  annotation(Inline = true);
end 'Modelica.ComplexMath.conj';

record 'Complex'
  parameter Real 're';
  parameter Real 'im';
end 'Complex';

  parameter 'Complex' 'Z' = 'Complex'(0.03, 0.1);
  'Complex' 'v0' = 'Complex'(1.0, 0.0);
  'Complex' 'v';
  'Complex' 'i';
equation
  'v' = 'Complex.\'-\'.subtract'('v0', 'Complex.\'*\'.multiply'('Complex'(0.03, 0.1), 'i'));
  'Complex.\'*\'.multiply'('v', 'Modelica.ComplexMath.conj'('i')) = 'Complex'(1.0, 0.2);
end 'ComplexTest.T08';

Notice how v and i don't have start values. Because of this, the variables v.re, v.im, i.re and i.im gets initialized with the zero value and the Jacobian matrix then becomes singular.

The same happens with model T09.

casella commented 8 months ago

See #12 and OpenModelica/OpenModelica#11792

casella commented 3 months ago

I pinged Per on the OpenModelica issue, let's see if he can fix that before Michele is back from Norway.