Model to test the saturationPressure function. This example computes the saturation pressure of water.

within Buildings.Utilities.Psychrometrics.Functions.Examples;
model SaturationPressure "Model to test the saturationPressure function"
  extends Modelica.Icons.Example;
  parameter Modelica.Units.SI.Temperature TMin=190 "Temperature";
  parameter Modelica.Units.SI.Temperature TMax=373.16 "Temperature";
  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.AbsolutePressure pSat "Saturation pressure";
  constant Real conv(unit="1/s") = 1 "Conversion factor";
equation
  T = TMin + conv*time * (TMax-TMin);
  pSat = Buildings.Utilities.Psychrometrics.Functions.saturationPressure(T);
end SaturationPressure;


Model to test X_pSatpphi function

within Buildings.Utilities.Psychrometrics.Functions.Examples;
model X_pSatpphi "Model to test X_pSatpphi function"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Air "Medium model"
  parameter Modelica.Units.SI.Temperature T=293.15 "Temperature";
  parameter Modelica.Units.SI.Pressure p=101325 "Pressure of the fluid";

  Modelica.Units.SI.AbsolutePressure pSat "Saturation pressure";
  Real phi(min=0, max=1) "Relative humidity";
  Modelica.Units.SI.MassFraction X_w(
    min=0,
    max=1,
    nominal=0.01) "Water vapor concentration per total mass of air";

  constant Real conv(unit="1/s") = 1 "Conversion factor";
equation
  phi = time*conv;
  pSat = Medium.saturationPressure(T);
  X_w = Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(pSat=pSat, p=p, phi=phi);
end X_pSatpphi;


Computes the unix time stamp and calendar time from the simulation time. This blocks computes the unix time stamp, date and time
and the day of the week based on the Modelica
variable time.
As for the weather data reader

Buildings.BoundaryConditions.WeatherData.ReaderTMY3,
time=0 corresponds to January 1st at midnight
in the local time zone.
The computed outputs are thus also for the local time zone.
The year for which time=0 is determined by
the parameter zerTim.

within Buildings.Utilities.Time;
model CalendarTime
  "Computes the unix time stamp and calendar time from the simulation time"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Buildings.Utilities.Time.Types.ZeroTime zerTim
    "Enumeration for choosing how reference time (time = 0) should be defined";
  parameter Integer yearRef(min=firstYear, max=lastYear) = 2016
    "Year when time = 0, used if zerTim=Custom"
  parameter Boolean outputUnixTimeStamp = false
    "= true, to output the unix time stamp (using GMT reference)"
  parameter Modelica.Units.SI.Time timZon(displayUnit="h") = 0
    "The local time zone, for computing the unix time stamp only"
  parameter Modelica.Units.SI.Time offset(displayUnit="h") = 0
    "Offset that is added to 'time', may be used for computing time in different time zones"

  Modelica.Blocks.Interfaces.RealOutput unixTimeStampLocal(final unit="s")
    "Unix time stamp at local time"
  Modelica.Blocks.Interfaces.RealOutput unixTimeStamp(final unit="s") = unixTimeStampLocal - timZon if outputUnixTimeStamp
    "Unix time stamp"
  discrete Modelica.Blocks.Interfaces.IntegerOutput year "Year"
  discrete Modelica.Blocks.Interfaces.IntegerOutput month "Month of the year"
  Modelica.Blocks.Interfaces.IntegerOutput day(fixed=false) "Day of the month"
  Modelica.Blocks.Interfaces.IntegerOutput hour(fixed=false) "Hour of the day"
  Modelica.Blocks.Interfaces.RealOutput minute "Minute of the hour"
  Modelica.Blocks.Interfaces.IntegerOutput weekDay(fixed=false)
    "Integer output representing week day (monday = 1, sunday = 7)"

protected
  final constant Real eps_time(final unit="s") = 1 "Small value for time";
  final constant Integer firstYear = 2010
    "First year that is supported, i.e. the first year in timeStampsNewYear[:]";
  final constant Integer lastYear = firstYear + size(timeStampsNewYear,1) - 1;
  constant Modelica.Units.SI.Time timeStampsNewYear[42]={1262304000.0,
    1293840000.0,1325376000.0,1356998400.0,1388534400.0,1420070400.0,
    1451606400.0,1483228800.0,1514764800.0,1546300800.0,1577836800.0,
    1609459200.0,1640995200.0,1672531200.0,1704067200.0,1735689600.0,
    1767225600.0,1798761600.0,1830297600.0,1861920000.0,1893456000.0,
    1924992000.0,1956528000.0,1988150400.0,2019686400.0,2051222400.0,
    2082758400.0,2114380800.0,2145916800.0,2177452800.0,2208988800.0,
    2240611200.0,2272147200.0,2303683200.0,2335219200.0,2366841600.0,
    2398377600.0,2429913600.0,2461449600.0,2493072000.0,2524608000.0,
    2556144000.0} "Epoch time stamps for new years day 2010 to 2051";
  constant Boolean isLeapYear[41] = {
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false, false, true, false,
    false}
    "List of leap years starting from firstYear (2010), up to and including 2050";
  final constant Integer dayInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    "Number of days in each month";
  parameter Modelica.Units.SI.Time timOff(fixed=false) "Time offset";
  // final parameters since the user may wrongly assume that this model shifts the
  // actual time of the simulation
  final constant Integer monthRef(min=1, max=12) = 1 "Month when time = 0"
  final constant Integer dayRef(min=1, max=31) = 1 "Day when time = 0"
  Integer daysSinceEpoch(fixed=false) "Number of days that passed since 1st of January 1970";
  discrete Integer yearIndex "Index of the current year in timeStampsNewYear";
  discrete Real epochLastMonth
    "Unix time stamp of the beginning of the current month";

  final parameter Modelica.Units.SI.Time hourSampleStart(fixed=false)
    "Time when the sampling every hour starts";
  final parameter Modelica.Units.SI.Time daySampleStart(fixed=false)
    "Time when the sampling every day starts";

  Boolean hourSampleTrigger "True, if hourly sample time instant";
  Boolean daySampleTrigger "True, if daily sample time instant";

  Boolean firstHourSampling(fixed=true, start=true)
    "=true if the hour is sampled the first time";
  Boolean firstDaySampling(fixed=true, start=true)
    "=true if the day is sampled the first time";
initial equation
  hourSampleStart = integer(time/3600)*3600 - offset;
  daySampleStart  = integer(time/(3600*24))*3600*24 - offset;

  hour = integer(floor(rem(unixTimeStampLocal,3600*24)/3600));
  daysSinceEpoch = integer(floor(unixTimeStampLocal/3600/24));

  day = integer(1+floor((unixTimeStampLocal-epochLastMonth)/3600/24));
  weekDay = integer(rem(4+daysSinceEpoch-1,7)+1);
