Search code examples
modelicadymola

How to initialize a record type by a function in synchronous models (modelica)


I wrote a function, with return value of type record. Normally I would initialize an instance of type record by an initial equation, using this function. But as I want to use this function in a clocked model, initial equations are not possible.

For me it seems to be the only way to initialize a variable, using the attribute start. Unfortunatelly records do not have this attribute but only its components.

Here is a simple example, showing what i wanted to do:

model RecordInitializeTest
  record simpleRecord
    Integer arg1;
    Integer arg2;
  end simpleRecord;

  function initFunc
    output simpleRecord sR;
  algorithm 
    sR.arg1 := 1;
    sR.arg2 := 2;
  end initFunc;

  model InitializeTest
    input Boolean u(start=false);
    output simpleRecord sR1;
  equation 
    if u and not previous(u) then
      sR1 =initFunc();
    else
      sR1 = previous(sR1);
    end if;
  end InitializeTest;

  InitializeTest iT;
equation 
  iT.u = sample(time > 0.5,Clock(0.1));
end RecordInitializeTest;

This model works in dymola but of course there are warnings, as iT.sR1.agr1 and iT.sR1.arg2 have no start values but are arguments to previous(). Conceputally I would like to use

output simpleRecord sR1(start=initFunc());

Has anyone an idea how to initialize sR1 in a convenient way without assignments like

output simpleRecord sR1(arg1(start=1),arg2(start=2));

as that would be inconvenient for large structured records.

Actually i want to execute a complex external impure function (instead of initFunc) only at some instances of time and initally and keep the result in between. And I explicitly don't want to use a continous time model. And I don't want to get warnings at the translation process.


Solution

  • If I fully understood your question, only some small modifications are needed to let your example run as expected:

    model RecordInitializeTest
      record simpleRecord
        Integer arg1(start=0);
        Integer arg2(start=0);
      end simpleRecord;
    
      function impureFunc
        output simpleRecord sR;
      algorithm 
        (sR.arg1, sR.arg2) :=Modelica.Utilities.System.getTime();
      end impureFunc;
    
      model ImpureTest
        input Boolean u(start=false);
        output simpleRecord sR1;
      equation 
        if firstTick() or u and not previous(u) then
          sR1 = impureFunc();
        else
          sR1 = previous(sR1);
        end if;
      end ImpureTest;
    
      ImpureTest iT(u=sample(time > 0.5, Clock(0.1)));
    end RecordInitializeTest;
    

    In the simulation result we see that new record values are computed exactly 2 times: At time 0 and at time 0.5:

    sim-results

    The changes are:

    • initFunc() is replaced by impureFunc(), to see in the result that the function is called at time 0 and time 0.5

    • To perform the initialization firstTick() is added to call the impure function at time 0

    • There are no start-value warnings anymore, since every variable in record has a dummy-start value. The actual start values do not matter, as they are set with firstTick()

    Note: I never created a clocked models before, so I might have made some foolish beginner's mistake.