Skip to content

Commit

Permalink
- improving how PlantSimulate deals with "junctions" where process mo…
Browse files Browse the repository at this point in the history
…del and disturbance meet.

- fixed some faililng unit tests related to PlantSimulator
- sorting and renaming unit tests and moving them into folders
- moving some 'helper" methods out ot PlantSimulator and into PlantSimulatorHelper class
- new version of PlantSimulatorInitializer that uses DisturbanceCalculator has been created, but this is for now commented out (todo)
  • Loading branch information
Steinar Elgsæter committed Dec 19, 2024
1 parent 2ec1aa8 commit da30b41
Show file tree
Hide file tree
Showing 40 changed files with 862 additions and 838 deletions.
18 changes: 12 additions & 6 deletions Dynamic/Identification/ClosedLoopUnitIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,15 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
idDisturbancesList.Add(distIdResult1);
idUnitModelsList.Add(unitModel_step1);
if (doConsoleDebugOut)
ConsoleDebugOut(unitModel_step1, "Step 1,MISO");
{
string otherGains = "";
for(int i=0;i < unitModel_step1.GetModelParameters().LinearGains.Count();i++)
{
if (i!= pidInputIdx)
otherGains+= " other Gains: "+ unitModel_step1.GetModelParameters().LinearGains.ElementAt(i).ToString("F2");
}
ConsoleDebugOut(unitModel_step1, "Step 1,MISO", otherGains);
}
}

// EstimateDisturbanceLF(dataSetRun1, unitModel_step1, pidInputIdx, pidParams);
Expand Down Expand Up @@ -213,8 +221,6 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
}
}



// ----------------
// - issue is that after run 1 modelled output does not match measurement.
// - the reason that we want this run is that after run1 the time constant and
Expand Down Expand Up @@ -260,7 +266,7 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
DateTime[] dateTimes = null;
bool doDebugPlot = true;

