Skip to content

Commit

Permalink
refs #1627, #2080: Add options for time event generation in CombiTime…
Browse files Browse the repository at this point in the history
…Table

* For interpolation by linear segments, the time event generation at interval boundaries can be selected from always, at discontinuities only (defined by replicated sample points) and never
* For interpolation by constant segments, time events at interval boundaries are always generated
* For smooth interpolation by cubic Hermite splines, time events at interval boundaries are not generated
* See also 497480d
  • Loading branch information
beutlich committed Apr 18, 2017
1 parent e1615bf commit c64bb66
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 42 deletions.
26 changes: 15 additions & 11 deletions Modelica/Blocks/Sources.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2151,6 +2151,9 @@ If, e.g., time = 1.0, the output y = 0.0 (before event), 1.0 (after event)
parameter Modelica.SIunits.Time shiftTime=startTime
"Shift time of first table column"
annotation (Dialog(group="Table data interpretation"));
parameter Modelica.Blocks.Types.TimeEvents timeEvents=Modelica.Blocks.Types.TimeEvents.Always
"Time event handling of table interpolation"
annotation (Dialog(group="Table data interpretation", enable=smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments));
final parameter Modelica.SIunits.Time t_min=t_minScaled*timeScale
"Minimum abscissa value defined in table";
final parameter Modelica.SIunits.Time t_max=t_maxScaled*timeScale
Expand All @@ -2172,6 +2175,7 @@ If, e.g., time = 1.0, the output y = 0.0 (before event), 1.0 (after event)
smoothness,
extrapolation,
shiftTime/timeScale,
if smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then timeEvents elseif smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then Modelica.Blocks.Types.TimeEvents.Always else Modelica.Blocks.Types.TimeEvents.NoTimeEvents,
if tableOnFile then verboseRead else false) "External table object";
discrete Modelica.SIunits.Time nextTimeEvent(start=0, fixed=true)
"Next time event instant";
Expand Down Expand Up @@ -2268,18 +2272,18 @@ The table interpolation has the following properties:
to <strong>shiftTime</strong>.</li>
<li>If time &lt; startTime, no interpolation is performed and the offset
is used as ordinate value for all outputs.</li>
<li>The table is implemented in a numerically sound way by <strong>always</strong>
<li>The table is implemented in a numerically sound way by
generating <strong>time events</strong> at interval boundaries, in case of
interpolation by constant or linear segments.
interpolation by linear segments.
This generates continuously differentiable values for the integrator.
(In package Modelica&nbsp;v3.2 and earlier, time events had always been generated
at interval boundaries if smoothness was LinearSegments, which means the blocks
<a href=\"modelica://Modelica.Blocks.Sources.TimeTable\">TimeTable</a> and
CombiTimetable behaved identically. In contrast, in packages Modelica&nbsp;v3.2.1
and&nbsp;v3.2.2 time events were only generated for replicated time points,
which could lead to unexpected simulation results. This behaviour was later
reverted again to match the previous behaviour of Modelica&nbsp;v3.2 and earlier.)
</li>
Via parameter <strong>timeEvents</strong> it is defined how the time events are generated:
<pre>
timeEvents = 1: Always generate time events at interval boundaries
= 2: Generate time events at discontinuities (defined by duplicated sample points)
= 3: No time events at interval boundaries
</pre></li>
For interpolation by constant segments time events are always generated at interval boundaries.
For smooth interpolation by cubic Hermite splines no time events are generated at interval boundaries.
<li>Via parameter <strong>timeScale</strong> the first column of the table array can
be scaled, e.g., if the table array is given in hours (instead of seconds)
<strong>timeScale</strong> shall be set to 3600.</li>
Expand All @@ -2303,7 +2307,7 @@ Example:
2, 4;
3, 9;
4, 16];
extrapolation = 2 (default)
extrapolation = 2 (default), timeEvents = 2
If, e.g., time = 1.0, the output y = 0.0 (before event), 1.0 (after event)
e.g., time = 1.5, the output y = 2.5,
e.g., time = 2.0, the output y = 4.0,
Expand Down
8 changes: 8 additions & 0 deletions Modelica/Blocks/Types.mo
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ package Types
NoExtrapolation "Extrapolation triggers an error")
"Enumeration defining the extrapolation of table interpolation";

