Opened 9 years ago

Last modified 7 years ago

#3526 new defect

Code generation fails for array in records

Reported by: Lennart Ochel Owned by: Lennart Ochel
Priority: high Milestone: Future
Component: Code Generation Version:
Keywords: record array Cc: Mahder Alemseged Gebremedhin, jan.hagemann@…

Description

Template CodegenUtil.ScalarVariableType failed fort he following model:

model test
  record R
    Real r[3];
  end R;

  function f
    input Real x;
    output R y;
  algorithm
    y.r[1] := 1.0+x;
    y.r[2] := 2.0+x;
    y.r[3] := 3.0+x;
  end f;

  R x;
  R y;
equation
  x = y;
  y = f(time);
end test;

Maybe this is also related to the module removeSimpleEquations, since the model works fine if it get disabled using --removeSimpleEquations=none.

Change History (10)

comment:1 by Lennart Ochel, 9 years ago

Mahder do you think this should be fixed in the templates or in the back end?

comment:2 by Mahder Alemseged Gebremedhin, 9 years ago

This is a backend problem. The generation fails on a variable named $TMP_test_R4.r. This looks like an automatically generated variable as a result of some processing. The type of the variable is ARRAY. Which is where the problem is. It should be a scalar. I think the subscripts form whatever this variable was based on are ignored somehow.

Since all arrays are expanded in a simulation model there was no rule to handle array types in ScalarVariableType (which btw is only used for the _init.xml) file it seems.

do you know where this $TMP_* var could be coming from? Somewhere in removeSimpleEquations() I will try to find it and see what happened.

comment:3 by Lennart Ochel, 9 years ago

removeSimpleEquations expands y = f(time) to test.R({x1.r[1], x1.r[2], x1.r[3]}) = test.f(time). That kind of expression is handled wrong in SimCode. Due to missing optimization this is handled as nonlinear system for which the temporary variable is introduced which contains wrong type information (see SimCodeUtil.createTempVars).

Even if the type information would be correct the model will still fail. That can be tested using following model:

model test
  record R
    Real r[3];
  end R;

  function f
    input Real x;
    output R y;
  algorithm
    y.r[1] := 1.0+x;
    y.r[2] := 2.0+x;
    y.r[3] := 3.0+x;
  end f;

  Real a[3];
equation
  R({a[1], a[2], a[3]}) = f(time);
end test;
Last edited 9 years ago by Lennart Ochel (previous) (diff)

comment:4 by Lennart Ochel, 9 years ago

PR269 should fix the wrong type information. Therewith, both models from above will lead to the same error for the generated c code.

test_02nls.c:87:50: warning: implicit declaration of function '$P$TMP_test_R1$Pr_index' is invalid in C99 [-Wimplicit-function-declaration]
  real_array_create(&tmp1007, ((modelica_real*)&($P$TMP_test_R1$Pr_index(((modelica_integer) 1)))), 1, 3);
                                                 ^
test_02nls.c:87:48: error: cannot take the address of an rvalue of type 'int'
  real_array_create(&tmp1007, ((modelica_real*)&($P$TMP_test_R1$Pr_index(((modelica_integer) 1)))), 1, 3);
                                               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_02nls.c:88:10: error: assigning to 'double' from incompatible type 'real_array_t' (aka 'struct base_array_s')
  res[0] = sub_alloc_real_array(tmp1006, tmp1007);
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_02nls.c:139:50: warning: implicit declaration of function '$P$TMP_test_R4$Pr_index' is invalid in C99 [-Wimplicit-function-declaration]
  real_array_create(&tmp1010, ((modelica_real*)&($P$TMP_test_R4$Pr_index(((modelica_integer) 1)))), 1, 3);
                                                 ^
test_02nls.c:139:48: error: cannot take the address of an rvalue of type 'int'
  real_array_create(&tmp1010, ((modelica_real*)&($P$TMP_test_R4$Pr_index(((modelica_integer) 1)))), 1, 3);
                                               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_02nls.c:140:10: error: assigning to 'double' from incompatible type 'real_array_t' (aka 'struct base_array_s')
  res[0] = sub_alloc_real_array(tmp1009, tmp1010);
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings and 4 errors generated.

comment:5 by Mahder Alemseged Gebremedhin, 9 years ago

PR271 has fixed this.

You can't take the last type and expect it to work :) that's cheating. You have to either expand the array of leave it as it is.

I think the subscripts form whatever this variable was based on are ignored somehow.

I was wrong here. As it turned out the variable is actually an array (it is created for an array). But it was not expanded. More specifically the tmpVars entry was an array. Which was unexpected for the code-generator because it handles scalars only. Everything is expanded at that point.

We have the possibility to actually handle un-expanded versions of residual equations (or with a bitmore changes all simvars). I have expanded residual equations now because I was not sure where the residual array (res*) passed to the residualFunc*s is allocated. If we make sure that is allocated correctly considering array residual variables everything should work fine. I will check.


That kind of expression is handled wrong in SimCode. Due to missing optimization this is handled as nonlinear system

I am gonna try and fix this. I think I know what the problem is.


Regarding crefs andtypes:

When you want the type of a cref you have to consider the subs as well. If you don't consider the subs you might get an array type for a cref that is actually a scalar because the identType stored is the array type. For example for r[2] the cref is stored as

DAE.CREF_IDENT(r, DAE.T_ARRAY(DAE.REAL, {3}, tysource), {2})
                              ^^^^^^^^   ^               ^
                              base type dims             subs

so if you take just the type you get an array.

Also don't take types from the last ident. In most cases this might work but when the we have complex arrays involved (e.g. a.b where a is an array of records) the last type will not give you the correct type even when you have considered its subs. a.b here is actually an array.

Avoid that ComponentReference.crefLastType function by all means :). It is the reason we have problems with records and arrays. Same for ComponentReference.crefType

I have added a new function ComponentReference.crefTypeFull which will give you the correct type of a cref. It is not considering WHOLEDIM() subs right now but I will fix it. Use this when you want the type of a cref anywhere.

There is also one more function Expression.crefToExp which will convert a DAE.ComponentReference to a DAE.Exp with the correct type. Use this one instead of Expression.crefExp which only considers last subs.

comment:6 by Martin Sjölund, 9 years ago

Milestone: 1.9.41.9.5

Milestone pushed to 1.9.5

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

Milestone: 1.9.51.10.0

Milestone renamed

comment:8 by Martin Sjölund, 8 years ago

Milestone: 1.10.01.11.0

Ticket retargeted after milestone closed

comment:9 by Martin Sjölund, 8 years ago

Milestone: 1.11.01.12.0

Milestone moved to 1.12.0 due to 1.11.0 already being released.

comment:10 by Francesco Casella, 7 years ago

Milestone: 1.12.0Future

The milestone of this ticket has been reassigned to "Future".

If you think the issue is still valid and relevant for you, please select milestone 1.13.0 for back-end, code generation and run-time issues, or 2.0.0 for front-end issues.

If you are aware that the problem is no longer present, please select the milestone corresponding to the version of OMC you used to check that, and set the status to "worksforme".

In both cases, a short informative comment would be welcome.

Note: See TracTickets for help on using tickets.