OpenModelica icon indicating copy to clipboard operation
OpenModelica copied to clipboard

Bad and incomplete text output when using getInstanceName()

Open max-privato opened this issue 3 years ago • 9 comments

Description and Steps to Reproduce

Consider the following code:

package RW
model W2root "OM does not write nameShort"
  W2 w2;
end W2root;
model W2 "does not write nameShort"
  final parameter String name = getInstanceName();
  String nameShort;
  Integer index;
algorithm
  when initial() then
    index := Modelica.Utilities.Strings.findLast(name, ".");
    nameShort := Modelica.Utilities.Strings.substring(name, index + 1, Modelica.Utilities.Strings.length(name));
  end when;

equation
  when initial() then
    Modelica.Utilities.Streams.print("### model full path: '" + name + ".mat" + "'");
    Modelica.Utilities.Streams.print("### model short name: '" + nameShort + ".mat" + "'");
  end when;
  annotation (
  experiment(StartTime = 0, StopTime = 2, Tolerance = 1e-6, Interval = 0.04));
end W2;
end RW;

When I run W2root, the expected output in message window, and the actual output obtained from Dymola is:

### model full path: 'W2root.w2.mat'
### model short name: 'w2.mat'

And this is what I read when I run it from Dymola. If I run W2root from OM 1.19.0, instead, I read: ### model full path: 'RW.W2root.w2.mat' Here I see two issues:

  1. The text I get as full path is 'RW.W2root.w2.mat' instead of 'W2root.w2.mat' (see MS 3.7.2.6)
  2. The second output row, containing the short name, is missing

Expected Behavior

I expect to read the following rows in the log:

### model full path: 'W2root.w2.mat'
### model short name: 'w2.mat'

Screenshots

Version and OS

OM 1.19.2 Win10 64bit

  • OpenModelica Version: [e.g. omc --version or Help->About OMEdit from OMEdit]
  • OS: [e.g. Windows 10, 64 bit]
  • Versions of used Modelica libraries if applicable

Additional Context

See also #9301 and #9303

max-privato avatar Aug 17 '22 15:08 max-privato

The getInstanceName issue might be fixed in #9307, if it doesn't break anything (in which case I'll just have to add a special case for getInstanceName).

The issue that the short name isn't printed is not solved though, but doesn't have anything to do with getInstanceName. I'm not sure if it's well defined to have a when-equation that depends on a when-algorithm like that, that might possibly lead to suprising behaviour. @kabdelhak or maybe @casella probably knows more.

perost avatar Aug 18 '22 11:08 perost

@max-privato please check with the next nightly and close this if fixed.

casella avatar Aug 18 '22 22:08 casella

The issue that the short name isn't printed is not solved though, but doesn't have anything to do with getInstanceName. I'm not sure if it's well defined to have a when-equation that depends on a when-algorithm like that, that might possibly lead to suprising behaviour. @kabdelhak or maybe @casella probably knows more.

@perost, which code are you referring to here?

casella avatar Aug 18 '22 22:08 casella

The issue that the short name isn't printed is not solved though, but doesn't have anything to do with getInstanceName. I'm not sure if it's well defined to have a when-equation that depends on a when-algorithm like that, that might possibly lead to suprising behaviour. @kabdelhak or maybe @casella probably knows more.

@perost, which code are you referring to here?

There are two print statements in the when-equation, but only one is actually printed when simulating the model. The when-equation depends on the when-algorithm to be executed first in order to give a value to nameShort, but I'm not sure if that's something one can actually rely on. But even then it's a bit weird that nothing is printed from the second print statement.

perost avatar Aug 19 '22 07:08 perost

@max-privato please check with the next nightly and close this if fixed.

I've checked with 1.20.0-dev-259. Now I receive: ### model full path: 'W2root.w2.mat' So, the first row is now ok. However, the seond row is still missing

max-privato avatar Aug 22 '22 13:08 max-privato

@max-privato, simple function calls in equation sections are not forbidden by the specification, but they are a bit fishy, because equations can be re-ordered based on dependencies, and it's not too clear what exactly must be done with them.

Is there a reason why you used an algorithm to set the variables and an equation to print them? What about putting the two print statements in the algorithm?

casella avatar Sep 01 '22 23:09 casella

@max-privato, simple function calls in equation sections are not forbidden by the specification, but they are a bit fishy, because equations can be re-ordered based on dependencies, and it's not too clear what exactly must be done with them.