type TimeEvents = enumeration(
Always "Always generate time events at interval boundaries",
AtDiscontinuities "Generate time events at discontinuities (defined by duplicated sample points)",
NoTimeEvents "No time events at interval boundaries")
"Enumeration defining the time event handling of time table interpolation";

type Init = enumeration(
NoInit
"No initialization (start values are used as guess values with fixed=false)",
Expand Down Expand Up @@ -129,6 +135,7 @@ initialization definition.
input Modelica.Blocks.Types.Smoothness smoothness;
input Modelica.Blocks.Types.Extrapolation extrapolation;
input Modelica.SIunits.Time shiftTime;
input Modelica.Blocks.Types.TimeEvents timeEvents;
input Boolean verboseRead=true "= true: Print info message; = false: No info message";
output ExternalCombiTimeTable externalCombiTimeTable;
external"C" externalCombiTimeTable = ModelicaStandardTables_CombiTimeTable_init2(
Expand All @@ -143,6 +150,7 @@ initialization definition.
smoothness,
extrapolation,
shiftTime,
timeEvents,
verboseRead) annotation (Library={"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO", "zlib"});
end constructor;

Expand Down
90 changes: 64 additions & 26 deletions Modelica/Resources/C-Sources/ModelicaStandardTables.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@
Modelica.Blocks.Tables.CombiTable2D
Release Notes:
Apr. 15, 2017: by Thomas Beutlich, ESI ITI GmbH
Added support for time event generation (independent of
smoothness) in CombiTimeTable (ticket #2080)
Apr. 11, 2017: by Thomas Beutlich, ESI ITI GmbH
Revised initialization of CombiTimeTable, CombiTable1D
and CombiTable2D (ticket #1899)
- Already read table in the initialization functions
- Removed the implementation of the read functions
Apr. 07, 2017: by Thomas Beutlich, ESI ITI GmbH
Decoupled shift time from start time in CombiTimeTable
(ticket #1771)
Added support for shift time (independent of start time)
in CombiTimeTable (ticket #1771)
Apr. 05, 2017: by Thomas Beutlich, ESI ITI GmbH
Fixed extrapolation of CombiTimeTable if simulation start
Expand All @@ -60,11 +64,6 @@
Added functions to retrieve minimum and maximum abscissa
values of CombiTable1D (ticket #2120)
Jan. 27, 2017: by Thomas Beutlich, ESI ITI GmbH
Always generate time events for CombiTimeTable with linear
interpolation (similarly to constant segments)
(tickets #1627 and #2080)
Aug. 10, 2016: by Thomas Beutlich, ESI ITI GmbH
Fixed event detection of CombiTimeTable for restarted
simulation (ticket #2040)
Expand Down Expand Up @@ -176,6 +175,13 @@ enum Extrapolation {
NO_EXTRAPOLATION
};

enum TimeEvents {
UNDEFINED = 0,
ALWAYS,
AT_DISCONT,
NO_TIMEEVENTS
};

/* ----- Internal enumerations ----- */

enum PointInterval {
Expand Down Expand Up @@ -213,6 +219,7 @@ typedef struct CombiTimeTable {
enum Smoothness smoothness; /* Smoothness kind */
enum Extrapolation extrapolation; /* Extrapolation kind */
enum TableSource source; /* Source kind */
enum TimeEvents timeEvents; /* Kind of time event handling */
int* cols; /* Columns of table to be interpolated */
size_t nCols; /* Number of columns of table to be interpolated */
double startTime; /* Start time of inter-/extrapolation */
Expand Down Expand Up @@ -494,7 +501,7 @@ void* ModelicaStandardTables_CombiTimeTable_init(_In_z_ const char* tableName,
int extrapolation) {
return ModelicaStandardTables_CombiTimeTable_init2(fileName,
tableName, table, nRow, nColumn, startTime, cols, nCols, smoothness,
extrapolation, startTime, 1 /* verbose */);
extrapolation, startTime, ALWAYS, 1 /* verbose */);
}

void* ModelicaStandardTables_CombiTimeTable_init2(_In_z_ const char* fileName,
Expand All @@ -506,6 +513,7 @@ void* ModelicaStandardTables_CombiTimeTable_init2(_In_z_ const char* fileName,
size_t nCols, int smoothness,
int extrapolation,
double shiftTime,
int timeEvents,
int verbose) {
CombiTimeTable* tableID;
#if defined(TABLE_SHARE)
Expand Down Expand Up @@ -566,6 +574,7 @@ void* ModelicaStandardTables_CombiTimeTable_init2(_In_z_ const char* fileName,

tableID->smoothness = (enum Smoothness)smoothness;
tableID->extrapolation = (enum Extrapolation)extrapolation;
tableID->timeEvents = (enum TimeEvents)timeEvents;
tableID->nCols = nCols;
tableID->startTime = startTime;
tableID->shiftTime = shiftTime;
Expand Down Expand Up @@ -1319,13 +1328,15 @@ double ModelicaStandardTables_CombiTimeTable_nextTimeEvent(void* _tableID,

/* There is at least one time event at the interval boundaries */
tableID->maxEvents = 1;
if (tableID->smoothness == LINEAR_SEGMENTS ||
tableID->smoothness == CONSTANT_SEGMENTS) {
if (tableID->timeEvents == ALWAYS ||
tableID->timeEvents == AT_DISCONT) {
for (i = 0; i < nRow - 1; i++) {
double t0 = TABLE_COL0(i);
double t1 = TABLE_COL0(i + 1);
if (t1 > tEvent && !isNearlyEqual(t1, tMax)) {
if (!isNearlyEqual(t0, t1)) {
int isEq = isNearlyEqual(t0, t1);
if ((tableID->timeEvents == ALWAYS && !isEq) ||
(tableID->timeEvents == AT_DISCONT && isEq)) {
tEvent = t1;
tableID->maxEvents++;
}
Expand All @@ -1342,26 +1353,46 @@ double ModelicaStandardTables_CombiTimeTable_nextTimeEvent(void* _tableID,

tEvent = TABLE_ROW0(0);
eventInterval = 0;
if (tableID->smoothness == LINEAR_SEGMENTS ||
tableID->smoothness == CONSTANT_SEGMENTS) {
if (tableID->timeEvents == ALWAYS ||
tableID->timeEvents == AT_DISCONT) {
for (i = 0; i < nRow - 1 &&
eventInterval < tableID->maxEvents; i++) {
double t0 = TABLE_COL0(i);
double t1 = TABLE_COL0(i + 1);
if (t1 > tEvent) {
if (!isNearlyEqual(t0, t1)) {
tEvent = t1;
tableID->intervals[eventInterval][0] = i;
if (tableID->timeEvents == ALWAYS) {
if (t1 > tEvent && !isNearlyEqual(t1, tMax)) {
if (!isNearlyEqual(t0, t1)) {
tEvent = t1;
tableID->intervals[eventInterval][0] = i;
tableID->intervals[eventInterval][1] = i + 1;
eventInterval++;
}
else {
tableID->intervals[eventInterval][0] = i + 1;
}
}
else {
tableID->intervals[eventInterval][1] = i + 1;
eventInterval++;
}
}
else if (tableID->timeEvents == AT_DISCONT) {
if (t1 > tEvent && !isNearlyEqual(t1, tMax)) {
if (isNearlyEqual(t0, t1)) {
tEvent = t1;
tableID->intervals[eventInterval][1] = i;
eventInterval++;
if (eventInterval < tableID->maxEvents) {
tableID->intervals[eventInterval][0] = i + 1;
}
}
else {
tableID->intervals[eventInterval][1] = i + 1;
}
}
else {
tableID->intervals[eventInterval][0] = i + 1;
}
}
else {
tableID->intervals[eventInterval][1] = i + 1;
}
}
}
}
Expand Down Expand Up @@ -1425,22 +1456,29 @@ double ModelicaStandardTables_CombiTimeTable_nextTimeEvent(void* _tableID,
iEnd = iStart < (nRow - 1) ? iStart : (nRow - 1);
}

if (tableID->smoothness == LINEAR_SEGMENTS ||
tableID->smoothness == CONSTANT_SEGMENTS) {
if (tableID->timeEvents == ALWAYS ||
tableID->timeEvents == AT_DISCONT) {
size_t i;
for (i = iStart + 1; i < nRow - 1; i++) {
double t0 = TABLE_COL0(i);
if (t0 > t) {
nextTimeEvent = t0;
break;
double t1 = TABLE_COL0(i + 1);
int isEq = isNearlyEqual(t0, t1);
if ((tableID->timeEvents == ALWAYS && !isEq) ||
(tableID->timeEvents == AT_DISCONT && isEq)) {
nextTimeEvent = t0;
break;
}
}
}

for (i = 0; i < iEnd; i++) {
double t0 = TABLE_COL0(i);
double t1 = TABLE_COL0(i + 1);
if (t1 > tEvent && !isNearlyEqual(t1, tMax)) {
if (!isNearlyEqual(t0, t1)) {
int isEq = isNearlyEqual(t0, t1);
if ((tableID->timeEvents == ALWAYS && !isEq) ||
(tableID->timeEvents == AT_DISCONT && isEq)) {
tEvent = t1;
tableID->eventInterval++;
}
Expand Down
19 changes: 14 additions & 5 deletions Modelica/Resources/C-Sources/ModelicaStandardTables.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,22 @@
DUMMY_FUNCTION_USERTAB: Use a dummy function "usertab"
Release Notes:
Apr. 15, 2017: by Thomas Beutlich, ESI ITI GmbH
Added support for time event generation (independent of
smoothness) in CombiTimeTable (ticket #2080)
Apr. 11, 2017: by Thomas Beutlich, ESI ITI GmbH
Revised initialization of CombiTimeTable, CombiTable1D
and CombiTable2D (ticket #1899)
- Already read table in the initialization functions
- Removed the implementation of the read functions
Apr. 07, 2017: by Thomas Beutlich, ESI ITI GmbH
Decoupled shift time from start time in CombiTimeTable
(ticket #1771)
Added support for shift time (independent of start time)
in CombiTimeTable (ticket #1771)
Feb. 25, 2017: by Thomas Beutlich, ESI ITI GmbH
Added support of extrapolation for CombiTable1D
Added support for extrapolation in CombiTable1D
Added functions to retrieve minimum and maximum
abscissa values of CombiTable1D
(ticket #2120)
Expand All @@ -71,7 +75,7 @@
(= table is "NoName" or has only blanks AND
fileName is "NoName" or has only blanks).
(2) Read from a file (tableName, fileName have to be supplied).
(2) Read from a file (fileName, tableName have to be supplied).
Tables may be linearly interpolated or the first derivative
may be continuous. In the latter case, cubic Hermite splines with Akima slope
Expand Down Expand Up @@ -117,7 +121,7 @@ MODELICA_EXPORT void* ModelicaStandardTables_CombiTimeTable_init(_In_z_ const ch
_In_ int* columns,
size_t nCols, int smoothness,
int extrapolation) MODELICA_NONNULLATTR;
/* Same as ModelicaStandardTables_CombiTimeTable_init2, but without shiftTime and
/* Same as ModelicaStandardTables_CombiTimeTable_init2, but without shiftTime, timeEvents and
verbose arguments
*/

Expand All @@ -130,6 +134,7 @@ MODELICA_EXPORT void* ModelicaStandardTables_CombiTimeTable_init2(_In_z_ const c
size_t nCols, int smoothness,
int extrapolation,
double shiftTime,
int timeEvents,
int verbose) MODELICA_NONNULLATTR;
/* Initialize 1-dim. table where first column is time
Expand Down Expand Up @@ -158,6 +163,10 @@ MODELICA_EXPORT void* ModelicaStandardTables_CombiTimeTable_init2(_In_z_ const c
= 3: periodic
= 4: no
-> shiftTime: Shift time of first table column
-> timeEvents: Time event handling (for constant or linear interpolation)
= 1: always
= 2: at discontinuities
= 3: no
-> verbose: Print message that file is loading
<- RETURN: Pointer to internal memory of table structure
*/
Expand Down

0 comments on commit c64bb66

Please sign in to comment.