Search code examples
modelica

Export Modelica variables in MAT files with no post-processing


The purpose here is to:

  • output some specific variables in a MAT file (without the complex structure offered by the standard Modelica output);
  • without any post-processing i.e. after the simulation I'd like to have the MAT file ready-to-go, with no further steps (contrary to Writing specific variable to .txt or .mat with Dymola);
  • not IDE specific (not using Dymola or OpenModelica specific commands);
  • potentially without generating events;

The Modelica.Utilities.Streams.writeRealMatrix utility is what came to my mind at first, but I cannot make the append argument to work properly.

Here is what I tried:

model WriteRealMatrixToFileTest
  discrete Boolean success;
  discrete Real time_pre(start=0, fixed=true);

equation 
  when sample(0,0.1) then
    success = Modelica.Utilities.Streams.writeRealMatrix("OutMat.mat", "OutMat", {{time, sin(time)}}, append=true, format="4");
    Modelica.Utilities.Streams.print("Printing status at time " + String(time) + ": " + String(success));
    time_pre = time;
  end when;
end WriteRealMatrixToFileTest;

but, even though it always return succesfull and even if the command is correctly called at every 0.1s, in the MAT file I just find the very last value (e.g. {10, -0.544} if stopTime=10).

One option would be to reading back the MAT file, append the new set of values to the matrix, re-write them back again, but it sounds really ugly to me. Are there other ways? Since I cannot declare a dynamic-size matrix I cannot think of other options.


Solution

  • The append argument works, but it does not behave like you expect. writeRealMatrix appends variables to the given .mat file, but it does not append values to an existing matrix inside this file. If a variable with this name exists, it is overwritten.

    And idea would be to:

    • Continuously write the results to a .txt file via Modelica.Utilities.Streams.print, which automatically appends to existing files
    • At the end of the simulation read the .txt content and store it with writeRealMatrix as .mat file inside a when terminal() section

    Maybe like this:

    model WriteRealMatrixToFileTest
      import Modelica.Utilities.Streams;
      import Modelica.Utilities.Strings;
    
      Boolean success(start=false);
    
      parameter String tmpFile = "OutMat.txt";
      parameter String outFile = "OutMat.mat";
    
    protected 
      function txt2mat "Convert txt file to mat file"
        input String inFile;
        input String outFile;
        output Boolean success;
    
      protected 
        String[:] lines;
        Integer nlines;
        Real t[:], v[:];
        Integer pos "Start position of value at current line";
    
      algorithm 
        lines :=Streams.readFile(inFile);
        nlines :=size(lines, 1);
        t :=fill(0, nlines); // we have to initialize t and v with the correct size
        v :=fill(0, nlines); // so we can later use t[i] and v[i]
    
        for i in 1:nlines loop
          t[i] :=Strings.scanReal(lines[i], 1);
          pos :=Strings.find(lines[i], ";")+1; // get delimiter position to scan v
          v[i] :=Strings.scanReal(lines[i], pos);
        end for;
    
        success :=Streams.writeRealMatrix(outFile,"OutMat",{t,v},format="4");
      end txt2mat;
    
    
    equation 
      when initial() then
        Modelica.Utilities.Files.removeFile(tmpFile);
      end when;
    
      when sample(0,0.1) then
        Streams.print(String(time)+";"+String(sin(time)), fileName=tmpFile);
      end when;
    
      when terminal() then
        success = txt2mat(tmpFile, outFile);
      end when;
    end WriteRealMatrixToFileTest;