I'd be curious why that is considered "fishy". Does a function call not also have a straightforward dependency relationship: depends on its arguments? So, it would be reordered to be called when its dependencies/arguments are fully known?

bilderbuchi avatar Sep 02 '22 05:09 bilderbuchi

See modelica/ModelicaSpecification#3227.

Given that the print functions are impure and are called within a when statement, this should actually work as you expect.

casella avatar Sep 02 '22 09:09 casella

I understand that the "print" directives are very special equations (they could be used in imperative languages as statements instead of equations). I did not think much about choosing an equation or algorithm action for them, but if they are allowed as I propose, they should work. I also understand that the order of equations within an equation section is not mandatory (the tool can reorder). But we expect that all the content of the when section is run, whatever the order of the two "equations". So, at most, the tool can reverse the order of the two print statements, but not eliminate one of them. If I used an algorithm section, instead, I would have guaranteed that the execution order would be kept.

max-privato avatar Sep 13 '22 21:09 max-privato

I tried to flatten RW.W2root, this is the outcome:

class RW.W2root "OM does not write nameShort"
  final parameter String w2.name = "W2root.w2";
  String w2.nameShort;
  Integer w2.index;
equation
  when initial() then
    Modelica.Utilities.Streams.print("### model full path: '" + w2.name + ".mat" + "'", "");
    Modelica.Utilities.Streams.print("### model short name: '" + w2.nameShort + ".mat" + "'", "");
  end when;
algorithm
  when initial() then
    w2.index := Modelica.Utilities.Strings.findLast(w2.name, ".", 0, true);
    w2.nameShort := Modelica.Utilities.Strings.substring(w2.name, w2.index + 1, Modelica.Utilities.Strings.length(w2.name));
  end when;
end RW.W2root;

name is constant-evaluated by the frontend (because it is a final parameter), and this leads to generated code that produces the intended outcome. nameShort isn't, and this leads to the following generated code:

/*
equation index: 4
type: WHEN

when {} then
  noReturnCall(Modelica.Utilities.Streams.print("### model short name: '" + w2.nameShort + ".mat" + "'", ""))%>);
end when;
*/
void W2root_eqFunction_4(DATA *data, threadData_t *threadData)
{
  TRACE_PUSH
  const int equationIndexes[2] = {1,4};
  static const MMC_DEFSTRINGLIT(tmp3,23,"### model short name: '");
  modelica_metatype tmpMeta4;
  static const MMC_DEFSTRINGLIT(tmp5,4,".mat");
  modelica_metatype tmpMeta6;
  modelica_metatype tmpMeta7;
  if(0)
  {
    tmpMeta4 = stringAppend(MMC_REFSTRINGLIT(tmp3),(data->localData[0]->stringVars[0] /* w2.nameShort DISCRETE */));
    tmpMeta6 = stringAppend(tmpMeta4,MMC_REFSTRINGLIT(tmp5));
    tmpMeta7 = stringAppend(tmpMeta6,(modelica_string) mmc_strings_len1[39]);
    omc_Modelica_Utilities_Streams_print(threadData, tmpMeta7, (modelica_string) mmc_emptystring);
  }
  TRACE_POP
}

Obviously the statement following if(0) is never executed 😅.

casella avatar May 29 '23 14:05 casella

See #10763.

@max-privato as a workaround for the time being you should avoid String variables corresponding to String equations that are solved at runtime. Only use String parameters and encapsulate the former when initial algorithm in a function:

package RWNew
model W2root "OM does not write nameShort"
  W2 w2;
end W2root;
model W2 "does not write nameShort"
  final parameter String name = getInstanceName();
  final parameter String nameShort = getShortName(name);
  function getShortName
    input String name;
    output String nameShort;
  protected
    Integer index;
  algorithm
    index := Modelica.Utilities.Strings.findLast(name, ".");
    nameShort := Modelica.Utilities.Strings.substring(name, index + 1, Modelica.Utilities.Strings.length(name));
  end getShortName;
equation
  when initial() then
    Modelica.Utilities.Streams.print("### model full path: '" + name + ".mat" + "'");
    Modelica.Utilities.Streams.print("### model short name: '" + nameShort + ".mat" + "'");
  end when;
  annotation (
  experiment(StartTime = 0, StopTime = 2, Tolerance = 1e-6, Interval = 0.04));
end W2;
end RWNew;

casella avatar May 29 '23 20:05 casella

Good to have a work around. Thank you

ceraolo avatar May 30 '23 06:05 ceraolo