Skip to content

Commit

Permalink
refs #2244: Improve extrapolation diagnostics
Browse files Browse the repository at this point in the history
* Add new parameter verboseExtrapolation to CombiTimeTable, CombiTable1Ds, CombiTable1D and CombiTable2D
* In case of extrapolation and if verboseExtrapolation is set to true, warnings are raised (by means of assertion)
* Improve error message if extrapolation triggers an error
  • Loading branch information
beutlich committed Apr 24, 2017
1 parent a54375a commit 21cab5d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 7 deletions.
17 changes: 17 additions & 0 deletions Modelica/Blocks/Sources.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2153,6 +2153,9 @@ If, e.g., time = 1.0, the output y = 0.0 (before event), 1.0 (after event)
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));
parameter Boolean verboseExtrapolation=false
"= true, if warning messages are to be printed if time is outside the table definition range"
annotation (Dialog(group="Table data interpretation", enable=extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint));
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 Down Expand Up @@ -2190,6 +2193,20 @@ If, e.g., time = 1.0, the output y = 0.0 (before event), 1.0 (after event)
assert(size(table, 1) > 0 and size(table, 2) > 0,
"tableOnFile = false and parameter table is an empty matrix");
end if;

if verboseExtrapolation and (
extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
assert(noEvent(time >= t_min), "
Extrapolation warning: Time (=" + String(time) + ") must be greater or equal
than the minimum abscissa value t_min (=" + String(t_min) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(time <= t_max), "
Extrapolation warning: Time (=" + String(time) + ") must be less or equal
than the maximum abscissa value t_max (=" + String(t_max) + ") defined in the table.
", level=AssertionLevel.warning);
end if;

timeScaled = time/timeScale;
when {time >= pre(nextTimeEvent), initial()} then
nextTimeEventScaled = Internal.getNextTimeEvent(tableID, timeScaled);
Expand Down
83 changes: 83 additions & 0 deletions Modelica/Blocks/Tables.mo
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ package Tables
parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
"Extrapolation of data outside the definition range"
annotation (Dialog(group="Table data interpretation"));
parameter Boolean verboseExtrapolation=false
"= true, if warning messages are to be printed if table input is outside the definition range"
annotation (Dialog(group="Table data interpretation", enable=extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint));
final parameter Real u_min=Internal.getTable1DAbscissaUmin(tableID)
"Minimum abscissa value defined in table";
final parameter Real u_max=Internal.getTable1DAbscissaUmax(tableID)
Expand All @@ -55,6 +58,22 @@ package Tables
assert(size(table, 1) > 0 and size(table, 2) > 0,
"tableOnFile = false and parameter table is an empty matrix");
end if;

if verboseExtrapolation and (
extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
for i in 1:n loop
assert(noEvent(u[i] >= u_min), "
Extrapolation warning: The value u[" + String(i) +"] (=" + String(u[i]) + ") must be greater or equal
than the minimum abscissa value u_min (=" + String(u_min) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(u[i] <= u_max), "
Extrapolation warning: The value u[" + String(i) +"] (=" + String(u[i]) + ") must be less or equal
than the maximum abscissa value u_max (=" + String(u_max) + ") defined in the table.
", level=AssertionLevel.warning);
end for;
end if;

if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
for i in 1:n loop
y[i] = Internal.getTable1DValueNoDer(tableID, i, u[i]);
Expand Down Expand Up @@ -302,6 +321,9 @@ MATLAB is a registered trademark of The MathWorks, Inc.
parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
"Extrapolation of data outside the definition range"
annotation (Dialog(group="Table data interpretation"));
parameter Boolean verboseExtrapolation=false
"= true, if warning messages are to be printed if table input is outside the definition range"
annotation (Dialog(group="Table data interpretation", enable=extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint));
final parameter Real u_min=Internal.getTable1DAbscissaUmin(tableID)
"Minimum abscissa value defined in table";
final parameter Real u_max=Internal.getTable1DAbscissaUmax(tableID)
Expand All @@ -325,6 +347,20 @@ MATLAB is a registered trademark of The MathWorks, Inc.
assert(size(table, 1) > 0 and size(table, 2) > 0,
"tableOnFile = false and parameter table is an empty matrix");
end if;

if verboseExtrapolation and (
extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
assert(noEvent(u >= u_min), "
Extrapolation warning: The value u (=" + String(u) + ") must be greater or equal
than the minimum abscissa value u_min (=" + String(u_min) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(u <= u_max), "
Extrapolation warning: The value u (=" + String(u) + ") must be less or equal
than the maximum abscissa value u_max (=" + String(u_max) + ") defined in the table.
", level=AssertionLevel.warning);
end if;

if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
for i in 1:nout loop
y[i] = Internal.getTable1DValueNoDer(tableID, i, u);
Expand Down Expand Up @@ -568,6 +604,13 @@ MATLAB is a registered trademark of The MathWorks, Inc.
parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
"Extrapolation of data outside the definition range"
annotation (Dialog(group="Table data interpretation", enable=false));
parameter Boolean verboseExtrapolation=false
"= true, if warning messages are to be printed if table input is outside the definition range"
annotation (Dialog(group="Table data interpretation", enable=extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint));
final parameter Real u_min[2]=Internal.getTable2DAbscissaUmin(tableID)
"Minimum abscissa value defined in table";
final parameter Real u_max[2]=Internal.getTable2DAbscissaUmax(tableID)
"Maximum abscissa value defined in table";
protected
parameter Modelica.Blocks.Types.ExternalCombiTable2D tableID=
Modelica.Blocks.Types.ExternalCombiTable2D(
Expand All @@ -586,6 +629,28 @@ MATLAB is a registered trademark of The MathWorks, Inc.
assert(size(table, 1) > 0 and size(table, 2) > 0,
"tableOnFile = false and parameter table is an empty matrix");
end if;

if verboseExtrapolation and (
extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
assert(noEvent(u1 >= u_min[1]), "
Extrapolation warning: The value u1 (=" + String(u1) + ") must be greater or equal
than the minimum abscissa value u_min[1] (=" + String(u_min[1]) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(u1 <= u_max[1]), "
Extrapolation warning: The value u1 (=" + String(u1) + ") must be less or equal
than the maximum abscissa value u_max[1] (=" + String(u_max[1]) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(u2 >= u_min[2]), "
Extrapolation warning: The value u2 (=" + String(u2) + ") must be greater or equal
than the minimum abscissa value u_min[2] (=" + String(u_min[2]) + ") defined in the table.
", level=AssertionLevel.warning);
assert(noEvent(u2 <= u_max[2]), "
Extrapolation warning: The value u2 (=" + String(u2) + ") must be less or equal
than the maximum abscissa value u_max[2] (=" + String(u_max[2]) + ") defined in the table.
", level=AssertionLevel.warning);
end if;

if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
y = Internal.getTable2DValueNoDer(tableID, u1, u2);
else
Expand Down Expand Up @@ -970,6 +1035,24 @@ MATLAB is a registered trademark of The MathWorks, Inc.
external"C" der_y = ModelicaStandardTables_CombiTable2D_getDerValue(tableID, u1, u2, der_u1, der_u2)
annotation (Library={"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO", "zlib"});
end getDerTable2DValue;

function getTable2DAbscissaUmin
"Return minimum abscissa value of 2-dim. table defined by matrix"
extends Modelica.Icons.Function;
input Modelica.Blocks.Types.ExternalCombiTable1D tableID;
output Real uMin[2] "Minimum abscissa value in table";
external"C" ModelicaStandardTables_CombiTable2D_minimumAbscissa(tableID, uMin)
annotation (Library={"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO", "zlib"});
end getTable2DAbscissaUmin;

function getTable2DAbscissaUmax
"Return maximum abscissa value of 2-dim. table defined by matrix"
extends Modelica.Icons.Function;
input Modelica.Blocks.Types.ExternalCombiTable1D tableID;
output Real uMax[2] "Maximum abscissa value in table";
external"C" ModelicaStandardTables_CombiTable2D_maximumAbscissa(tableID, uMax)
annotation (Library={"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO", "zlib"});
end getTable2DAbscissaUmax;
end Internal;
annotation (Documentation(info="<html>
<p>This package contains blocks for one- and two-dimensional interpolation in tables.</p>
Expand Down
65 changes: 58 additions & 7 deletions Modelica/Resources/C-Sources/ModelicaStandardTables.c
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,14 @@ double ModelicaStandardTables_CombiTimeTable_getValue(void* _tableID, int iCol,
break;

case NO_EXTRAPOLATION:
ModelicaError("Extrapolation error\n");
ModelicaFormatError("Extrapolation error: Time "
"(=%lf) must be %s or equal\nthan the %s abscissa "
"value %s (=%lf) defined in the table.\n", tOld,
(extrapolate == LEFT) ? "greater" : "less",
(extrapolate == LEFT) ? "minimum" : "maximum",
(extrapolate == LEFT) ? "t_min" : "t_max",
(extrapolate == LEFT) ?
TABLE_ROW0(0) : TABLE_COL0(tableID->nRow - 1));
return y;

case PERIODIC:
Expand Down Expand Up @@ -1259,7 +1266,14 @@ double ModelicaStandardTables_CombiTimeTable_getDerValue(void* _tableID, int iCo
break;

case NO_EXTRAPOLATION:
ModelicaError("Extrapolation error\n");
ModelicaFormatError("Extrapolation error: Time "
"(=%lf) must be %s or equal\nthan the %s abscissa "
"value %s (=%lf) defined in the table.\n", tOld,
(extrapolate == LEFT) ? "greater" : "less",
(extrapolate == LEFT) ? "minimum" : "maximum",
(extrapolate == LEFT) ? "t_min" : "t_max",
(extrapolate == LEFT) ?
TABLE_ROW0(0) : TABLE_COL0(tableID->nRow - 1));
return der_y;

case PERIODIC:
Expand Down Expand Up @@ -1469,9 +1483,9 @@ double ModelicaStandardTables_CombiTimeTable_nextTimeEvent(void* _tableID,
int isEq = isNearlyEqual(t0, t1);
if ((tableID->timeEvents == ALWAYS && !isEq) ||
(tableID->timeEvents == AT_DISCONT && isEq)) {
nextTimeEvent = t0;
break;
}
nextTimeEvent = t0;
break;
}
}
}

Expand Down Expand Up @@ -1961,7 +1975,14 @@ double ModelicaStandardTables_CombiTable1D_getValue(void* _tableID, int iCol,
break;

case NO_EXTRAPOLATION:
ModelicaError("Extrapolation error\n");
ModelicaFormatError("Extrapolation error: The value u "
"(=%lf) must be %s or equal\nthan the %s abscissa "
"value %s (=%lf) defined in the table.\n", u,
(extrapolate == LEFT) ? "greater" : "less",
(extrapolate == LEFT) ? "minimum" : "maximum",
(extrapolate == LEFT) ? "u_min" : "u_max",
(extrapolate == LEFT) ?
TABLE_ROW0(0) : TABLE_COL0(tableID->nRow - 1));
return y;

case PERIODIC:
Expand Down Expand Up @@ -2095,7 +2116,14 @@ double ModelicaStandardTables_CombiTable1D_getDerValue(void* _tableID, int iCol,
break;

case NO_EXTRAPOLATION:
ModelicaError("Extrapolation error\n");
ModelicaFormatError("Extrapolation error: The value u "
"(=%lf) must be %s or equal\nthan the %s abscissa "
"value %s (=%lf) defined in the table.\n", u,
(extrapolate == LEFT) ? "greater" : "less",
(extrapolate == LEFT) ? "minimum" : "maximum",
(extrapolate == LEFT) ? "u_min" : "u_max",
(extrapolate == LEFT) ?
TABLE_ROW0(0) : TABLE_COL0(tableID->nRow - 1));
return der_y;

case PERIODIC:
Expand Down Expand Up @@ -3038,6 +3066,29 @@ double ModelicaStandardTables_CombiTable2D_getDerValue(void* _tableID, double u1
return der_y;
}

void ModelicaStandardTables_CombiTable2D_minimumAbscissa(void* _tableID,
_Inout_ double* uMin) {
CombiTable2D* tableID = (CombiTable2D*)_tableID;
if (NULL != tableID && NULL != tableID->table) {
const double* table = tableID->table;
const size_t nCol = tableID->nCol;
uMin[0] = TABLE_COL0(1);
uMin[1] = TABLE_ROW0(1);
}
}

void ModelicaStandardTables_CombiTable2D_maximumAbscissa(void* _tableID,
_Inout_ double* uMax) {
CombiTable2D* tableID = (CombiTable2D*)_tableID;
if (NULL != tableID && NULL != tableID->table) {
const double* table = tableID->table;
const size_t nRow = tableID->nRow;
const size_t nCol = tableID->nCol;
uMax[0] = TABLE_COL0(nRow - 1);
uMax[1] = TABLE_ROW0(nCol - 1);
}
}

double ModelicaStandardTables_CombiTable2D_read(void* _tableID, int force,
int verbose) {
return 1.; /* Success */
Expand Down
8 changes: 8 additions & 0 deletions Modelica/Resources/C-Sources/ModelicaStandardTables.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ MODELICA_EXPORT void* ModelicaStandardTables_CombiTable2D_init2(_In_z_ const cha
MODELICA_EXPORT void ModelicaStandardTables_CombiTable2D_close(void* tableID);
/* Close table and free allocated memory */

MODELICA_EXPORT void ModelicaStandardTables_CombiTable2D_minimumAbscissa(void* tableID,
_Inout_ double* uMin);
/* Get minimum abscissa defined in table (= table[2,1] and table[end,1]) */

MODELICA_EXPORT void ModelicaStandardTables_CombiTable2D_maximumAbscissa(void* tableID,
_Inout_ double* uMax);
/* Get maximum abscissa defined in table (= table[1,2] and table[1,end]) */

MODELICA_EXPORT double ModelicaStandardTables_CombiTable2D_getValue(void* tableID, double u1,
double u2);
/* Interpolate in table
Expand Down

0 comments on commit 21cab5d

Please sign in to comment.