initial algorithm
  // check if yearRef is in the valid range
  assert(not zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom
         or yearRef>=firstYear and yearRef<=lastYear,
    "The value you chose for yearRef (=" + String(yearRef) + ") is outside of
   the validity range of " + String(firstYear) + " to " + String(lastYear) + ".");

  // check if the day number exists for the chosen month and year
  assert(not zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom
         or dayInMonth[monthRef] + (if monthRef==2 and isLeapYear[yearRef-firstYear + 1] then 1 else 0) >=dayRef,
    "The day number you chose is larger than the number of days contained by the month you chose.");

  // compute the offset to be added to time based on the parameters specified by the user
  if zerTim == Buildings.Utilities.Time.Types.ZeroTime.UnixTimeStamp then
    timOff :=0;
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.UnixTimeStampGMT then
    timOff :=timZon;
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2010 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2010 then
      timOff :=timeStampsNewYear[1];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2011 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2011 then
      timOff :=timeStampsNewYear[2];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2012 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2012 then
      timOff :=timeStampsNewYear[3];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2013 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2013 then
      timOff :=timeStampsNewYear[4];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2014 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2014 then
      timOff :=timeStampsNewYear[5];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2015 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2015 then
      timOff :=timeStampsNewYear[6];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2016 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2016 then
      timOff :=timeStampsNewYear[7];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2017 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2017 then
      timOff :=timeStampsNewYear[8];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2018 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2018 then
      timOff :=timeStampsNewYear[9];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2019 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2019 then
      timOff :=timeStampsNewYear[10];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2020 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2020 then
      timOff :=timeStampsNewYear[11];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2021 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2021 then
      timOff :=timeStampsNewYear[12];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2022 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2022 then
      timOff :=timeStampsNewYear[13];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2023 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2023 then
      timOff :=timeStampsNewYear[14];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2024 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2024 then
      timOff := timeStampsNewYear[14];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2025 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2025 then
      timOff := timeStampsNewYear[15];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2026 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2026 then
      timOff := timeStampsNewYear[16];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2027 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2027 then
      timOff := timeStampsNewYear[17];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2028 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2028 then
      timOff := timeStampsNewYear[18];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2029 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2029 then
      timOff := timeStampsNewYear[19];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2030 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2030 then
      timOff := timeStampsNewYear[20];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2031 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2031 then
      timOff := timeStampsNewYear[21];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2032 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2032 then
      timOff := timeStampsNewYear[22];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2033 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2033 then
      timOff := timeStampsNewYear[23];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2034 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2034 then
      timOff := timeStampsNewYear[24];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2035 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2035 then
      timOff := timeStampsNewYear[25];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2036 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2036 then
      timOff := timeStampsNewYear[26];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2037 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2037 then
      timOff := timeStampsNewYear[27];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2038 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2038 then
      timOff := timeStampsNewYear[28];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2039 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2039 then
      timOff := timeStampsNewYear[29];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2040 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2040 then
      timOff := timeStampsNewYear[30];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2041 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2041 then
      timOff := timeStampsNewYear[31];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2042 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2042 then
      timOff := timeStampsNewYear[32];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2043 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2043 then
      timOff := timeStampsNewYear[33];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2044 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2044 then
      timOff := timeStampsNewYear[34];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2045 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2045 then
      timOff := timeStampsNewYear[35];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2046 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2046 then
      timOff := timeStampsNewYear[36];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2047 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2047 then
      timOff := timeStampsNewYear[37];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2048 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2048 then
      timOff := timeStampsNewYear[38];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2049 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2049 then
      timOff := timeStampsNewYear[39];
  elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.NY2050 or
    zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef == 2050 then
      timOff := timeStampsNewYear[40];
  else
    timOff :=0;
    // this code should not be reachable
    assert(false, "No valid ZeroTime could be identified.
   This is a bug, please submit a bug report.");
  end if;

  // add additional offset when using a custom date and time
  if zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom then
    timOff :=timOff + ((dayRef - 1) + sum({dayInMonth[i] for i in 1:(monthRef - 1)})
     + (if monthRef > 2 and isLeapYear[yearRef - firstYear + 1] then 1 else 0))*3600*24;
  end if;

   // input data range checks at initial time
  assert(time + offset + timOff >= timeStampsNewYear[1],
    if zerTim == Buildings.Utilities.Time.Types.ZeroTime.UnixTimeStamp then
      "Could not initialize date in the CalendarTime block.
   You selected 1970 as the time=0 reference.
   Therefore the simulation startTime must be at least " + String(timeStampsNewYear[1]) + "."
    elseif zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom then
      if yearRef <firstYear then
        "Could not initialize date in the CalendarTime block.
   You selected a custom time=0 reference.
   The minimum value for yearRef is then " + String(firstYear) + " but your value is " + String(yearRef) + "."
      else
        "Could not initialize date in the CalendarTime block.
   You selected a custom time=0 reference.
   Possibly your startTime is too small."
      else
        "Could not initialize date in the CalendarTime block.
   Possibly your startTime is negative?");

  assert(time + offset + timOff < timeStampsNewYear[size(timeStampsNewYear,1)],
    if zerTim == Buildings.Utilities.Time.Types.ZeroTime.Custom and yearRef >= lastYear then
      "Could not initialize date in the CalendarTime block.
   You selected a custom time=0 reference.
   The maximum value for yearRef is then " + String(lastYear) +
   " but your value is " + String(yearRef) + "."
    else
       "Could not initialize date in the CalendarTime block.
       Possibly your startTime is too large.");

  // iterate to find the year at initialization
initial algorithm
  year :=0;
  for i in 1:size(timeStampsNewYear,1) loop
    // may be reformulated using break if JModelica fixes bug
    if unixTimeStampLocal < timeStampsNewYear[i]
      and (if i == 1 then true else unixTimeStampLocal >= timeStampsNewYear[i-1]) then
      yearIndex :=i - 1;
      year :=firstYear + i - 2;
    end if;
  end for;

  // iterate to find the month at initialization
  epochLastMonth := timeStampsNewYear[yearIndex];
  month:=13;
  for i in 1:12 loop
    if (unixTimeStampLocal-epochLastMonth)/3600/24 <
      (if i==2 and isLeapYear[yearIndex] then 1 + dayInMonth[i] else dayInMonth[i]) then
      // construction below avoids the need of a break, which bugs out JModelica
      month :=min(i,month);
    else
      epochLastMonth :=epochLastMonth + (if i == 2 and isLeapYear[yearIndex]
         then 1 + dayInMonth[i] else dayInMonth[i])*3600*24;
    end if;
  end for;

equation
  // compute unix time step based on found offset
  unixTimeStampLocal = time + offset + timOff;

  // compute other variables that can be computed without using when() statements
  hourSampleTrigger =sample(hourSampleStart, 3600);
  when hourSampleTrigger then
    if pre(firstHourSampling) then
      hour = integer(floor(rem(unixTimeStampLocal,3600*24)/3600));
    else
      hour = if (pre(hour) == 23) then 0 else (pre(hour) + 1);
    end if;
    firstHourSampling = false;
  end when;

  daySampleTrigger =sample(daySampleStart, 86400);
  when daySampleTrigger then
    if pre(firstDaySampling) then
      daysSinceEpoch = integer(floor(unixTimeStampLocal/3600/24));
      weekDay=integer(rem(4+daysSinceEpoch-1,7)+1);

    else
      daysSinceEpoch = pre(daysSinceEpoch) + 1;
      weekDay = if (pre(weekDay) == 7) then 1 else (pre(weekDay) + 1);
    end if;

    // update the year when passing the epoch time stamp of the next year
    if unixTimeStampLocal - timeStampsNewYear[pre(yearIndex)+1] > -eps_time then
      yearIndex=pre(yearIndex)+1;
      year = pre(year) + 1;
    else
      yearIndex = pre(yearIndex);
      year = pre(year);
    end if;
    assert(yearIndex<=size(timeStampsNewYear,1),
      "Index out of range for epoch vector: timeStampsNewYear needs to be extended beyond the year "
        + String(firstYear+size(timeStampsNewYear,1)));

    // update the month when passing the last day of the current month
    if unixTimeStampLocal - ( pre(epochLastMonth) + (if pre(month)==2 and isLeapYear[yearIndex] then 1 + dayInMonth[pre(month)] else dayInMonth[pre(month)])*3600*24)  > -eps_time then
      month = if pre(month) == 12 then 1 else pre(month) + 1;
      // Use floor(0.1 + ...) to avoid floating point errors when accumulating epochLastMonth.
      epochLastMonth = floor(0.1 + pre(epochLastMonth) +
        (if pre(month)==2 and isLeapYear[yearIndex]
          then 1 + dayInMonth[pre(month)] else dayInMonth[pre(month)])*3600*24);
    else
      month = pre(month);
      epochLastMonth = pre(epochLastMonth);
    end if;

    day = integer(1+floor((unixTimeStampLocal-epochLastMonth)/3600/24));

    firstDaySampling = false;
  end when;

  // using Real variables and operations for minutes since otherwise too many events are generated
  minute = (unixTimeStampLocal/60-daysSinceEpoch*60*24-hour*60);
end CalendarTime;


Model time. This component outputs the model time, which starts at the value at which the simulation starts.
For example, if a simulation starts at t=-1, then this block outputs first t=-1,
and its output is advanced at the same rate as the simulation time.

within Buildings.Utilities.Time;
block ModelTime "Model time"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealOutput y "Model time"

equation
  y = time;
end ModelTime;


Package with models for time

within Buildings.Utilities;
package Time "Package with models for time"
  extends Modelica.Icons.Package;
end Time;


Example for the calendar time model. This model demonstrates the use of the

Buildings.Utilities.Time.CalendarTime
block.

within Buildings.Utilities.Time.Examples;
model CalendarTime "Example for the calendar time model"
  extends Modelica.Icons.Example;
  Buildings.Utilities.Time.CalendarTime calendarTime2016(
    zerTim=Buildings.Utilities.Time.Types.ZeroTime.NY2016)
    "Computes date and time assuming time=0 corresponds to new year 2016"

equation
end CalendarTime;


Test model for the ModelTime block. This model tests the implementation of
the block that outputs the model time.

within Buildings.Utilities.Time.Examples;
model ModelTime "Test model for the ModelTime block"
  extends Modelica.Icons.Example;
  Buildings.Utilities.Time.ModelTime modTim "Model time"
equation
end ModelTime;


within Buildings.Utilities.Time;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Package with type definitions

within Buildings.Utilities.Time;
package Types "Package with type definitions"
 extends Modelica.Icons.TypesPackage;
end Types;


Validation model for the calendar time model. This model validates the use of the

Buildings.Utilities.Time.CalendarTime
block for a period of a couple of months.
This shorter simulation time has been selected to
store the reference results that are used in the regression tests
at a resulation that makes sense for the minute and hour outputs.

within Buildings.Utilities.Time.Validation;
model CalendarTimeMonths "Validation model for the calendar time model"
  extends Modelica.Icons.Example;
  Buildings.Utilities.Time.CalendarTime calTim(zerTim=Buildings.Utilities.Time.Types.ZeroTime.NY2015)
    "Computes date and time assuming time=0 corresponds to new year 2015"

equation
end CalendarTimeMonths;


Validation model for the calendar time model with start time slightly below the full hour. This model validates the use of the

Buildings.Utilities.Time.CalendarTime.
It is identical to

Buildings.Utilities.Time.Validation.CalendarTimeMonths
except that the start and end time are different.

within Buildings.Utilities.Time.Validation;
model CalendarTimeMonthsMinus
  "Validation model for the calendar time model with start time slightly below the full hour"
  extends Buildings.Utilities.Time.Validation.CalendarTimeMonths;
end CalendarTimeMonthsMinus;


Validation model for the calendar time model with start time slightly higher than the full hour. This model validates the use of the

Buildings.Utilities.Time.CalendarTime.
It is identical to

Buildings.Utilities.Time.Validation.CalendarTimeMonths
except that the start and end time are different.

within Buildings.Utilities.Time.Validation;
model CalendarTimeMonthsPlus
  "Validation model for the calendar time model with start time slightly higher than the full hour"
  extends Buildings.Utilities.Time.Validation.CalendarTimeMonths;
end CalendarTimeMonthsPlus;


within Buildings.Utilities.Time;
package Validation "Collection of models that validate the time models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


activation process of continuous transitions.

within PNlib.Blocks;

block activationCon "activation process of continuous transitions"
  //no events are generated within while-loops; for-loops are applied
  parameter input Integer nIn "number of input places";
  parameter input Integer nOut "number of output places";
  input Real tIn[:] "marking of input places";
  input Real tOut[:] "marking of output places";
  input Integer tIntIn[:] "marking of input places";
  input Integer tIntOut[:] "marking of output places";
  input PNlib.Types.ArcType arcType[:] "arc type of input places";
  input Real arcWeightIn[:] "arc weights of input places";
  input Real arcWeightOut[:] "arc weights of output places";
  input Integer arcWeightIntIn[:] "arc weights of input places";
  input Integer arcWeightIntOut[:] "arc weights of output places";
  input Real minTokens[:] "minimum capacities of input places";
  input Real maxTokens[:] "maximum capacities of output places";
  input Integer minTokensInt[:] "minimum capacities of input places";
  input Integer maxTokensInt[:] "maximum capacities of output places";
  input Boolean firingCon "firing condition";
  input Boolean fed[:] "input places are fed?";
  input Boolean emptied[:] "output places are emptied?";
  input Boolean disPlaceIn[:] "types of input places";
  input Boolean disPlaceOut[:] "types of output places";
  input Real testValue[:] "test values of test and inhibitor arcs";
  input Integer testValueInt[:] "integer test values of test and inhibitor arcs";
  input Boolean normalArc[:] "normal or double arc?";
  output Boolean active "activation of transition";
  output Boolean weaklyInputActiveVec[nIn] "places that causes weakly input activation";
  output Boolean weaklyOutputActiveVec[nOut] "places that causes weakly output activation";
  Boolean NoTokens;
algorithm
  NoTokens := false;
  active := true;
  weaklyInputActiveVec := fill(false, nIn);
  weaklyOutputActiveVec := fill(false, nOut);

  //check input places
  for i in 1:nIn loop
    if disPlaceIn[i] then //discrete place
      if arcType[i] == PNlib.Types.ArcType.NormalArc and (tIntIn[i] - arcWeightIntIn[i] < minTokensInt[i]) then //normal arc
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealTestArc and (tIntIn[i] <= testValueInt[i]) then //real test arc
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc and (tIntIn[i] < testValueInt[i]) then //test arc
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and (tIntIn[i] >= testValueInt[i]) then // real inhibition arc
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and (tIntIn[i] > testValueInt[i]) then //inhibition arc
        active := false;
      end if;
    else //continuous place
      if arcType[i] == PNlib.Types.ArcType.NormalArc or not normalArc[i] then //normal arc or double arc
        NoTokens := not (tIn[i] - minTokens[i] >= -Constants.almost_eps);
        if arcWeightIn[i] <= 0.0 then
        elseif NoTokens and (not fed[i]) then
          active := false;
        elseif NoTokens and fed[i] then //weakly input active??
          weaklyInputActiveVec[i] := true;
        end if;
      end if;
      if arcType[i] == PNlib.Types.ArcType.RealTestArc then //real test arc
        if tIn[i] <= testValue[i] + Constants.almost_eps then
          active := false;
        end if;
        if tIn[i] > testValue[i] + Constants.almost_eps and fed[i] and not normalArc[i] then //weakly input active??
          weaklyInputActiveVec[i] := true;
        end if;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc then //test arc
        if tIn[i] < testValue[i] - Constants.almost_eps then
          active := false;
        end if;
        if tIn[i] >= testValue[i] - Constants.almost_eps and fed[i] and not normalArc[i] then //weakly input active??
          weaklyInputActiveVec[i] := true;
        end if;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and (tIn[i] >= testValue[i] - Constants.almost_eps) then //real inhibitor arc
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and (tIn[i] > testValue[i] + Constants.almost_eps) then //inhibitor arc
        active := false;
      end if;
    end if;
  end for;

  //output places
  for i in 1:nOut loop
    if disPlaceOut[i] then //discrete place
      if tIntOut[i] + arcWeightIntOut[i] > maxTokensInt[i] then
        active := false;
      end if;
    else //continuous place
      if tOut[i] >= maxTokens[i] then
        if emptied[i] then
          weaklyOutputActiveVec[i] := true;
        else
          active := false;
        end if;
      end if;
    end if;
  end for;

  active := active and firingCon;
  // hack for Dymola 2017
  // weaklyOutputActiveVec := weaklyOutputActiveVec and fill(firingCon, nOut);
  for i in 1:nOut loop
    weaklyOutputActiveVec[i] := weaklyOutputActiveVec[i] and firingCon;
  end for;

  // hack for Dymola 2017
  //weaklyInputActiveVec := weaklyInputActiveVec and fill(firingCon, nIn);
  for i in 1:nIn loop
    weaklyInputActiveVec[i] := weaklyInputActiveVec[i] and firingCon;
  end for;
end activationCon;


Activation of a discrete transition.

within PNlib.Blocks;

block activationDis "Activation of a discrete transition"
  parameter input Integer nIn "number of input places";
  parameter input Integer nOut "number of output places";
  input Real tIn[:] "tokens of input places";
  input Real tOut[:] "tokens of output places";
  input Integer tIntIn[:] "tokens of input places";
  input Integer tIntOut[:] "tokens of output places";
  input PNlib.Types.ArcType arcType[:] "arc type of input places";
  input Real arcWeightIn[:] "arc weights of input places";
  input Integer arcWeightIntIn[:] "arc weights of input places";
  input Real arcWeightOut[:] "arc weights of output places";
  input Integer arcWeightIntOut[:] "arc weights of output places";
  input Real minTokens[:] "minimum capacities of input places";
  input Integer minTokensInt[:] "minimum capacities of input places";
  input Real maxTokens[:] "maximum capacities of output places";
  input Integer maxTokensInt[:] "maximum capacities of output places";
  input Boolean firingCon "firing condition of transition";
  input Boolean disPlaceIn[:] "types of input places";
  input Boolean disPlaceOut[:] "types of output places";
  input Boolean normalArc[:] "normal or double arc?";
  input Real testValue[:] "test values of test and inhibitor arcs";
  input Integer testValueInt[:] "integer test values of test and inhibitor arcs";
  output Boolean active "activation of transition";
algorithm
  active := true;
  //check input places
  for i in 1:nIn loop
    if disPlaceIn[i] then //discrete
      if (arcType[i] == PNlib.Types.ArcType.NormalArc or not normalArc[i]) and not (tIntIn[i] - arcWeightIntIn[i] >= minTokensInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealTestArc and not (tIntIn[i] > testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc and not (tIntIn[i] >= testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and not (tIntIn[i] < testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and not (tIntIn[i] <= testValueInt[i]) then
        active := false;
      end if;
    else //continuous
      if (arcType[i] == PNlib.Types.ArcType.NormalArc or not normalArc[i]) and not (tIn[i] - arcWeightIn[i] - minTokens[i] >= -Constants.almost_eps) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealTestArc and not (tIn[i] > testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc and not (tIn[i] >= testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and not (tIn[i] < testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and not (tIn[i] <= testValue[i]) then
        active := false;
      end if;
    end if;
  end for;
  //check output places
  for i in 1:nOut loop
    if disPlaceOut[i] then //discrete
      if not (tIntOut[i] + arcWeightIntOut[i] <= maxTokensInt[i]) then
        active := false;
      end if;
    else //continuous
      if not (tOut[i] + arcWeightOut[i] - maxTokens[i] <= Constants.almost_eps) then
        active := false;
      end if;
    end if;
  end for;
  active := active and firingCon;
end activationDis;


Input Activation of a discrete transition.

within PNlib.Blocks;

block activationDisIn "Input Activation of a discrete transition"
  parameter input Integer nIn "number of input places";
  input Real tIn[:] "tokens of input places";
  input Integer tIntIn[:] "tokens of input places";
  input PNlib.Types.ArcType arcType[:] "arc type of input places";
  input Real arcWeightIn[:] "arc weights of input places";
  input Integer arcWeightIntIn[:] "arc weights of input places";
  input Real minTokens[:] "minimum capacities of input places";
  input Integer minTokensInt[:] "minimum capacities of input places";
  input Boolean firingCon "firing condition of transition";
  input Boolean disPlaceIn[:] "types of input places";
  input Boolean normalArc[:] "normal or double arc?";
  input Real testValue[:] "test values of test and inhibitor arcs";
  input Integer testValueInt[:] "integer test values of test and inhibitor arcs";
  output Boolean active "activation of transition";
algorithm
  active := true;
  //check input places
  for i in 1:nIn loop
    if disPlaceIn[i] then //discrete
      if (arcType[i] == PNlib.Types.ArcType.NormalArc or not normalArc[i]) and not (tIntIn[i] - arcWeightIntIn[i] >= minTokensInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealTestArc and not (tIntIn[i] > testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc and not (tIntIn[i] >= testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and not (tIntIn[i] < testValueInt[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and not (tIntIn[i] <= testValueInt[i]) then
        active := false;
      end if;
    else //continuous
      if (arcType[i] == PNlib.Types.ArcType.NormalArc or not normalArc[i]) and not (tIn[i] - arcWeightIn[i] - minTokens[i] >= -Constants.almost_eps) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealTestArc and not (tIn[i] > testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.TestArc and not (tIn[i] >= testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.RealInhibitorArc and not (tIn[i] < testValue[i]) then
        active := false;
      elseif arcType[i] == PNlib.Types.ArcType.InhibitorArc and not (tIn[i] <= testValue[i]) then
        active := false;
      end if;
    end if;
  end for;
  active := active and firingCon;
end activationDisIn;


Output activation of a discrete transition.

within PNlib.Blocks;

block activationDisOut "Output activation of a discrete transition"
  parameter input Integer nOut "number of output places";
  input Real tOut[:] "tokens of output places";
  input Integer tIntOut[:] "tokens of output places";
  input Real arcWeightOut[:] "arc weights of output places";
  input Integer arcWeightIntOut[:] "arc weights of output places";
  input Real maxTokens[:] "maximum capacities of output places";
  input Integer maxTokensInt[:] "maximum capacities of output places";
  input Boolean firingCon "firing condition of transition";
  input Boolean disPlaceOut[:] "types of output places";
  output Boolean active "activation of transition";
algorithm
  active := true;
  //check output places
  for i in 1:nOut loop
    if disPlaceOut[i] then //discrete
      if not (tIntOut[i] + arcWeightIntOut[i] <= maxTokensInt[i]) then
        active := false;
      end if;
    else //continuous
      if not (tOut[i] + arcWeightOut[i] - maxTokens[i] <= Constants.almost_eps) then
        active := false;
      end if;
    end if;
  end for;
  active := active and firingCon;
end activationDisOut;


Does any entry of a Boolean vector change its value?.

within PNlib.Blocks;

block anyChange "Does any entry of a Boolean vector change its value?"
  input Boolean vec[:](each start = false, each fixed = true);
  output Boolean anychange;
algorithm
  anychange := false;
  for i in 1:size(vec, 1) loop
    anychange := anychange or change(vec[i]);
  end for;
end anyChange;


Is any entry of a Boolean vector true?.

within PNlib.Blocks;

block anyTrue "Is any entry of a Boolean vector true?"
  input Boolean vec[:];
  output Boolean anytrue;
  output Integer numtrue;
algorithm
  anytrue := false;
  numtrue := 0;
  for i in 1:size(vec, 1) loop
    anytrue := anytrue or vec[i];
    if vec[i] then
      numtrue := numtrue + 1;
    end if;
  end for;
end anyTrue;


enabling process of input transitions (continuous places).

within PNlib.Blocks;

block enablingInCon "enabling process of input transitions (continuous places)"
  parameter input Integer nIn "number of input transitions";
  input Real arcWeight[nIn] "arc weights of input transitions";
  input Real t "current marking";
  input Real maxMarks "maximum capacity";
  input Boolean TAein[nIn] "active input transitions which are already enabled by their input places";
  input PNlib.Types.EnablingType enablingType "resolution of actual conflicts";
  input Integer enablingPrio[:] "enabling priorities of output transitions";
  input Real enablingProb[nIn] "enabling probabilites of input transitions";
  input Boolean disTransition[nIn] "discrete transition?";
  input Boolean delayPassed "Does any delayPassed of a output transition";
  input Boolean active[nIn] "Are the input transitions active?";
  parameter input Integer localSeed "Local seed to initialize random number generator";
  parameter input Integer globalSeed "Global seed to initialize random number generator";
  output Boolean TEin_[nIn] "enabled input transitions";
protected
  discrete Integer state128[4] "state of random number generator";
  Boolean TEin[nIn] "enabled input transitions";
  Boolean disTAin[nIn](each start = false, each fixed = true) "discret active input transitions";
  Integer remTAin[nIn](each start = 0, each fixed = true) "remaining active input transitions";
  discrete Real cumEnablingProb[nIn](each start = 0, each fixed = true) "cumulated, scaled enabling probabilities";
  discrete Real arcWeightSum "arc weight sum";
  Integer nremTAin "number of remaining active input transitions";
  Integer nTAin "number ofactive input transitions";
  Integer k "iteration index";
  Integer posTE "possible enabled transition";
  discrete Real randNum "uniform distributed random number";
  discrete Real sumEnablingProbTAin "sum of the enabling probabilities of the active input transitions";
  Boolean endWhile;
  Integer Index "priority Index";
initial algorithm
  // Generate initial state from localSeed and globalSeed
  state128 := Modelica.Math.Random.Generators.Xorshift128plus.initialState(localSeed, globalSeed);
  (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(state128);
algorithm
  TEin := fill(false, nIn);
  when delayPassed then
    if nIn > 0 then
      // hack for Dymola 2017
      //disTAin := TAein and disTransition;
      disTAin := Functions.OddsAndEnds.boolAnd(TAein, disTransition);
      arcWeightSum := Functions.OddsAndEnds.conditionalSum(arcWeight, disTAin); //arc weight sum of all active input transitions which are already enabled by their input places
      if t + arcWeightSum - maxMarks <= Constants.almost_eps or Functions.OddsAndEnds.isEqual(arcWeightSum, 0.0) then //Place has no actual conflict; all active input transitions are enabled
        TEin := TAein;
      else //Place has an actual conflict
        // hack for Dymola 2017
        // TEin := TAein and not disTransition;
        TEin := Functions.OddsAndEnds.boolAnd(TAein, not disTransition);
        if enablingType == PNlib.Types.EnablingType.Priority then //deterministic enabling according to priorities
          arcWeightSum := 0;
          for i in 1:nIn loop
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if Index > 0 and disTAin[Index] and ((t + arcWeightSum + arcWeight[Index] - maxMarks <= Constants.almost_eps) or Functions.OddsAndEnds.isEqual(arcWeight[Index], 0.0)) then
              TEin[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
        else //probabilistic enabling according to enabling probabilities
          arcWeightSum := 0;
          remTAin := zeros(nIn);
          nremTAin := 0;
          for i in 1:nIn loop
            if disTAin[i] then
              nremTAin := nremTAin + 1; //number of active input transitions
              remTAin[nremTAin] := i; //active input transitions
            end if;
          end for;
          nTAin := nremTAin; //number of active input transitions
          sumEnablingProbTAin := sum(enablingProb[remTAin[1:nremTAin]]); //enabling probability sum of all active input transitions
          cumEnablingProb := zeros(nIn); //cumulative, scaled enabling probabilities
          cumEnablingProb[1] := enablingProb[remTAin[1]]/sumEnablingProbTAin;
          for j in 2:nremTAin loop
            cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAin[j]]/sumEnablingProbTAin;
          end for;
          for i in 1:nTAin loop
            (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(pre(state128)) "uniform distributed random number";
            endWhile := false;
            k := 1;
            while k <= nremTAin and not endWhile loop
              if randNum <= cumEnablingProb[k] then
                posTE := remTAin[k];
                endWhile := true;
              else
                k := k + 1;
              end if;
            end while;
            if t + arcWeightSum + arcWeight[posTE] - maxMarks <= Constants.almost_eps or Functions.OddsAndEnds.isEqual(arcWeight[i], 0.0) then
              arcWeightSum := arcWeightSum + arcWeight[posTE];
              TEin[posTE] := true;
            end if;
            nremTAin := nremTAin - 1;
            if nremTAin > 0 then
              remTAin := Functions.OddsAndEnds.deleteElementInt(remTAin, k);
              cumEnablingProb := zeros(nIn);
              sumEnablingProbTAin := sum(enablingProb[remTAin[1:nremTAin]]);
              if sumEnablingProbTAin > 0 then
                cumEnablingProb[1] := enablingProb[remTAin[1]]/sumEnablingProbTAin;
                for j in 2:nremTAin loop
                  cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAin[j]]/sumEnablingProbTAin;
                end for;
              else
                cumEnablingProb[1:nremTAin] := fill(1/nremTAin, nremTAin);
              end if;
            end if;
          end for;
        end if;
      end if;
    else
      disTAin := fill(false, nIn);
      remTAin := fill(0, nIn);
      cumEnablingProb := fill(0.0, nIn);
      arcWeightSum := 0.0;
      nremTAin := 0;
      nTAin := 0;
      k := 0;
      posTE := 0;
      randNum := 0.0;
      state128 := pre(state128);
      sumEnablingProbTAin := 0.0;
      endWhile := false;
      Index := 0;
    end if;
  end when;
  // hack for Dymola 2017
  // TEin_ := TEin and active;
  for i in 1:nIn loop
    TEin_[i] := TEin[i] and active[i];
  end for;
end enablingInCon;


enabling process of discrete input transitions.

within PNlib.Blocks;

block enablingInDis "enabling process of discrete input transitions"
  parameter input Integer nIn "number of input transitions";
  input Integer arcWeight[:] "arc weights of input transitions";
  input Integer t "current token number";
  input Integer maxTokens "maximum capacity";
  input Boolean TAein[:] "active previous transitions which are already enabled by their input places";
  input PNlib.Types.EnablingType enablingType "resolution of actual conflicts";
  input Integer enablingPrio[:] "enabling priorities of input transitions";
  input Real enablingProb[:] "enabling probabilites of input transitions";
  input Real enablingBene[:] "enabling benefit of input transitions";
  input PNlib.Types.BenefitType benefitType "algorithm for benefit";
  input Boolean disTransition[:] "type of input transitions";
  input Boolean delayPassed "Does any delayPassed of a output transition";
  input Boolean active[:] "Are the input transitions active?";
  parameter input Integer localSeed "Local seed to initialize random number generator";
  parameter input Integer globalSeed "Global seed to initialize random number generator";
  output Boolean TEin_[nIn] "enabled input transitions";
protected
  discrete Integer state128[4] "state of random number generator";
  Boolean TEin[nIn] "enabled input transitions";
  Integer remTAin[nIn](each start = 0, each fixed = true) "remaining active input transitions";
  discrete Real cumEnablingProb[nIn](each start = 0, each fixed = true) "cumulated, scaled enabling probabilities";
  Integer arcWeightSum "arc weight sum";
  Integer nremTAin "number of remaining active input transitions";
  Integer nTAin "number ofactive input transitions";
  Integer k "iteration index";
  Integer posTE "possible enabled transition";
  discrete Real randNum "uniform distributed random number";
  discrete Real sumEnablingProbTAin "sum of the enabling probabilities of the active input transitions";
  Boolean endWhile;
  Integer Index "priority Index";
  discrete Real benefitMax "theoretical benefit";
  Boolean valid "valid solution";
  discrete Real benefitLimit "best valid benefit";
initial algorithm
  // Generate initial state from localSeed and globalSeed
  state128 := Modelica.Math.Random.Generators.Xorshift128plus.initialState(localSeed, globalSeed);
  (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(state128);
algorithm
  TEin := fill(false, nIn);
  arcWeightSum := 0;
  when delayPassed then
    if nIn > 0 then
      arcWeightSum := Functions.OddsAndEnds.conditionalSumInt(arcWeight, TAein); //arc weight sum of all active input transitions which are already enabled by their input places
      if t + arcWeightSum <= maxTokens then //Place has no actual conflict; all active input transitions are enabled
        TEin := TAein;
      else //Place has an actual conflict
        if enablingType == PNlib.Types.EnablingType.Priority then //deterministic enabling according to priorities
          arcWeightSum := 0;
          for i in 1:nIn loop
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if Index > 0 and TAein[Index] and disTransition[Index] and t + (arcWeightSum + arcWeight[Index]) <= maxTokens then ///new 07.03.2011
              TEin[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
          for i in 1:nIn loop //continuous transitions afterwards (discrete transitions have priority over continuous transitions)
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if TAein[Index] and not disTransition[Index] and t + (arcWeightSum + arcWeight[Index]) <= maxTokens then
              TEin[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
        elseif enablingType == PNlib.Types.EnablingType.Probability then //probabilistic enabling according to enabling probabilities
          arcWeightSum := 0;
          remTAin := zeros(nIn);
          nremTAin := 0;
          for i in 1:nIn loop
            if TAein[i] and disTransition[i] then
              nremTAin := nremTAin + 1; //number of active input transitions
              remTAin[nremTAin] := i; //active input transitions
            end if;
          end for;
          nTAin := nremTAin; //number of active input transitions
          sumEnablingProbTAin := sum(enablingProb[remTAin[1:nremTAin]]); //enabling probability sum of all active input transitions
          cumEnablingProb := zeros(nIn); //cumulative, scaled enabling probabilities
          cumEnablingProb[1] := enablingProb[remTAin[1]]/sumEnablingProbTAin;
          for j in 2:nremTAin loop
            cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAin[j]]/sumEnablingProbTAin;
          end for;
          for i in 1:nTAin loop
            (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(pre(state128)) "uniform distributed random number";
            endWhile := false;
            k := 1;
            while k <= nremTAin and not endWhile loop
              if randNum <= cumEnablingProb[k] then
                posTE := remTAin[k];
                endWhile := true;
              else
                k := k + 1;
              end if;
            end while;
            if t + arcWeightSum + arcWeight[posTE] <= maxTokens then
              arcWeightSum := arcWeightSum + arcWeight[posTE];
              TEin[posTE] := true;
            end if;
            nremTAin := nremTAin - 1;
            if nremTAin > 0 then
              remTAin := Functions.OddsAndEnds.deleteElementInt(remTAin, k);
              cumEnablingProb := zeros(nIn);
              sumEnablingProbTAin := sum(enablingProb[remTAin[1:nremTAin]]);
              if sumEnablingProbTAin > 0 then
                cumEnablingProb[1] := enablingProb[remTAin[1]]/sumEnablingProbTAin;
                for j in 2:nremTAin loop
                  cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAin[j]]/sumEnablingProbTAin;
                end for;
              else
                cumEnablingProb[1:nremTAin] := fill(1/nremTAin, nremTAin);
              end if;
            end if;
          end for;
        else
          if benefitType == PNlib.Types.BenefitType.Greedy then
            TEin := PNlib.Functions.Enabling.benefitGreedyDisIn(nIn, arcWeight, t, maxTokens, TAein, enablingBene, disTransition);
          elseif benefitType == PNlib.Types.BenefitType.BenefitQuotient then
            TEin := PNlib.Functions.Enabling.benefitQuotientDisIn(nIn, arcWeight, t, maxTokens, TAein, enablingBene, disTransition);
          else
            //TEin:=fill(false, nIn);
            arcWeightSum := 0;
            benefitMax := sum(enablingBene);
            benefitLimit := 0;
            (TEin, arcWeightSum, benefitMax, valid, benefitLimit) := PNlib.Functions.Enabling.benefitBaBDisIn(1, nIn, enablingBene, arcWeight, enablingBene./arcWeight, t, benefitMax, maxTokens, TEin, 0, benefitLimit, TAein, disTransition);
          end if;
        end if;
      end if;
    else
      remTAin := fill(0, nIn);
      cumEnablingProb := fill(0.0, nIn);
      arcWeightSum := 0;
      nremTAin := 0;
      nTAin := 0;
      k := 0;
      posTE := 0;
      randNum := 0;
      state128 := pre(state128);
      sumEnablingProbTAin := 0;
      endWhile := false;
      Index := 0;
      benefitMax := 0;
      valid := false;
      benefitLimit := 0;
    end if;
  end when;
  // hack for Dymola 2017
  // TEin_ := TEin and active;
  for i in 1:nIn loop
    TEin_[i] := TEin[i] and active[i];
  end for;
end enablingInDis;


enabling process of output transitions (continuous places).

within PNlib.Blocks;

block enablingOutCon "enabling process of output transitions (continuous places)"
  parameter input Integer nOut "number of output transitions";
  input Real arcWeight[:] "arc weights of output transitions";
  input Real t "current marks";
  input Real minMarks "minimum capacity";
  input Boolean TAout[:] "active output transitions with passed delay";
  input PNlib.Types.EnablingType enablingType "resolution of actual conflicts";
  input Integer enablingPrio[:] "enabling priorities of output transitions";
  input Real enablingProb[:] "enabling probabilites of output transitions";
  input Boolean disTransition[:] "discrete transition?";
  input Boolean delayPassed "Does any delayPassed of a output transition";
  parameter input Integer localSeed "Local seed to initialize random number generator";
  parameter input Integer globalSeed "Global seed to initialize random number generator";
  output Boolean TEout_[nOut] "enabled output transitions";
protected
  discrete Integer state128[4] "state of random number generator";
  Boolean TEout[nOut] "enabled output transitions";
  Boolean disTAout[nOut](each start = false, each fixed = true) "discret active output transitions";
  Integer remTAout[nOut](each start = 0, each fixed = true) "remaining active output transitions";
  discrete Real cumEnablingProb[nOut](each start = 0, each fixed = true) "cumulated, scaled enabling probabilities";
  discrete Real arcWeightSum "arc weight sum";
  Integer nremTAout "number of remaining active output transitions";
  Integer nTAout "number of active output transitions";
  Integer k "iteration index";
  Integer posTE "possible enabled transition";
  discrete Real randNum "uniform distributed random number";
  discrete Real sumEnablingProbTAout "sum of the enabling probabilities of the active output transitions";
  Boolean endWhile;
  Integer Index;
initial algorithm
// Generate initial state from localSeed and globalSeed
  state128 := Modelica.Math.Random.Generators.Xorshift128plus.initialState(localSeed, globalSeed);
  (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(state128);
algorithm
  TEout := fill(false, nOut);
  when delayPassed then
    if nOut > 0 then
      // hack for Dymola 2017
      // disTAout := TAout and disTransition;
      disTAout := Functions.OddsAndEnds.boolAnd(TAout, disTransition);
      arcWeightSum := Functions.OddsAndEnds.conditionalSum(arcWeight, disTAout);
      //arc weight sum of all active output transitions
      if t - arcWeightSum - minMarks >= -Constants.almost_eps or Functions.OddsAndEnds.isEqual(arcWeightSum, 0.0) then //Place has no actual conflict; all active output transitions are enabled
        TEout := TAout;
      else //Place has an actual conflict;
        // hack for Dymola 2017
        // TEout := TAout and not disTransition;
        TEout := Functions.OddsAndEnds.boolAnd(TAout, not disTransition);
        if enablingType == PNlib.Types.EnablingType.Priority then //deterministic enabling according to priorities
          arcWeightSum := 0;
          for i in 1:nOut loop //discrete transitions are proven at first
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if Index > 0 and disTAout[Index] and ((t - arcWeightSum - arcWeight[Index] - minMarks >= -Constants.almost_eps) or Functions.OddsAndEnds.isEqual(arcWeight[Index], 0.0)) then
              TEout[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
        else //probabilistic enabling according to enabling probabilities
          arcWeightSum := 0;
          remTAout := zeros(nOut);
          nremTAout := 0;
          for i in 1:nOut loop
            if disTAout[i] then
              nremTAout := nremTAout + 1; //number of active output transitions
              remTAout[nremTAout] := i; //active output transitions
            end if;
          end for;
          nTAout := nremTAout; //number of active output transitions
          sumEnablingProbTAout := sum(enablingProb[remTAout[1:nremTAout]]); //enabling probability sum of all active output transitions
          cumEnablingProb := zeros(nOut); //cumulative, scaled enabling probabilities
          cumEnablingProb[1] := enablingProb[remTAout[1]]/sumEnablingProbTAout;
          for j in 2:nremTAout loop
            cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAout[j]]/sumEnablingProbTAout;
          end for;
          for i in 1:nTAout loop
            (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(pre(state128)) "uniform distributed random number";
            endWhile := false;
            k := 1;
            while k <= nremTAout and not endWhile loop
              if randNum <= cumEnablingProb[k] then
                posTE := remTAout[k];
                endWhile := true;
              else
                k := k + 1;
              end if;
            end while;
            if (t - (arcWeightSum + arcWeight[posTE]) - minMarks >= -Constants.almost_eps) or Functions.OddsAndEnds.isEqual(arcWeight[i], 0.0) then
              arcWeightSum := arcWeightSum + arcWeight[posTE];
              TEout[posTE] := true;
            end if;
            nremTAout := nremTAout - 1;
            if nremTAout > 0 then
              remTAout := Functions.OddsAndEnds.deleteElementInt(remTAout, k);
              cumEnablingProb := zeros(nOut);
              sumEnablingProbTAout := sum(enablingProb[remTAout[1:nremTAout]]);
              if sumEnablingProbTAout > 0 then
                cumEnablingProb[1] := enablingProb[remTAout[1]]/sumEnablingProbTAout;
                for j in 2:nremTAout loop
                  cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAout[j]]/sumEnablingProbTAout;
                end for;
              else
                cumEnablingProb[1:nremTAout] := fill(1/nremTAout, nremTAout);
              end if;
            end if;
          end for;
        end if;
      end if;
    else
      disTAout := fill(false, nOut);
      remTAout := fill(0, nOut);
      cumEnablingProb := fill(0.0, nOut);
      arcWeightSum := 0.0;
      nremTAout := 0;
      nTAout := 0;
      k := 0;
      posTE := 0;
      randNum := 0.0;
      state128 := pre(state128);
      sumEnablingProbTAout := 0.0;
      endWhile := false;
      Index := 0;
    end if;
  end when;
  // hack for Dymola 2017
  // TEout_ := TEout and TAout;
  for i in 1:nOut loop
    TEout_[i] := TEout[i] and TAout[i];
  end for;
end enablingOutCon;


enabling process of output transitions.

within PNlib.Blocks;

block enablingOutDis "enabling process of output transitions"
  parameter input Integer nOut "number of output transitions";
  input Integer arcWeight[:] "arc weights of output transitions";
  input Integer t "current token number";
  input Integer minTokens "minimum capacity";
  input Boolean TAout[:] "active output transitions with passed delay";
  input PNlib.Types.EnablingType enablingType "resolution of actual conflicts";
  input Integer enablingPrio[:] "enabling priorities of output transitions";
  input Real enablingProb[:] "enabling probabilites of output transitions";
  input Real enablingBene[:] "enabling benefit of output transitions";
  input PNlib.Types.BenefitType benefitType "algorithm for benefit";
  input Boolean disTransition[:] "discrete output transition";
  input Boolean delayPassed "Does any delayPassed of a output transition";
  input Boolean activeCon "change of activation of output transitions";
  parameter input Integer localSeed "Local seed to initialize random number generator";
  parameter input Integer globalSeed "Global seed to initialize random number generator";
  output Boolean TEout_[nOut] "enabled output transitions";
protected
  discrete Integer state128[4] "state of random number generator";
  Boolean TEout[nOut] "enabled output transitions";
  Integer remTAout[nOut](each start = 0, each fixed = true) "remaining active output transitions";
  discrete Real cumEnablingProb[nOut](each start = 0, each fixed = true) "cumulated, scaled enabling probabilities";
  Integer arcWeightSum "arc weight sum";
  Integer nremTAout "number of remaining active output transitions";
  Integer nTAout "number of active output transitions";
  Integer k "iteration index";
  Integer posTE "possible enabled transition";
  discrete Real randNum "uniform distributed random number";
  discrete Real sumEnablingProbTAout "sum of the enabling probabilities of the active output transitions";
  Boolean endWhile;
  Integer Index "priority Index";
  discrete Real benefitMax "theoretical benefit";
  Boolean valid "valid solution";
  discrete Real benefitLimit "best valid benefit";
initial algorithm
  // Generate initial state from localSeed and globalSeed
  state128 := Modelica.Math.Random.Generators.Xorshift128plus.initialState(localSeed, globalSeed);
  (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(state128);
algorithm
  TEout := fill(false, nOut);
  arcWeightSum := 0;
  for i in 1:nOut loop //continuous transitions afterwards (discrete transitions have priority over continuous transitions)
    if TAout[i] and not disTransition[i] and t - (arcWeightSum + arcWeight[i]) >= minTokens then
      TEout[i] := true;
      arcWeightSum := arcWeightSum + arcWeight[i];
    end if;
  end for;

  when delayPassed or activeCon then
    if nOut > 0 then
      arcWeightSum := Functions.OddsAndEnds.conditionalSumInt(arcWeight, TAout); //arc weight sum of all active output transitions
      if t - arcWeightSum >= minTokens then //Place has no actual conflict; all active output transitions are enabled
        TEout := TAout;
      else //Place has an actual conflict;
        if enablingType == PNlib.Types.EnablingType.Priority then //deterministic enabling according to priorities
          arcWeightSum := 0;
          for i in 1:nOut loop //discrete transitions are proven at first
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if Index > 0 and TAout[Index] and disTransition[Index] and t - (arcWeightSum + arcWeight[Index]) >= minTokens then
              TEout[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
          for i in 1:nOut loop //continuous transitions afterwards (discrete transitions have priority over continuous transitions)
            Index := Modelica.Math.Vectors.find(i, enablingPrio);
            if TAout[Index] and not disTransition[Index] and t - (arcWeightSum + arcWeight[Index]) >= minTokens then
              TEout[Index] := true;
              arcWeightSum := arcWeightSum + arcWeight[Index];
            end if;
          end for;
        elseif enablingType == PNlib.Types.EnablingType.Probability then //probabilistic enabling according to enabling probabilities
          remTAout := zeros(nOut);
          nremTAout := 0;
          arcWeightSum := 0;
          for i in 1:nOut loop
            if TAout[i] and disTransition[i] then
              nremTAout := nremTAout + 1; //number of active output transitions
              remTAout[nremTAout] := i; //active output transitions
            end if;
          end for;
          nTAout := nremTAout; //number of active output transitions
          if nTAout > 0 then
            sumEnablingProbTAout := sum(enablingProb[remTAout[1:nremTAout]]); //enabling probability sum of all active output transitions
            cumEnablingProb := zeros(nOut); //cumulative, scaled enabling probabilities
            cumEnablingProb[1] := enablingProb[remTAout[1]]/sumEnablingProbTAout;
            for j in 2:nremTAout loop
              cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAout[j]]/sumEnablingProbTAout;
            end for;
            for i in 1:nTAout loop
              (randNum, state128) := Modelica.Math.Random.Generators.Xorshift128plus.random(pre(state128)) "uniform distributed random number";
              endWhile := false;
              k := 1;
              while k <= nremTAout and not endWhile loop
                if randNum <= cumEnablingProb[k] then
                  posTE := remTAout[k];
                  endWhile := true;
                else
                  k := k + 1;
                end if;
              end while;
              if t - (arcWeightSum + arcWeight[posTE]) >= minTokens then
                arcWeightSum := arcWeightSum + arcWeight[posTE];
                TEout[posTE] := true;
              end if;
              nremTAout := nremTAout - 1;
              if nremTAout > 0 then
                remTAout := Functions.OddsAndEnds.deleteElementInt(remTAout, k);
                cumEnablingProb := zeros(nOut);
                sumEnablingProbTAout := sum(enablingProb[remTAout[1:nremTAout]]);
                if sumEnablingProbTAout > 0 then
                  cumEnablingProb[1] := enablingProb[remTAout[1]]/sumEnablingProbTAout;
                  for j in 2:nremTAout loop
                    cumEnablingProb[j] := cumEnablingProb[j - 1] + enablingProb[remTAout[j]]/sumEnablingProbTAout;
                  end for;
                else
                  cumEnablingProb[1:nremTAout] := fill(1/nremTAout, nremTAout);
                end if;
              end if;
            end for;
          end if;
          for i in 1:nOut loop
            if TAout[i] and not disTransition[i] and t - (arcWeightSum + arcWeight[i]) >= minTokens then
              TEout[i] := true;
              arcWeightSum := arcWeightSum + arcWeight[i];
            end if;
          end for;
        else
          if benefitType == PNlib.Types.BenefitType.Greedy then
            TEout := PNlib.Functions.Enabling.benefitGreedyDisOut(nOut, arcWeight, t, minTokens, TAout, enablingBene, disTransition);
          elseif benefitType == PNlib.Types.BenefitType.BenefitQuotient then
            TEout := PNlib.Functions.Enabling.benefitQuotientDisOut(nOut, arcWeight, t, minTokens, TAout, enablingBene, disTransition);
          else
            arcWeightSum := 0;
            benefitMax := sum(enablingBene);
            benefitLimit := 0;
            (TEout, arcWeightSum, benefitMax, valid, benefitLimit) := PNlib.Functions.Enabling.benefitBaBDisOut(1, nOut, enablingBene, arcWeight, enablingBene./arcWeight, t, benefitMax, minTokens, TEout, 0, benefitLimit, TAout, disTransition);
          end if;
        end if;
      end if;
    else
      remTAout := fill(0, nOut);
      cumEnablingProb := fill(0.0, nOut);
      arcWeightSum := 0;
      nremTAout := 0;
      nTAout := 0;
      k := 0;
      posTE := 0;
      randNum := 0;
      state128 := pre(state128);
      sumEnablingProbTAout := 0.0;
      endWhile := false;
      Index := 0;
      benefitMax := 0;
      valid := false;
      benefitLimit := 0;
    end if;
  end when;
  // hack for Dymola 2017
  // TEout_ := TEout and TAout;
  for i in 1:nOut loop
    TEout_[i] := TEout[i] and TAout[i];
  end for;
end enablingOutDis;


calculates the firing sum of continuous places.

within PNlib.Blocks;

block firingSumCon "calculates the firing sum of continuous places"
  input Boolean fire[:] "firability of transitions";
  input Real arcWeight[:] "arc weights";
  input Real instSpeed[:] "istantaneous speed of transitions";
  input Boolean disTransition[:] "types of transitions";
  output Real conFiringSum "continuous firing sum";
  output Real disFiringSum "discrete firing sum";
protected
  Real vec1[size(fire, 1)];
  Real vec2[size(fire, 1)];
//algorithm //changed 21.03.11 due to negative values
equation
  for i in 1:size(fire, 1) loop
    if fire[i] and not disTransition[i] then
      vec1[i] = arcWeight[i]*instSpeed[i];
    else
      vec1[i] = 0;
    end if;
    if fire[i] and disTransition[i] then
      vec2[i] = arcWeight[i];
    else
      vec2[i] = 0;
    end if;
  end for;
  conFiringSum = sum(vec1);
  disFiringSum = sum(vec2);
end firingSumCon;


calculates the firing sum of discrete places.

within PNlib.Blocks;

block firingSumDis "calculates the firing sum of discrete places"
  input Boolean fire[:] "firability of transitions";
  input Integer arcWeight[:] "arc weights";
  output Integer firingSum "firing sum";
algorithm
  firingSum := 0;
  for i in 1:size(fire, 1) loop
    if fire[i] then
      firingSum := firingSum + arcWeight[i];
    end if;
  end for;
end firingSumDis;


within PNlib;

package Blocks "contains blocks with specific procedures that are used in the Petri net component models"
end Blocks;


Calculates the token flow for a continuous place..

within PNlib.Blocks;

block tokenFlowCon "Calculates the token flow for a continuous place."
  parameter input Integer nIn "number of input transitions";
  parameter input Integer nOut "number of output transitions";
  input Real conFiringSumIn;
  input Real conFiringSumOut;
  input Boolean fireIn[nIn];
  input Boolean fireOut[nOut];
  input Real arcWeightIn[nIn];
  input Real arcWeightOut[nOut];
  input Real instSpeedIn[nIn];
  input Real instSpeedOut[nOut];
  output Real inflowSum;
  output Real inflow[nIn];
  output Real outflowSum;
  output Real outflow[nOut];
equation
  der(inflowSum) = conFiringSumIn;
  // der(inflow) = arcWeightIn .* instSpeedIn;
  for i in 1:nIn loop
    der(inflow[i]) = if pre(fireIn[i]) then arcWeightIn[i]*instSpeedIn[i] else 0.0;
  end for;
  der(outflowSum) = conFiringSumOut;
  // der(outflow) = arcWeightOut .* instSpeedOut;
  for i in 1:nOut loop
    der(outflow[i]) = if pre(fireOut[i]) then arcWeightOut[i]*instSpeedOut[i] else 0.0;
  end for;
end tokenFlowCon;


Calculates the token flow for a discrete place..

within PNlib.Blocks;

block tokenFlowDis "Calculates the token flow for a discrete place."
  parameter input Integer nIn "number of input transitions";
  parameter input Integer nOut "number of output transitions";
  input Boolean fireIn[nIn];
  input Boolean fireOut[nOut];
  input Integer arcWeightIn[nIn];
  input Integer arcWeightOut[nOut];
  output Integer inflowSum;
  output Integer inflow[nIn];
  output Integer outflowSum;
  output Integer outflow[nOut];
equation
  for i in 1:nIn loop
    inflow[i] = pre(inflow[i]) + (if pre(fireIn[i]) then arcWeightIn[i] else 0);
  end for;
  inflowSum = sum(inflow);
  for i in 1:nOut loop
    outflow[i] = pre(outflow[i]) + (if pre(fireOut[i]) then arcWeightOut[i] else 0);
  end for;
  outflowSum = sum(outflow);
end tokenFlowDis;


Inhibitor Arc.

within PNlib.Components;

model IA "Inhibitor Arc"
  //****MODIFIABLE PARAMETERS AND VARIABLES BEGIN****//
  parameter Real testValue = 1 "marking that has to be deceeded to enable firing"
  parameter Boolean realInhibitorArc = true "real Inhibitor arc <, Inhibitor arc <="
  parameter Boolean normalArc = true "double arc: inhibitor and normal arc?"
  //****MODIFIABLE PARAMETERS AND VARIABLES END****//
  Boolean animateWeightTIarc = settings.animateWeightTIarc "only for transition animation and display (Do not change!)";
  Integer testColor[3] "only for transition animation and display (Do not change!)";
  Interfaces.TransitionIn inPlace(active = outTransition.active, fire = outTransition.fire, arcWeight = if normalArc then 0 else outTransition.arcWeight, arcWeightint = if normalArc then 0 else outTransition.arcWeightint, disTransition = outTransition.disTransition, instSpeed = if normalArc then 0 else outTransition.instSpeed, prelimSpeed = if normalArc then 0 else outTransition.prelimSpeed, maxSpeed = if normalArc then 0 else outTransition.maxSpeed) "connector for place"
  Interfaces.PlaceOut outTransition(t = inPlace.t, tint = inPlace.tint, minTokens = inPlace.minTokens, minTokensint = inPlace.minTokensint, enable = inPlace.enable, fed = inPlace.fed, decreasingFactor = inPlace.decreasingFactor, disPlace = inPlace.disPlace, tokenInOut = inPlace.tokenInOut, arcType = if realInhibitorArc then PNlib.Types.ArcType.RealInhibitorArc else PNlib.Types.ArcType.InhibitorArc, testValue = testValue, testValueint = testValueInt, normalArc = normalArc, speedSum = inPlace.speedSum) "connector for transition"
protected
  outer PNlib.Components.Settings settings "global settings for animation and display";
  Integer testValueInt "integer test value (for generating events!)";
equation
  if outTransition.disPlace then
    testValueInt = integer(testValue);
  else
    testValueInt = 1;
  end if;
  //****ANIMATION BEGIN****//
  if inPlace.t < testValue and settings.animateTIarc then
    testColor = {0, 255, 0};
  elseif settings.animateTIarc then
    testColor = {255, 0, 0};
  else
    testColor = {255, 255, 255};
  end if;
  //****ANIMATION END****//
  //****ERROR MESSENGES BEGIN****//
  assert((outTransition.disPlace and testValue - testValueInt <= 0.0) or not outTransition.disPlace, "Test arcs connected to discrete places must have integer test values.");
  assert(testValue >= 0, "Test values must be greater or equal than zero.");
  //****ERROR MESSENGES END****//
end IA;


within PNlib;

package Components "Contains component models to compose models of petri nets."
  extends Modelica.Icons.Package;
end Components;


Continuous Place.

within PNlib.Components;

model PC "Continuous Place"
  Real t "marking";
  parameter Integer nIn(min = 0) = 0 "number of input transitions"
  parameter Integer nOut(min = 0) = 0 "number of output transitions"
  //****MODIFIABLE PARAMETERS AND VARIABLES BEGIN****//
  parameter Real startMarks = 0 "start marks"
  parameter Real minMarks = 0 "minimum capacity"
  parameter Real maxMarks = PNlib.Constants.inf "maximum capacity"
  Boolean reStart = false "restart condition"
  parameter Real reStartMarks = 0 "number of marks at restart"
  parameter Integer N = settings.N "N+1=amount of levels"
  parameter PNlib.Types.EnablingType enablingType = PNlib.Types.EnablingType.Priority "resolution type of actual conflict (type-1-conflict)"
  parameter Integer enablingPrioIn[nIn] = 1:nIn "enabling priorities of input transitions"
  parameter Integer enablingPrioOut[nOut] = 1:nOut "enabling priorities of output transitions"
  parameter Real enablingProbIn[nIn] = fill(1/nIn, nIn) "enabling probabilities of input transitions"
  parameter Real enablingProbOut[nOut] = fill(1/nOut, nOut) "enabling probabilities of output transitions"
  //****MODIFIABLE PARAMETERS AND VARIABLES END****//
  Real levelCon "conversion of tokens to level concentration according to M and N of the settings box";
  Boolean showPlaceName = settings.showPlaceName "only for place animation and display (Do not change!)";
  Boolean showCapacity = settings.showCapacity "only for place animation and display (Do not change!)";
  Boolean animateMarking = settings.animateMarking "only for place animation and display (Do not change!)";
  Real color[3] "only for place animation and display (Do not change!)";
  parameter Boolean showTokenFlow = settings.showTokenFlow
  Blocks.tokenFlowCon tokenFlow(nIn = nIn, nOut = nOut, conFiringSumIn = firingSumIn.conFiringSum, conFiringSumOut = firingSumOut.conFiringSum, fireIn = fireIn, fireOut = fireOut, arcWeightIn = arcWeightIn, arcWeightOut = arcWeightOut, instSpeedIn = instSpeedIn, instSpeedOut = instSpeedOut) if showTokenFlow;
  parameter Integer localSeedIn = PNlib.Functions.Random.counter() "Local seed to initialize random number generator for input conflicts"
  parameter Integer localSeedOut = PNlib.Functions.Random.counter() "Local seed to initialize random number generator for output conflicts"
  Interfaces.PlaceIn inTransition[nIn](each t = t_, each tint = 1, each maxTokens = maxMarks, each maxTokensint = 1, enable = enableIn.TEin_, each emptied = emptying.anytrue, decreasingFactor = decFactorIn, each disPlace = false, each speedSum = firingSumOut.conFiringSum, fire = fireIn, disTransition = disTransitionIn, active = activeIn, arcWeight = arcWeightIn, instSpeed = instSpeedIn, maxSpeed = maxSpeedIn, prelimSpeed = prelimSpeedIn, enabledByInPlaces = enabledByInPlaces) if nIn > 0 "connector for input transitions"
  Interfaces.PlaceOut outTransition[nOut](each t = t_, each tint = 1, each minTokens = minMarks, each minTokensint = 1, enable = enableOut.TEout_, each fed = feeding.anytrue, decreasingFactor = decFactorOut, each disPlace = false, each arcType = PNlib.Types.ArcType.NormalArc, each speedSum = firingSumIn.conFiringSum, each tokenInOut = pre(disMarksInOut), fire = fireOut, disTransition = disTransitionOut, active = activeOut, arcWeight = arcWeightOut, instSpeed = instSpeedOut, maxSpeed = maxSpeedOut, prelimSpeed = prelimSpeedOut, each testValue = -1, each testValueint = -1, each normalArc = false) if nOut > 0 "connector for output transitions"
  Modelica.Blocks.Interfaces.RealOutput pc_t = t "connector for Simulink connection"
protected
  outer PNlib.Components.Settings settings "global settings for animation and display";
  Real disMarkChange "discrete mark change";
  Real conMarkChange "continuous mark change";
  Real arcWeightIn[nIn] "weights of input arcs";
  Real arcWeightOut[nOut] "weights of output arcs";
  Real instSpeedIn[nIn] "instantaneous speed of input transitions";
  Real instSpeedOut[nOut] "instantaneous speed of output transitions";
  Real maxSpeedIn[nIn] "maximum speed of input transitions";
  Real maxSpeedOut[nOut] "maximum speed of output transitions";
  Real prelimSpeedIn[nIn] "preliminary speed of input transitions";
  Real prelimSpeedOut[nOut] "preliminary speed of output transitions";
  Real tokenscale "only for place animation and display";
  Real t_(start = startMarks, fixed = true) "marking";
  Boolean disMarksInOut(start = false, fixed = true) "discrete marks change";
  Boolean preFireIn[nIn] "pre-value of fireIn";
  Boolean preFireOut[nOut] "pre-value of fireOut";
  Boolean fireIn[nIn](each start = false, each fixed = true) "Does any input transition fire?";
  Boolean fireOut[nOut](each start = false, each fixed = true) "Does any output transition fire?";
  Boolean disTransitionIn[nIn] "Are the input transitions discrete?";
  Boolean disTransitionOut[nOut] "Are the output transitions discrete?";
  Boolean activeIn[nIn] "Are the input transitions active?";
  Boolean activeOut[nOut] "Are the output transitions active?";
  Boolean enabledByInPlaces[nIn] "Are the input transitions enabled by all their input places?";
  //****BLOCKS BEGIN****// since no events are generated within functions!!!
  //enabling discrete transitions
  Blocks.enablingInCon enableIn(active = activeIn, delayPassed = delayPassedIn.anytrue, nIn = nIn, arcWeight = arcWeightIn, t = t_, maxMarks = maxMarks, TAein = enabledByInPlaces and activeIn, enablingType = enablingType, enablingPrio = enablingPrioIn, enablingProb = enablingProbIn, disTransition = disTransitionIn, localSeed = localSeedIn, globalSeed = settings.globalSeed);
  Blocks.enablingOutCon enableOut(delayPassed = delayPassedOut.anytrue, nOut = nOut, arcWeight = arcWeightOut, t = t_, minMarks = minMarks, TAout = activeOut, enablingType = enablingType, enablingPrio = enablingPrioOut, enablingProb = enablingProbOut, disTransition = disTransitionOut, localSeed = localSeedOut, globalSeed = settings.globalSeed);
  //Does any delay passed of a connected transition?
  Blocks.anyTrue delayPassedOut(vec = activeOut and disTransitionOut);
  Blocks.anyTrue delayPassedIn(vec = activeIn and disTransitionIn);
  //Does any discrete transition fire?
  Blocks.anyTrue disMarksOut(vec = fireOut and disTransitionOut);
  Blocks.anyTrue disMarksIn(vec = fireIn and disTransitionIn);
  //Is the place fed by input transitions?
  Blocks.anyTrue feeding(vec = preFireIn and not disTransitionIn);
  //Is the place emptied by output transitions?"
  Blocks.anyTrue emptying(vec = preFireOut and not disTransitionOut);
  //firing sum calculation
  Blocks.firingSumCon firingSumIn(fire = preFireIn, arcWeight = arcWeightIn, instSpeed = instSpeedIn, disTransition = disTransitionIn);
  Blocks.firingSumCon firingSumOut(fire = preFireOut, arcWeight = arcWeightOut, instSpeed = instSpeedOut, disTransition = disTransitionOut);
  //****BLOCKS END****//
  Real decFactorIn[nIn] "decreasing factors for input transitions";
  Real decFactorOut[nOut] "decreasing factors for output transitions";
equation
  //decreasing factor calculation
  (decFactorIn, decFactorOut) = Functions.decreasingFactor(nIn = nIn, nOut = nOut, t = t_, minMarks = minMarks, maxMarks = maxMarks, speedIn = firingSumIn.conFiringSum, speedOut = firingSumOut.conFiringSum, maxSpeedIn = maxSpeedIn, maxSpeedOut = maxSpeedOut, prelimSpeedIn = prelimSpeedIn, prelimSpeedOut = prelimSpeedOut, arcWeightIn = arcWeightIn, arcWeightOut = arcWeightOut, firingIn = fireIn and not disTransitionIn, firingOut = fireOut and not disTransitionOut);
  //calculation of continuous mark change
  conMarkChange = firingSumIn.conFiringSum - firingSumOut.conFiringSum;
  der(t_) = conMarkChange;
  //calculation of discrete mark change
  disMarkChange = firingSumIn.disFiringSum - firingSumOut.disFiringSum;
  disMarksInOut = pre(disMarksOut.anytrue) or pre(disMarksIn.anytrue);
  when {disMarksInOut, reStart} then
    reinit(t_, if reStart then reStartMarks else t_ + pre(disMarkChange));
  end when;
  //Conversion of tokens to level concentrations
  levelCon = t*settings.M/N;
  for i in 1:nOut loop
    preFireOut[i] = if disTransitionOut[i] then fireOut[i] else pre(fireOut[i]);
  end for;
  for i in 1:nIn loop
    preFireIn[i] = if disTransitionIn[i] then fireIn[i] else pre(fireIn[i]);
  end for;
  t = noEvent(if t_ < minMarks then minMarks elseif t_ > maxMarks then maxMarks else t_);
  //****MAIN END****//
  //****ANIMATION BEGIN****//
  //scaling of tokens for animation
  tokenscale = t*settings.scale;
  color = if settings.animatePlace then if tokenscale < 100 then {255, 255 - 2.55*tokenscale, 255 - 2.55*tokenscale} else {255, 0, 0} else {255, 255, 255};
  //****ANIMATION END****//
  //****ERROR MESSENGES BEGIN****//
  assert(Functions.OddsAndEnds.prioCheck(enablingPrioIn, nIn) or nIn == 0 or enablingType == PNlib.Types.EnablingType.Probability, "The priorities of the input priorities may be given only once and must be selected from 1 to nIn");
  assert(Functions.OddsAndEnds.prioCheck(enablingPrioOut, nOut) or nOut == 0 or enablingType == PNlib.Types.EnablingType.Probability, "The priorities of the output priorities may be given only once and must be selected from 1 to nOut");
  assert(Functions.OddsAndEnds.isEqual(sum(enablingProbIn), 1.0, 1e-6) or nIn == 0 or enablingType == PNlib.Types.EnablingType.Priority, "The sum of input enabling probabilities has to be equal to 1");
  assert(Functions.OddsAndEnds.isEqual(sum(enablingProbOut), 1.0, 1e-6) or nOut == 0 or enablingType == PNlib.Types.EnablingType.Priority, "The sum of output enabling probabilities has to be equal to 1");
  assert(startMarks >= minMarks and startMarks <= maxMarks, "minMarks<=startMarks<=maxMarks");
  //****ERROR MESSENGES END****//
end PC;


Discrete Place.

within PNlib.Components;

model PD "Discrete Place"
  discrete Integer t(start = startTokens, fixed = true) "marking";
  parameter Integer nIn(min = 0) = 0 "number of input transitions"
  parameter Integer nOut(min = 0) = 0 "number of output transitions"
  //****MODIFIABLE PARAMETERS AND VARIABLES BEGIN****//
  parameter Integer startTokens = 0 "start tokens"
  parameter Integer minTokens = 0 "minimum capacity"
  parameter Integer maxTokens = PNlib.Constants.Integer_inf "maximum capacity"
  Boolean reStart(start = false, fixed = true) = false "restart condition"
  parameter Integer reStartTokens = startTokens "number of tokens at restart"
  parameter PNlib.Types.EnablingType enablingType = PNlib.Types.EnablingType.Priority "resolution type of actual conflict (type-1-conflict)"
  parameter Integer enablingPrioIn[nIn] = 1:nIn "enabling priorities of input transitions"
  parameter Integer enablingPrioOut[nOut] = 1:nOut "enabling priorities of output transitions"
  parameter Real enablingProbIn[nIn] = fill(1/nIn, nIn) "enabling probabilities of input transitions"
  parameter Real enablingProbOut[nOut] = fill(1/nOut, nOut) "enabling probabilities of output transitions"
  parameter Real enablingBeneIn[nIn] = 1:nIn "enabling benefit of input transitions"
  parameter Real enablingBeneOut[nOut] = 1:nOut "enabling benefit of output transitions"
  parameter PNlib.Types.BenefitType benefitType = PNlib.Types.BenefitType.Greedy "enabling strategy for benefit"
  parameter Integer N = settings.N "N+1=amount of levels"
  //****MODIFIABLE PARAMETERS AND VARIABLES END****//
  Real levelCon "conversion of tokens to level concentration according to M and N of the settings box";
  Boolean showCapacity = settings.showCapacity "only for place animation and display (Do not change!)";
  Boolean animateMarking = settings.animateMarking "only for place animation and display (Do not change!)";
  Real color[3] "only for place animation and display (Do not change!)";
  parameter Boolean showTokenFlow = settings.showTokenFlow
  Blocks.tokenFlowDis tokenFlow(nIn = nIn, nOut = nOut, fireIn = fireIn, fireOut = fireOut, arcWeightIn = arcWeightIn, arcWeightOut = arcWeightOut) if showTokenFlow;
  parameter Integer localSeedIn = PNlib.Functions.Random.counter() "Local seed to initialize random number generator for input conflicts"
  parameter Integer localSeedOut = PNlib.Functions.Random.counter() "Local seed to initialize random number generator for output conflicts"
  PNlib.Interfaces.PlaceIn inTransition[nIn](each t = pret, each tint = pret, each maxTokens = maxTokens, each maxTokensint = maxTokens, enable = enableIn.TEin_, each emptied = false, each decreasingFactor = 1, each disPlace = true, each speedSum = 0, fire = fireIn, disTransition = disTransitionIn, arcWeightint = arcWeightIn, active = activeIn, enabledByInPlaces = enabledByInPlaces) if nIn > 0 "connector for input transitions"
  PNlib.Interfaces.PlaceOut outTransition[nOut](each t = pret, each tint = pret, each minTokens = minTokens, each minTokensint = minTokens, enable = enableOut.TEout_, each fed = false, each decreasingFactor = 1, each disPlace = true, each arcType = PNlib.Types.ArcType.NormalArc, each speedSum = 0, each tokenInOut = pre(tokeninout), fire = fireOut, disTransition = disTransitionOut, arcWeightint = arcWeightOut, active = activeOut, each testValue = -1, each testValueint = -1, each normalArc = false) if nOut > 0 "connector for output transitions"
  Modelica.Blocks.Interfaces.IntegerOutput pd_t = t "connector for Simulink connection"
protected
  outer PNlib.Components.Settings settings "global settings for animation and display";
  Real tokenscale "only for place animation and display";
  discrete Integer pret "pre marking";
  Integer arcWeightIn[nIn] "Integer weights of input arcs";
  Integer arcWeightOut[nOut] "Integer weights of output arcs";
  Boolean tokeninout(start = false, fixed = true) "change of tokens?";
  Boolean fireIn[nIn] "Do input transtions fire?";
  Boolean fireOut[nOut] "Do output transitions fire?";
  Boolean disTransitionIn[nIn] "Are the input transitions discrete?";
  Boolean disTransitionOut[nOut] "Are the output transtions discrete?";
  Boolean activeIn[nIn] "Are delays passed of input transitions?";
  Boolean activeOut[nOut](each start = false, each fixed = true) "Are delay passed of output transitions?";
  Boolean enabledByInPlaces[nIn] "Are input transitions are enabled by all their input places?";
  //****BLOCKS BEGIN****// since no events are generated within functions!!!
  //change of activation of output transitions
  Blocks.anyChange activeConOut(vec = pre(activeOut) and not disTransitionOut);
  //Does any delay passed of a connected transition?
  Blocks.anyTrue delayPassedOut(vec = activeOut and disTransitionOut);
  Blocks.anyTrue delayPassedIn(vec = activeIn and disTransitionIn);
  //firing sum calculation
  Blocks.firingSumDis firingSumIn(fire = fireIn and disTransitionIn, arcWeight = arcWeightIn);
  Blocks.firingSumDis firingSumOut(fire = fireOut and disTransitionOut, arcWeight = arcWeightOut);
  //Enabling process
  Blocks.enablingOutDis enableOut(delayPassed = delayPassedOut.anytrue, activeCon = activeConOut.anychange, nOut = nOut, arcWeight = arcWeightOut, t = pret, minTokens = minTokens, TAout = activeOut, enablingType = enablingType, enablingPrio = enablingPrioOut, enablingProb = enablingProbOut, enablingBene = enablingBeneOut, benefitType = benefitType, disTransition = disTransitionOut, localSeed = localSeedOut, globalSeed = settings.globalSeed);
  Blocks.enablingInDis enableIn(delayPassed = delayPassedIn.anytrue, active = activeIn, nIn = nIn, arcWeight = arcWeightIn, t = pret, maxTokens = maxTokens, TAein = enabledByInPlaces and activeIn, enablingType = enablingType, enablingPrio = enablingPrioIn, enablingProb = enablingProbIn, enablingBene = enablingBeneIn, benefitType = benefitType, disTransition = disTransitionIn, localSeed = localSeedIn, globalSeed = settings.globalSeed);
  //****BLOCKS END****//
equation
  //****MAIN BEGIN****//
  //recalculation of tokens
  pret = pre(t);
  tokeninout = pre(firingSumIn.firingSum) > 0 or pre(firingSumOut.firingSum) > 0;
  when pre(reStart) then
    t = reStartTokens;
  elsewhen {pre(firingSumIn.firingSum) > 0, pre(firingSumOut.firingSum) > 0} then
    t = pret + pre(firingSumIn.firingSum) - pre(firingSumOut.firingSum);
  end when;
  //Conversion of tokens to level concentrations
  levelCon = t*settings.M/N;
  //****MAIN END****//
  //****ANIMATION BEGIN****//
  tokenscale = t*settings.scale;
  color = if settings.animatePlace then if tokenscale < 100 then {255, 255 - 2.55*tokenscale, 255 - 2.55*tokenscale} else {255, 0, 0} else {255, 255, 255};
  //****ANIMATION END****//
  //****ERROR MESSENGES BEGIN****//
  assert(Functions.OddsAndEnds.prioCheck(enablingPrioIn, nIn) or nIn == 0 or enablingType == PNlib.Types.EnablingType.Probability, "The priorities of the input priorities may be given only once and must be selected from 1 to nIn");
  assert(Functions.OddsAndEnds.prioCheck(enablingPrioOut, nOut) or nOut == 0 or enablingType == PNlib.Types.EnablingType.Probability, "The priorities of the output priorities may be given only once and must be selected from 1 to nOut");
  assert(Functions.OddsAndEnds.isEqual(sum(enablingProbIn), 1.0, 1e-6) or nIn == 0 or enablingType == PNlib.Types.EnablingType.Priority, "The sum of input enabling probabilities has to be equal to 1");
  assert(Functions.OddsAndEnds.isEqual(sum(enablingProbOut), 1.0, 1e-6) or nOut == 0 or enablingType == PNlib.Types.EnablingType.Priority, "The sum of output enabling probabilities has to be equal to 1");
  assert(startTokens >= minTokens and startTokens <= maxTokens, "minTokens<=startTokens<=maxTokens");
  //****ERROR MESSENGES END****//
end PD;


Global Settings for Animation and Display.

within PNlib.Components;

model Settings "Global Settings for Animation and Display"
  parameter Boolean showPlaceName = true "show names of places"
  parameter Boolean showTransitionName = true "show names of transitions"
  parameter Boolean showTime = true "show Time variables of discrete transitions"
  parameter Boolean showCapacity = false "show capacities of places"
  parameter Boolean animateMarking = true "animation of markings"
  parameter Boolean animatePlace = true "animation of places"
  parameter Real scale = 1 "scale factor for place animation 0-100"
  parameter Boolean animateTransition = true "animation of transitions"
  parameter Real timeFire = 0.3 "time of transition animation"
  parameter Boolean animatePutFireTime = true "animation of putative fire time of stochastic transitions"
  parameter Boolean animateHazardFunc = true "animation of hazard functions of stochastic transitions"
  parameter Boolean animateSpeed = true "animation speed of continuous transitions"
  parameter Boolean animateWeightTIarc = true "show weights of test and inhibitor arcs"
  parameter Boolean animateTIarc = true "animation of test and inhibition arcs"
  parameter Integer N = 10 "N+1=amount of levels"
  parameter Real M = 1 "maximum concentration"
  parameter Boolean showTokenFlow = false
  parameter Integer globalSeed = 30020 "global seed to initialize random number generator"
end Settings;


immediate Transition.

within PNlib.Components;

model T "immediate Transition"
  parameter Integer nIn(min = 0) = 0 "number of input places"
  parameter Integer nOut(min = 0) = 0 "number of output places"
  //****MODIFIABLE PARAMETERS AND VARIABLES BEGIN****//
  Real arcWeightIn[nIn] = fill(1, nIn) "arc weights of input places"
  Real arcWeightOut[nOut] = fill(1, nOut) "arc weights of output places"
  Boolean firingCon = true "additional firing condition"
  //****MODIFIABLE PARAMETERS AND VARIABLES END****//
  Boolean active(start = false, fixed = true) "Is the transition active?";
  Boolean fire "Does the transition fire?";
  PNlib.Interfaces.TransitionIn inPlaces[nIn](each active = active, arcWeight = arcWeightIn, arcWeightint = arcWeightIntIn, each fire = fire, each disTransition = true, each instSpeed = 0, each prelimSpeed = 0, each maxSpeed = 0, t = tIn, tint = tIntIn, arcType = arcType, minTokens = minTokens, minTokensint = minTokensInt, disPlace = disPlaceIn, enable = enableIn, testValue = testValue, testValueint = testValueInt, normalArc = normalArc) if nIn > 0 "connector for input places"
  PNlib.Interfaces.TransitionOut outPlaces[nOut](each active = active, arcWeight = arcWeightOut, arcWeightint = arcWeightIntOut, each fire = fire, each enabledByInPlaces = enabledByInPlaces, each disTransition = true, each instSpeed = 0, each prelimSpeed = 0, each maxSpeed = 0, t = tOut, tint = tIntOut, maxTokens = maxTokens, maxTokensint = maxTokensInt, disPlace = disPlaceOut, enable = enableOut) if nOut > 0 "connector for output places"
protected
  outer PNlib.Components.Settings settings "global settings for animation and display";
  Boolean showTransitionName = settings.showTransitionName "only for transition animation and display (Do not change!)";
  Boolean showDelay = settings.showTime "only for transition animation and display (Do not change!)";
  Real color[3] "only for transition animation and display (Do not change!)";
  Real tIn[nIn] "tokens of input places";
  Real tOut[nOut] "tokens of output places";
  Real testValue[nIn] "test values of input arcs";
  Real fireTime "for transition animation";
  Real minTokens[nIn] "minimum tokens of input places";
  Real maxTokens[nOut] "maximum tokens of output places";
  Integer tIntIn[nIn] "integer tokens of input places (for generating events!)";
  Integer tIntOut[nOut] "integer tokens of output places (for generating events!)";
  PNlib.Types.ArcType arcType[nIn] "type of input arcs 1=normal, 2=real test arc,  3=test arc, 4=real inhibitor arc, 5=inhibitor arc";
  Integer arcWeightIntIn[nIn] "Integer arc weights of discrete input places (for generating events!)";
  Integer arcWeightIntOut[nOut] "Integer arc weights of discrete output places (for generating events!)";
  Integer minTokensInt[nIn] "Integer minimum tokens of input places (for generating events!)";
  Integer maxTokensInt[nOut] "Integer maximum tokens of output places (for generating events!)";
  Integer testValueInt[nIn] "Integer test values of input arcs (for generating events!)";
  Boolean normalArc[nIn] "1=no, 2=yes, i.e. double arc: test and normal arc or inhibitor and normal arc";
  Boolean disPlaceIn[nIn] "Are the input places discrete or continuous? true=discrete";
  Boolean disPlaceOut[nOut] "Are the output places discrete or continuous? true=discrete";
  Boolean enableIn[nIn] "Is the transition enabled by input places?";
  Boolean enableOut[nOut] "Is the transition enabled by output places?";
  Boolean ani "for transition animation";
  //****BLOCKS BEGIN****// since no events are generated within functions!!!
  //activation process
  Blocks.activationDis activation(testValue = testValue, testValueInt = testValueInt, normalArc = normalArc, nIn = nIn, nOut = nOut, tIn = tIn, tOut = tOut, tIntIn = tIntIn, tIntOut = tIntOut, arcType = arcType, arcWeightIn = arcWeightIn, arcWeightIntIn = arcWeightIntIn, arcWeightOut = arcWeightOut, arcWeightIntOut = arcWeightIntOut, minTokens = minTokens, maxTokens = maxTokens, minTokensInt = minTokensInt, maxTokensInt = maxTokensInt, firingCon = firingCon, disPlaceIn = disPlaceIn, disPlaceOut = disPlaceOut);
  //Is the transition enabled by all input places?
  Boolean enabledByInPlaces = Functions.OddsAndEnds.allTrue(enableIn);
  //Is the transition enabled by all output places?
  Boolean enabledByOutPlaces = Functions.OddsAndEnds.allTrue(enableOut);
  //****BLOCKS END****//
equation
  //****MAIN BEGIN****//
  //reset active
  active = activation.active and not pre(active);
  //firing process
  fire = if nOut == 0 then enabledByInPlaces else enabledByOutPlaces;
  //****MAIN END****//
  //****ANIMATION BEGIN****//
  when fire then
    fireTime = time;
    ani = true;
  end when;
  color = if (fireTime + settings.timeFire >= time and settings.animateTransition and ani) then {255, 255, 0} else {0, 0, 0};
  //****ANIMATION END****//
  //****ERROR MESSENGES BEGIN****//
  for i in 1:nIn loop
    if disPlaceIn[i] then
      arcWeightIntIn[i] = integer(arcWeightIn[i]);
    else
      arcWeightIntIn[i] = 1;
    end if;
    assert((disPlaceIn[i] and arcWeightIn[i] - arcWeightIntIn[i] <= 0.0) or not disPlaceIn[i], "Input arcs connected to discrete places must have integer weights.");
    assert(arcWeightIn[i] >= 0, "Input arc weights must be positive.");
  end for;
  for i in 1:nOut loop
    if disPlaceOut[i] then
      arcWeightIntOut[i] = integer(arcWeightOut[i]);
    else
      arcWeightIntOut[i] = 1;
    end if;
    assert((disPlaceOut[i] and arcWeightOut[i] - arcWeightIntOut[i] <= 0.0) or not disPlaceOut[i], "Output arcs connected to discrete places must have integer weights.");
    assert(arcWeightOut[i] >= 0, "Output arc weights must be positive.");
  end for;
  //****ERROR MESSENGES END****//
end T;