Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/minor-docs-improvements'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Dynamic/PlantSimulator/PlantSimulator.cs
#	TimeSeriesAnalysis.csproj
  • Loading branch information
Steinar Elgsæter committed Dec 3, 2024
2 parents 117db3e + be2a5f5 commit 53cd1c4
Show file tree
Hide file tree
Showing 21 changed files with 536 additions and 574 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ TestResult.xml
profiler/
docs/_site/
docs/api/
TimeSeriesAnalysis.ClosedTests/
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"FSharp.suggestGitignore": false
}
20 changes: 6 additions & 14 deletions Dynamic/Identification/FitScoreCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static double Calc(double[] meas, double[] sim)
static public double GetPlantWideSimulated(PlantSimulator plantSimObj, TimeSeriesDataSet inputData,
TimeSeriesDataSet simData)
{
// const string disturbanceSignalPrefix = "_D";
const string disturbanceSignalPrefix = "_D";
List<double> fitScores = new List<double>();
foreach (var modelName in plantSimObj.modelDict.Keys)
{
Expand All @@ -68,17 +68,13 @@ static public double GetPlantWideSimulated(PlantSimulator plantSimObj, TimeSerie
if (outputName == "" || outputName == null)
continue;


//
// Step 1: get the output signals of individual models in the measured dataset
//

if (plantSimObj.modelDict[modelName].GetProcessModelType() == ModelType.PID)
{
if (inputData.ContainsSignal(outputName))
{
measY = inputData.GetValues(outputName);
}

}
else //if (plantSimObj.modelDict[modelName].GetProcessModelType() == ModelType.SubProcess)
{
Expand All @@ -88,29 +84,25 @@ static public double GetPlantWideSimulated(PlantSimulator plantSimObj, TimeSerie
{
measY = inputData.GetValues(outputIdentName);
}
/* else if (simData.ContainsSignal(outputIdentName))
else if (simData.ContainsSignal(outputIdentName))
{
measY = simData.GetValues(outputIdentName);
}*/
}
}
// add in fit of process output, but only if "additive output signal" is not a
// locally identified "_D_" signal, as then output matches 100% always (any model error is put into disturbance signal as well)
/* else if (modelObj.GetAdditiveInputIDs() != null)
else if (modelObj.GetAdditiveInputIDs() != null)
{
if (!modelObj.GetAdditiveInputIDs()[0].StartsWith(disturbanceSignalPrefix))
{
measY = inputData.GetValues(outputName);
}
}*/
}
else if (inputData.ContainsSignal(outputName))
{
measY = inputData.GetValues(outputName);
}
}

//
// Step 2: get the corresponding signal from the simulated dataset
//
if (simData.ContainsSignal(outputName))
{
simY = simData.GetValues(outputName);
Expand Down
9 changes: 0 additions & 9 deletions Dynamic/Identification/GainSchedFittingSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,5 @@ public GainSchedFittingSpecs()
/// Default is 0, i.e. first input is used for gain-scheduling.
/// </summary>
public int uGainScheduledInputIndex = 0;

/// <summary>
/// If set to false, the model starts in the same value as the tuning set starts in,
/// if set to true, the model passes through the mean of the dataset.
/// </summary>
public bool DoSetOperatingPointToDatasetMean = false;



}
}
32 changes: 25 additions & 7 deletions Dynamic/Identification/GainSchedIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public static GainSchedModel IdentifyForGivenThresholds(UnitDataSet dataSet, Gai
if (idParams.Fitting.WasAbleToIdentify)
{
// simulate the model and determine the optimal bias term:
DetermineOperatingPointAndSimulate(ref idParams, ref dataSet, gsFittingSpecs.DoSetOperatingPointToDatasetMean);
DetermineOperatingPointAndSimulate(ref idParams, ref dataSet);

if (doTimeDelayEstimation)
EstimateTimeDelay(ref idParams, ref dataSet);
Expand Down Expand Up @@ -493,12 +493,12 @@ static private (GainSchedParameters, int) ChooseBestModelFromSimulationList(List
/// </summary>
/// <param name="gsParams">the gain-scheduled parameters that are to be updated with an operating point.</param>
/// <param name="dataSet">tuning dataset to be updated with Y_sim </param>
/// <param name="doMeanU">set the operating point to be the centre of the tuning set, if set to false models is set to match the start of the dataset</param>
///
/// <returns>true if able to estiamte bias, otherwise false</returns>
private static bool DetermineOperatingPointAndSimulate(ref GainSchedParameters gsParams, ref UnitDataSet dataSet, bool doMeanU)
private static bool DetermineOperatingPointAndSimulate(ref GainSchedParameters gsParams, ref UnitDataSet dataSet)
{
// if set to true, then the operating point is set to the average U in the dataset, otherwise it is set to equal the start
const bool doMeanU = false; // can be true or false, makes little difference?

var gsIdentModel = new GainSchedModel(gsParams, "ident_model");
var vec = new Vec(dataSet.BadDataID);

Expand All @@ -508,7 +508,7 @@ private static bool DetermineOperatingPointAndSimulate(ref GainSchedParameters g
var val = vec.Mean(vec.GetValues(dataSet.U.GetColumn(gsParams.GainSchedParameterIndex), dataSet.IndicesToIgnore));
if (val.HasValue && doMeanU)
{
desiredOpU = val.Value; //dataSet.U.GetColumn(gsParams.GainSchedParameterIndex).First();
desiredOpU = dataSet.U.GetColumn(gsParams.GainSchedParameterIndex).First();
}
gsParams.MoveOperatingPointUWithoutChangingModel(desiredOpU);

Expand Down Expand Up @@ -768,17 +768,35 @@ private static GainSchedParameters EvaluateMultipleTimeConstantsForGivenGainThre
{
curGainSchedParams_separateTc.TimeConstant_s = curTimeConstants;
curGainSchedParams_separateTc.TimeConstantThresholds = new double[] { candidateTcThresholds[i] };
DetermineOperatingPointAndSimulate(ref curGainSchedParams_separateTc, ref DS_separateTc,false);
DetermineOperatingPointAndSimulate(ref curGainSchedParams_separateTc, ref DS_separateTc);
candModelsStep2.Add(new GainSchedParameters(curGainSchedParams_separateTc));
// candYsimStep2.Add((double[])DS_separateTc.Y_sim.Clone());
}
else
{
curGainSchedParams_separateTc.TimeConstant_s = new double[] { curTimeConstants.First() };
curGainSchedParams_separateTc.TimeConstantThresholds = null;
DetermineOperatingPointAndSimulate(ref curGainSchedParams_separateTc, ref DS_separateTc,false);
DetermineOperatingPointAndSimulate(ref curGainSchedParams_separateTc, ref DS_separateTc);
candModelsStep2.Add(new GainSchedParameters(curGainSchedParams_separateTc));
}
/*
{
var curGainSchedParams_commonTc1 = new GainSchedParameters(curGainSchedParams_separateTc);
curGainSchedParams_commonTc1.TimeConstant_s = new double[] { curTimeConstants[0] };
curGainSchedParams_commonTc1.TimeConstantThresholds = null;
DetermineOperatingPointAndSimulate(ref curGainSchedParams_commonTc1, ref DS_commonTc1);
candModelsStep2.Add(new GainSchedParameters(curGainSchedParams_commonTc1));
// candYsimStep2.Add((double[])DS_commonTc1.Y_sim.Clone());
}
{
var curGainSchedParams_commonTc2 = new GainSchedParameters(curGainSchedParams_separateTc);
curGainSchedParams_commonTc2.TimeConstant_s = new double[] { curTimeConstants[1] };
curGainSchedParams_commonTc2.TimeConstantThresholds = null;
DetermineOperatingPointAndSimulate(ref curGainSchedParams_commonTc2, ref DS_commonTc2);
candModelsStep2.Add(new GainSchedParameters(curGainSchedParams_commonTc2));
// candYsimStep2.Add((double[])DS_commonTc2.Y_sim.Clone());
}
*/

bool doDebugPlot = false;
if (doDebugPlot)
Expand Down
34 changes: 17 additions & 17 deletions Dynamic/Identification/UnitIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,39 @@ namespace TimeSeriesAnalysis.Dynamic
{
/// <summary>
/// Identifier of the "Default" process model - a dynamic process model with time-constant, time-delay,
/// linear process gain and optional (nonlinear)curvature process gains.
/// linear process gain and optional (nonlinear) curvature process gains.
/// <para>
/// This model class is sufficent for real-world linear or weakly nonlinear dynamic systems, yet also introduces the fewest possible
/// parameters to describe the system in an attempt to avoiding over-fitting/over-parametrization
/// parameters to describe the system in an attempt to avoid over-fitting/over-parameterization.
/// </para>
/// <para>
/// The "default" process model is identified using a linear-in-parameters paramterization(paramters a,b,c), so that it can be solved by linear regression
/// and identification should thus be both fast and stable. The issue with the parametriation(a,b,c) is that the meaning of each paramter is less
/// inutitive, for instance the time constant depends on a, but linear gain depends on both a and b, while curvature depends on a and c.
/// The "default" process model is identified using a linear-in-parameters parameterization (parameters a,b,c), so that it can be solved by linear regression
/// and identification should thus be both fast and stable. The issue with the parameterization (a,b,c) is that the meaning of each parameter is less
/// intuitive, for instance the time constant depends on a, but linear gain depends on both a and b, while curvature depends on a and c.
/// Looking at the unceratinty of each parameter to determine if the model should be dynamic or static or what the uncertainty of the time constant is,
/// is very hard, and this observation motivates re-paramtrizing the model after identification.
/// is very hard, and this observation motivates re-parameterizing the model after identification.
/// </para>
/// <para>
/// When assessing and simulating the model, parmaters are converted into more intuitive paramters "time constant", "linear gains" and "curvature gain"
/// which are a different parametrization. The UnitIdentifier, UnitModel and UnitParamters classes handle this transition seamlessly to the user.
/// Uncertainty is expressed in terms of this more intuitive parametrization, to allow for a more intuitive assessment of the parameters.
/// When assessing and simulating the model, parameters are converted into the more intuitive parameters "time constant", "linear gains" and "curvature gain"
/// which are a different parameterization. The UnitIdentifier, UnitModel and UnitParameters classes handle this transition seamlessly to the user.
/// Uncertainty is expressed in terms of this more intuitive parameterization, to allow for a more intuitive assessment of the parameters.
/// </para>
/// <para>
/// Another advantage of the paramterization, is that the model internally separates betwen stedy-state and transient state, you can at any instance
/// Another advantage of the parameterization is that the model internally separates between steady-state and transient state. You can at any instance
/// "turn off" dynamics and request the steady-state model output for the current input. This is useful if you have transient data that you want to
/// analyze in the steady-state, as you can then fit the model to all available data-points without having to select what data points you beleive are at
/// analyze in the steady-state, as you can then fit the model to all available data-points without having to select what data points you believe are at
/// steady state, then you can disable dynamic terms to do a static analysis of the dynamic model.
/// </para>
/// <para>
/// Time-delay is an integer parameter, and finding the time-delay alongside continous paramters
/// Time-delay is an integer parameter, and finding the time-delay alongside continuous parameters
/// turns the identification problem into a linear mixed-integer problem.
/// The time delay identification is done by splitting the time-delay estimation from continous parameter
/// The time delay identification is done by splitting the time-delay estimation from continuous parameter
/// identification, turning the solver into a sequential optimization solver.
/// This logic to re-run estimation for multiple time-delays and selecting the best estiamte of time delay
/// is deferred to <seealso cref="UnitTimeDelayIdentifier"/>
/// This logic to re-run estimation for multiple time-delays and selecting the best estimate of time delay
/// is deferred to <seealso cref="UnitTimeDelayIdentifier"/>.
/// </para>
/// <para>
/// Since the aim is to identify transients/dynamics, the regression is done on model differences rather than absolute values
/// Since the aim is to identify transients/dynamics, the regression is done on model differences rather than absolute values.
/// </para>
/// </summary>

Expand All @@ -67,7 +67,7 @@ public static class UnitIdentifier
/// </summary>
/// <param name="dataSet">The dataset containing the ymeas and U that is to be fitted against,
/// a new y_sim is also added</param>
/// <param name="fittingSpecs">optional fitting specs object for tuning data</param>
/// <param name="fittingSpecs">optional fitting specs object for tuning data</param>
/// <param name="doEstimateTimeDelay">(default:true) if set to false, time delay estimation is disabled (can drastically speeed up identification)</param>
/// <returns> the identified model parameters and some information about the fit</returns>
public static UnitModel Identify(ref UnitDataSet dataSet,
Expand Down
Loading

0 comments on commit 53cd1c4

Please sign in to comment.