From 21cab5d68aa25b506d2d41014b2ad6b3bc1a1ee3 Mon Sep 17 00:00:00 2001 From: Thomas Beutlich Date: Mon, 24 Apr 2017 23:05:21 +0200 Subject: [PATCH] refs #2244: Improve extrapolation diagnostics * 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 --- Modelica/Blocks/Sources.mo | 17 ++++ Modelica/Blocks/Tables.mo | 83 +++++++++++++++++++ .../C-Sources/ModelicaStandardTables.c | 65 +++++++++++++-- .../C-Sources/ModelicaStandardTables.h | 8 ++ 4 files changed, 166 insertions(+), 7 deletions(-) diff --git a/Modelica/Blocks/Sources.mo b/Modelica/Blocks/Sources.mo index 440457c3ca..1c90bb7faa 100644 --- a/Modelica/Blocks/Sources.mo +++ b/Modelica/Blocks/Sources.mo @@ -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 @@ -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); diff --git a/Modelica/Blocks/Tables.mo b/Modelica/Blocks/Tables.mo index 946a6664ce..f47edb6124 100644 --- a/Modelica/Blocks/Tables.mo +++ b/Modelica/Blocks/Tables.mo @@ -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) @@ -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]); @@ -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) @@ -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); @@ -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( @@ -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 @@ -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="

This package contains blocks for one- and two-dimensional interpolation in tables.

diff --git a/Modelica/Resources/C-Sources/ModelicaStandardTables.c b/Modelica/Resources/C-Sources/ModelicaStandardTables.c index 725f3bb6b9..5b8fb38394 100644 --- a/Modelica/Resources/C-Sources/ModelicaStandardTables.c +++ b/Modelica/Resources/C-Sources/ModelicaStandardTables.c @@ -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: @@ -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: @@ -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; + } } } @@ -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: @@ -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: @@ -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 */ diff --git a/Modelica/Resources/C-Sources/ModelicaStandardTables.h b/Modelica/Resources/C-Sources/ModelicaStandardTables.h index 1ed4d52c81..2ea927de33 100644 --- a/Modelica/Resources/C-Sources/ModelicaStandardTables.h +++ b/Modelica/Resources/C-Sources/ModelicaStandardTables.h @@ -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