(var plantSim, var inputData) = PlantSimulator.CreateFeedbackLoopWithEstimatedDisturbance(dataSetStep3, pidModel, unitModel, pidInputIdx);
(var plantSim, var inputData) = PlantSimulatorHelper.CreateFeedbackLoopWithEstimatedDisturbance(dataSetStep3, pidModel, unitModel, pidInputIdx);
if (doDebugPlot)
{
y_simList.Add(inputData.GetValues(unitModel.ID, SignalType.Output_Y));
Expand Down Expand Up @@ -459,7 +465,7 @@ private static double EstimateDisturbanceLF(UnitDataSet dataSet, UnitModel unitM
{
unitParams.LinearGains = new double[] { Kp };
umInternal.SetModelParameters(unitParams);
(var isOk, var y_proc) = PlantSimulator.SimulateSingle(dataSet, umInternal);
(var isOk, var y_proc) = PlantSimulatorHelper.SimulateSingle(dataSet, umInternal);
var d_LF = vec.Multiply(vec.Subtract(y_proc, y_proc[0]), -1);
var d_est1 = vec.Add(d_HF, d_LF);
var d_est2 = vec.Subtract(dataSet.Y_meas, y_proc);
Expand Down Expand Up @@ -1018,7 +1024,7 @@ public static bool ClosedLoopSim(UnitDataSet unitData, UnitParameters modelParam
//TODO: this does not ignore bad datapoints?
var pidModel = new PidModel(pidParams,"PidModel");
var unitModel = new UnitModel(modelParams, "ProcModel");
(var plantSim, var inputDataSet) = PlantSimulator.CreateFeedbackLoopWithEstimatedDisturbance(unitData, pidModel,
(var plantSim, var inputDataSet) = PlantSimulatorHelper.CreateFeedbackLoopWithEstimatedDisturbance(unitData, pidModel,
unitModel, pidInputIdx);

var isOk = plantSim.Simulate(inputDataSet, out var simData);
Expand Down
64 changes: 39 additions & 25 deletions Dynamic/Identification/DisturbanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

using TimeSeriesAnalysis;
using TimeSeriesAnalysis.Utility;
using Newtonsoft.Json.Linq;


namespace TimeSeriesAnalysis.Dynamic
Expand Down Expand Up @@ -72,14 +73,6 @@ public class DisturbanceIdResult
/// (For debugging:) an estimated process gain
/// </summary>
public double estPidProcessGain;
/// <summary>
/// (for debugging) the high-frequency component of the disturbance that is determined by observing changes in process variable y
/// </summary>
public double[] d_HF;
/// <summary>
/// (for debugging) the low-frequency component of the disturbance that is determined by observing changes in manipulated variable u
/// </summary>
public double[] d_LF;

/// <summary>
/// Constuctor
Expand All @@ -100,13 +93,9 @@ public void SetToZero()
d_est = Vec<double>.Fill(0, N);
estPidProcessGain = 0;
isAllZero = true;
d_HF = Vec<double>.Fill(0, N);
d_LF = Vec<double>.Fill(0, N);
adjustedUnitDataSet = null;

}


}

/// <summary>
Expand Down Expand Up @@ -158,12 +147,14 @@ private static UnitDataSet RemoveSetpointAndOtherInputChangeEffectsFromDataSet(U
// BEGIN "no_dist" process simulation =
// a simulation of the process that does not include any real Y_meas or u_pid, thus no effects of
// disturbances are visible in this simulation



var unitModelCopy = (UnitModel)unitModel.Clone("RemoveSetpointAndOtherInputChangeEffectsFromDataSet");// make copy that has no additive output signals(disturbance)
unitModelCopy.additiveInputIDs = null;

var processSim_noDist = new PlantSimulator(
new List<ISimulatableModel> { pidModel1, unitModel });
processSim_noDist.ConnectModels(unitModel, pidModel1);
processSim_noDist.ConnectModels(pidModel1, unitModel,pidInputIdx);
new List<ISimulatableModel> { pidModel1, unitModelCopy });
processSim_noDist.ConnectModels(unitModelCopy, pidModel1);
processSim_noDist.ConnectModels(pidModel1, unitModelCopy, pidInputIdx);

var inputData_noDist = new TimeSeriesDataSet();
if (unitDataSet.U.GetNColumns()>1)
Expand All @@ -172,7 +163,7 @@ private static UnitDataSet RemoveSetpointAndOtherInputChangeEffectsFromDataSet(U
{
if (curColIdx == pidInputIdx)
continue;
inputData_noDist.Add(processSim_noDist.AddExternalSignal(unitModel, SignalType.External_U, curColIdx),
inputData_noDist.Add(processSim_noDist.AddExternalSignal(unitModelCopy, SignalType.External_U, curColIdx),
unitDataSet.U.GetColumn(curColIdx));
}
}
Expand Down Expand Up @@ -203,7 +194,8 @@ private static UnitDataSet RemoveSetpointAndOtherInputChangeEffectsFromDataSet(U

// create a new Y_meas that excludes the influence of any disturbance using "no_Dist" simulation
// this is used to find d_HF
var procOutputY = simData_noDist.GetValues(unitModel.GetID(), SignalType.Output_Y);
//var procOutputY = simData_noDist.GetValues(unitModel.GetID(), SignalType.Output_Y);
var procOutputY = simData_noDist.GetValues(unitModelCopy.GetID());
var deltaProcOutputY = vec.Subtract(procOutputY, procOutputY[idxFirstGoodValue]);
unitDataSet_adjusted.Y_meas = vec.Subtract(unitDataSet.Y_meas, deltaProcOutputY);

Expand Down Expand Up @@ -289,7 +281,7 @@ public static DisturbanceIdResult CalculateDisturbanceVector(UnitDataSet unitDat
// non-disturbance related changes in the dataset producing "unitDataSet_adjusted"
var unitDataSet_adjusted = RemoveSetpointAndOtherInputChangeEffectsFromDataSet(unitDataSet, unitModel, pidInputIdx, pidParams);
unitDataSet_adjusted.D = null;
(bool isOk, double[] y_proc) = PlantSimulator.SimulateSingle(unitDataSet_adjusted, unitModel);
(bool isOk, double[] y_proc) = PlantSimulatorHelper.SimulateSingle(unitDataSet_adjusted, unitModel);

if (y_proc == null)
{
Expand All @@ -311,13 +303,35 @@ public static DisturbanceIdResult CalculateDisturbanceVector(UnitDataSet unitDat
}

//TODO: can these be removed?
double[] d_LF = vec.Multiply(vec.Subtract(y_proc, y_proc[indexOfFirstGoodValue]), -1);
double[] d_HF = vec.Subtract(unitDataSet_adjusted.Y_meas, unitDataSet_adjusted.Y_setpoint);
//double[] d_LF = vec.Multiply(vec.Subtract(y_proc, y_proc[indexOfFirstGoodValue]), -1);
//double[] d_HF = vec.Subtract(unitDataSet_adjusted.Y_meas, unitDataSet_adjusted.Y_setpoint);

// old: d[k] = y_meas[k] -y_proc[k]
//double[] d_est = vec.Subtract(unitDataSet_adjusted.Y_meas, y_proc);

bool IsNaN(double value)
{
if (double.IsNaN(value) || value == unitDataSet_adjusted.BadDataID)
return true;
else
return false;
}

double[] d_est = new double[unitDataSet_adjusted.Y_meas.Length];

for (int i = 1; i < d_est.Length; i++)
{
if (IsNaN(unitDataSet_adjusted.Y_meas[i]) || IsNaN(y_proc[i]))
d_est[i] = double.NaN;
else
d_est[i] = unitDataSet_adjusted.Y_meas[i] - y_proc[i-1];
}
d_est[0] = unitDataSet_adjusted.Y_meas[0] - y_proc[0];


double[] d_est = vec.Subtract(unitDataSet_adjusted.Y_meas, y_proc);
result.d_est = d_est;
result.d_LF = d_LF;
result.d_HF = d_HF;
//result.d_LF = d_LF;
// result.d_HF = d_HF;
result.estPidProcessGain = unitModel.GetModelParameters().LinearGains.ElementAt(pidInputIdx);
result.adjustedUnitDataSet = unitDataSet_adjusted;

Expand Down
8 changes: 4 additions & 4 deletions Dynamic/Identification/GainSchedIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ static private (GainSchedParameters, int) ChooseBestModelFromFittingInfo(
if (simulateAndAddToYsimInDataSet)
{
var bestModel = new GainSchedModel(BestGainSchedParams);
PlantSimulator.SimulateSingleToYsim(dataSet, bestModel);
PlantSimulatorHelper.SimulateSingleToYsim(dataSet, bestModel);
}
return (BestGainSchedParams, bestModelIdx);
}
Expand Down Expand Up @@ -512,7 +512,7 @@ private static bool DetermineOperatingPointAndSimulate(ref GainSchedParameters g
}
gsParams.MoveOperatingPointUWithoutChangingModel(desiredOpU);

(var isOk, var y_sim) = PlantSimulator.SimulateSingle(dataSet, gsIdentModel);
(var isOk, var y_sim) = PlantSimulatorHelper.SimulateSingle(dataSet, gsIdentModel);

if (isOk)
{
Expand All @@ -523,7 +523,7 @@ private static bool DetermineOperatingPointAndSimulate(ref GainSchedParameters g
if (estBias.HasValue)
{
gsParams.IncreaseOperatingPointY(estBias.Value);
(var isOk2, var y_sim2) = PlantSimulator.SimulateSingle(dataSet, gsIdentModel);
(var isOk2, var y_sim2) = PlantSimulatorHelper.SimulateSingle(dataSet, gsIdentModel);
dataSet.Y_sim = y_sim2;
if (gsParams.Fitting == null)
gsParams.Fitting = new FittingInfo();
Expand Down Expand Up @@ -587,7 +587,7 @@ private static void EstimateTimeDelay(ref GainSchedParameters gsParams, ref Unit
copiedGsParams.TimeConstant_s = vec.Subtract(gsParams.TimeConstant_s, timedelay_s);

var gsIdentModel = new GainSchedModel(copiedGsParams, "ident_model");
(var isOk, var y_sim) = PlantSimulator.SimulateSingle(dataSet, gsIdentModel);
(var isOk, var y_sim) = PlantSimulatorHelper.SimulateSingle(dataSet, gsIdentModel);

if (isOk)
{
Expand Down
4 changes: 2 additions & 2 deletions Dynamic/Identification/UnitIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public static UnitModel IdentifyLinearDiff(ref UnitDataSet dataSet, FittingSpecs

if (model.modelParameters.Fitting.WasAbleToIdentify)
{
PlantSimulator.SimulateSingleToYsim(dataSet, model);
PlantSimulatorHelper.SimulateSingleToYsim(dataSet, model);
model.SetFittedDataSet(dataSet);
}
return model;
Expand Down Expand Up @@ -449,7 +449,7 @@ private static UnitModel Identify_Internal(ref UnitDataSet dataSet, FittingSpecs
// simulate
if (modelParameters.Fitting.WasAbleToIdentify)
{
PlantSimulator.SimulateSingleToYsim(dataSet, model);
PlantSimulatorHelper.SimulateSingleToYsim(dataSet, model);
model.SetFittedDataSet(dataSet);
}
return model;
Expand Down
44 changes: 44 additions & 0 deletions Dynamic/PlantSimulator/Comment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace TimeSeriesAnalysis.Dynamic
{
/// <summary>
/// Class that holds comments added to models.
/// </summary>
public class Comment
{
/// <summary>
/// Author of comment.
/// </summary>
public string author;
/// <summary>
/// Date of comment.
/// </summary>
public DateTime date;
/// <summary>
/// Comment string
/// </summary>
public string comment;
/// <summary>
/// Plant score, intended to hold manully set values indicating specific statuses of the model.
/// </summary>
public double plantScore;

/// <summary>
/// Comment constructor.
/// </summary>
/// <param name="author"></param>
/// <param name="date"></param>
/// <param name="comment"></param>
/// <param name="plantScore"></param>
public Comment(string author, DateTime date, string comment, double plantScore = 0)
{
this.author = author;
this.date = date;
this.comment = comment;
this.plantScore = plantScore;
}
}
}
Loading

0 comments on commit da30b41

Please sign in to comment.