summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Project/ElectricCalculation.cpp27
-rw-r--r--Project/ElementForm.wxcp84
-rw-r--r--Project/ElementFormBase.cpp11
-rw-r--r--Project/ElementFormBase.h3
-rw-r--r--Project/IndMotor.cpp61
-rw-r--r--Project/IndMotor.h13
-rw-r--r--Project/IndMotorForm.cpp15
-rw-r--r--Project/IndMotorForm.h3
-rw-r--r--Project/PowerFlow.cpp179
-rw-r--r--Project/PowerFlow.h13
-rw-r--r--Project/PropertiesData.h1
-rw-r--r--Project/PropertiesForm.wxcp192
-rw-r--r--Project/PropertiesFormBase.cpp20
-rw-r--r--Project/PropertiesFormBase.h4
-rw-r--r--Project/SimulationsSettingsForm.cpp8
-rw-r--r--Project/Workspace.cpp12
16 files changed, 573 insertions, 73 deletions
diff --git a/Project/ElectricCalculation.cpp b/Project/ElectricCalculation.cpp
index 7b03eeb..a2db413 100644
--- a/Project/ElectricCalculation.cpp
+++ b/Project/ElectricCalculation.cpp
@@ -397,6 +397,33 @@ void ElectricCalculation::UpdateElementsPowerFlow(std::vector<std::complex<doubl
}
}
+ // Ind motor
+ for(unsigned int i = 0; i < m_indMotorList.size(); i++) {
+ IndMotor* motor = m_indMotorList[i];
+ auto data = motor->GetElectricalData();
+ if(motor->IsOnline() && data.calcQInPowerFlow) {
+ double reactivePower = data.qValue * systemPowerBase;
+
+ switch(data.reactivePowerUnit) {
+ case UNIT_PU: {
+ reactivePower /= systemPowerBase;
+ } break;
+ case UNIT_kVAr: {
+ reactivePower /= 1e3;
+ } break;
+ case UNIT_MVAr: {
+ reactivePower /= 1e6;
+ } break;
+ default:
+ break;
+ }
+
+ data.reactivePower = reactivePower;
+
+ motor->SetElectricalData(data);
+ }
+ }
+
// Synchronous machines
for(int i = 0; i < (int)m_busList.size(); i++) {
Bus* bus = m_busList[i];
diff --git a/Project/ElementForm.wxcp b/Project/ElementForm.wxcp
index db8b092..a53c597 100644
--- a/Project/ElementForm.wxcp
+++ b/Project/ElementForm.wxcp
@@ -1,7 +1,7 @@
{
"metadata": {
"m_generatedFilesDir": ".",
- "m_objCounter": 2190,
+ "m_objCounter": 2191,
"m_includeFiles": [],
"m_bitmapFunction": "wxC9EE9InitBitmapResources",
"m_bitmapsFile": "ElementFormBitmaps.cpp",
@@ -29858,6 +29858,88 @@
}, {
"type": "string",
"m_label": "Name:",
+ "m_value": "m_checkBoxComputeQ"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Label:",
+ "m_value": "Calculate reactive power in load flow (using stability data)"
+ }, {
+ "type": "bool",
+ "m_label": "Value:",
+ "m_value": false
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_COMMAND_CHECKBOX_CLICKED",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnCalcQInPFClick(wxCommandEvent& event)",
+ "m_description": "Process a wxEVT_COMMAND_CHECKBOX_CLICKED event, when the checkbox is clicked.",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }, {
+ "m_type": 4415,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
"m_value": "m_checkBoxUseMachinePower"
}, {
"type": "multi-string",
diff --git a/Project/ElementFormBase.cpp b/Project/ElementFormBase.cpp
index 6a75ec7..25fc622 100644
--- a/Project/ElementFormBase.cpp
+++ b/Project/ElementFormBase.cpp
@@ -3187,6 +3187,13 @@ IndMotorFormBase::IndMotorFormBase(wxWindow* parent,
boxSizerLvl5_2->Add(m_choiceReactivePower, 0, wxLEFT | wxRIGHT | wxBOTTOM, WXC_FROM_DIP(5));
+ m_checkBoxComputeQ =
+ new wxCheckBox(m_panelGeneral, wxID_ANY, _("Calculate reactive power in load flow (using stability data)"),
+ wxDefaultPosition, wxDLG_UNIT(m_panelGeneral, wxSize(-1, -1)), 0);
+ m_checkBoxComputeQ->SetValue(false);
+
+ boxSizerLvl2_1->Add(m_checkBoxComputeQ, 0, wxALL | wxALIGN_CENTER_VERTICAL, WXC_FROM_DIP(5));
+
m_checkBoxUseMachinePower = new wxCheckBox(m_panelGeneral, wxID_ANY, _("Use machine rated power as base"),
wxDefaultPosition, wxDLG_UNIT(m_panelGeneral, wxSize(-1, -1)), 0);
m_checkBoxUseMachinePower->SetValue(false);
@@ -3510,6 +3517,8 @@ IndMotorFormBase::IndMotorFormBase(wxWindow* parent,
}
#endif
// Connect events
+ m_checkBoxComputeQ->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
+ wxCommandEventHandler(IndMotorFormBase::OnCalcQInPFClick), NULL, this);
m_checkBoxUseKf->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
wxCommandEventHandler(IndMotorFormBase::OnCheckboxUseCageFactorClick), NULL, this);
m_buttonSwitchingButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
@@ -3522,6 +3531,8 @@ IndMotorFormBase::IndMotorFormBase(wxWindow* parent,
IndMotorFormBase::~IndMotorFormBase()
{
+ m_checkBoxComputeQ->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED,
+ wxCommandEventHandler(IndMotorFormBase::OnCalcQInPFClick), NULL, this);
m_checkBoxUseKf->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED,
wxCommandEventHandler(IndMotorFormBase::OnCheckboxUseCageFactorClick), NULL, this);
m_buttonSwitchingButton->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED,
diff --git a/Project/ElementFormBase.h b/Project/ElementFormBase.h
index 734681c..c8fe7f0 100644
--- a/Project/ElementFormBase.h
+++ b/Project/ElementFormBase.h
@@ -771,6 +771,7 @@ class IndMotorFormBase : public wxDialog
wxStaticText* m_staticTextReactivePower;
wxTextCtrl* m_textCtrlReactivePower;
wxChoice* m_choiceReactivePower;
+ wxCheckBox* m_checkBoxComputeQ;
wxCheckBox* m_checkBoxUseMachinePower;
wxPanel* m_panelStability;
wxCheckBox* m_checkBoxPlotIndMachine;
@@ -806,6 +807,7 @@ class IndMotorFormBase : public wxDialog
wxButton* m_ButtonCancel;
protected:
+ virtual void OnCalcQInPFClick(wxCommandEvent& event) { event.Skip(); }
virtual void OnCheckboxUseCageFactorClick(wxCommandEvent& event) { event.Skip(); }
virtual void OnStabilityButtonClick(wxCommandEvent& event) { event.Skip(); }
virtual void OnOKButtonClick(wxCommandEvent& event) { event.Skip(); }
@@ -823,6 +825,7 @@ class IndMotorFormBase : public wxDialog
wxStaticText* GetStaticTextReactivePower() { return m_staticTextReactivePower; }
wxTextCtrl* GetTextCtrlReactivePower() { return m_textCtrlReactivePower; }
wxChoice* GetChoiceReactivePower() { return m_choiceReactivePower; }
+ wxCheckBox* GetCheckBoxComputeQ() { return m_checkBoxComputeQ; }
wxCheckBox* GetCheckBoxUseMachinePower() { return m_checkBoxUseMachinePower; }
wxPanel* GetPanelGeneral() { return m_panelGeneral; }
wxCheckBox* GetCheckBoxPlotIndMachine() { return m_checkBoxPlotIndMachine; }
diff --git a/Project/IndMotor.cpp b/Project/IndMotor.cpp
index cace164..4df2bb1 100644
--- a/Project/IndMotor.cpp
+++ b/Project/IndMotor.cpp
@@ -263,3 +263,64 @@ bool IndMotor::GetPlotData(ElementPlotData& plotData, PlotStudy study)
plotData.AddData(m_electricalData.slipVector, _("Slip"));
return true;
}
+
+void IndMotor::InitPowerFlowMotor(double systemPowerBase, int busNumber)
+{
+ double k = 1.0; // Power base change factor.
+ if(m_electricalData.useMachinePowerAsBase) {
+ double oldBase = GetValueFromUnit(m_electricalData.ratedPower, m_electricalData.ratedPowerUnit);
+ k = systemPowerBase / oldBase;
+ }
+ // Calculate the induction machine transient constants at the machine base
+ m_electricalData.r1t = m_electricalData.r1 * k;
+ m_electricalData.r2t = m_electricalData.r2 * k;
+ m_electricalData.x1t = m_electricalData.x1 * k;
+ m_electricalData.x2t = m_electricalData.x2 * k;
+ m_electricalData.xmt = m_electricalData.xm * k;
+
+ m_electricalData.xt = m_electricalData.x1t +
+ (m_electricalData.x2t * m_electricalData.xmt) / (m_electricalData.x2t + m_electricalData.xmt);
+ m_electricalData.x0 = m_electricalData.x1t + m_electricalData.xmt;
+
+ double r1 = m_electricalData.r1t;
+ double r2 = m_electricalData.r2t;
+ if(m_electricalData.useKf) r2 *= (1.0 + m_electricalData.kf * m_electricalData.r2t);
+ double x1 = m_electricalData.x1t;
+ double x2 = m_electricalData.x2t;
+ double xm = m_electricalData.xmt;
+ m_electricalData.k1 = x2 + xm;
+ m_electricalData.k2 = -x1 * m_electricalData.k1 - x2 * xm;
+ m_electricalData.k3 = xm + x1;
+ m_electricalData.k4 = r1 * m_electricalData.k1;
+
+ auto puData = GetPUElectricalData(systemPowerBase);
+ m_electricalData.p0 = puData.activePower;
+ m_electricalData.busNum = busNumber;
+}
+
+bool IndMotor::CalculateReactivePower(double voltage)
+{
+ double a = m_electricalData.p0 *
+ (m_electricalData.r1t * m_electricalData.r1t + m_electricalData.k3 * m_electricalData.k3) -
+ voltage * voltage * m_electricalData.r1t;
+ double b = 2.0 * m_electricalData.p0 *
+ (m_electricalData.r1t * m_electricalData.k2 + m_electricalData.k3 * m_electricalData.k4) -
+ voltage * voltage * (m_electricalData.k2 + m_electricalData.k1 * m_electricalData.k3);
+ double c =
+ m_electricalData.p0 * (m_electricalData.k2 * m_electricalData.k2 + m_electricalData.k4 * m_electricalData.k4) -
+ voltage * voltage * m_electricalData.k1 * m_electricalData.k4;
+ double d = (b * b - 4.0 * a * c);
+ if(d < 0.0) return false;
+ double r2_s = (-b + std::sqrt(d)) / (2.0 * a);
+
+ double qa = m_electricalData.k1 * (r2_s * m_electricalData.r1t - m_electricalData.x1t * m_electricalData.k1 -
+ m_electricalData.x2t * m_electricalData.xmt);
+ double qb =
+ r2_s * (r2_s * (m_electricalData.xmt + m_electricalData.x1t) + m_electricalData.r1t * m_electricalData.k1);
+ double qc = r2_s * m_electricalData.r1t - m_electricalData.x1t * m_electricalData.k1 -
+ m_electricalData.x2t * m_electricalData.xmt;
+ double qd = r2_s * (m_electricalData.xmt + m_electricalData.x1t) + m_electricalData.r1t * m_electricalData.k1;
+ m_electricalData.qValue = (-voltage * voltage * (qa - qb)) / (qc * qc + qd * qd);
+
+ return true;
+}
diff --git a/Project/IndMotor.h b/Project/IndMotor.h
index 89bd6e1..0aa6937 100644
--- a/Project/IndMotor.h
+++ b/Project/IndMotor.h
@@ -32,6 +32,17 @@ struct IndMotorElectricalData {
ElectricalUnit reactivePowerUnit = UNIT_MVAr;
bool useMachinePowerAsBase = true;
+ bool calcQInPowerFlow = true;
+
+ // Power flow
+ double k1 = 0.0;
+ double k2 = 0.0;
+ double k3 = 0.0;
+ double k4 = 0.0;
+ double p0 = 0.0;
+ int busNum = 0;
+
+ double qValue = 0.0;
// Stability
bool plotIndMachine = false;
@@ -119,6 +130,8 @@ class IndMotor : public Machines
virtual IndMotorElectricalData GetElectricalData() { return m_electricalData; }
virtual IndMotorElectricalData GetPUElectricalData(double systemPowerBase);
virtual void SetElectricalData(IndMotorElectricalData electricalData) { m_electricalData = electricalData; }
+ virtual void InitPowerFlowMotor(double systemPowerBase, int busNumber);
+ virtual bool CalculateReactivePower(double voltage);
virtual bool GetPlotData(ElementPlotData& plotData, PlotStudy study = STABILITY);
diff --git a/Project/IndMotorForm.cpp b/Project/IndMotorForm.cpp
index 6df1684..8517aef 100644
--- a/Project/IndMotorForm.cpp
+++ b/Project/IndMotorForm.cpp
@@ -78,7 +78,8 @@ IndMotorForm::IndMotorForm(wxWindow* parent, IndMotor* indMotor) : IndMotorFormB
default:
break;
}
-
+
+ m_checkBoxComputeQ->SetValue(data.calcQInPowerFlow);
m_checkBoxUseMachinePower->SetValue(data.useMachinePowerAsBase);
// Stability
@@ -99,6 +100,8 @@ IndMotorForm::IndMotorForm(wxWindow* parent, IndMotor* indMotor) : IndMotorFormB
m_parent = parent;
m_indMotor = indMotor;
+
+ UpdateFields();
}
IndMotorForm::~IndMotorForm() {}
@@ -172,7 +175,8 @@ bool IndMotorForm::ValidateData()
data.reactivePowerUnit = UNIT_MVAr;
} break;
}
-
+
+ data.calcQInPowerFlow = m_checkBoxComputeQ->GetValue();
data.useMachinePowerAsBase = m_checkBoxUseMachinePower->GetValue();
// Stability
@@ -223,7 +227,12 @@ bool IndMotorForm::ValidateData()
m_indMotor->SetElectricalData(data);
return true;
}
-void IndMotorForm::OnCheckboxUseCageFactorClick(wxCommandEvent& event)
+void IndMotorForm::OnCheckboxUseCageFactorClick(wxCommandEvent& event) { UpdateFields(); }
+void IndMotorForm::OnCalcQInPFClick(wxCommandEvent& event) { UpdateFields(); }
+
+void IndMotorForm::UpdateFields()
{
m_textCtrlKf->Enable(m_checkBoxUseKf->GetValue());
+ m_textCtrlReactivePower->Enable(!m_checkBoxComputeQ->GetValue());
+ m_choiceReactivePower->Enable(!m_checkBoxComputeQ->GetValue());
}
diff --git a/Project/IndMotorForm.h b/Project/IndMotorForm.h
index 5a476a6..e24efea 100644
--- a/Project/IndMotorForm.h
+++ b/Project/IndMotorForm.h
@@ -36,10 +36,13 @@ class IndMotorForm : public IndMotorFormBase
virtual bool ValidateData();
protected:
+ virtual void OnCalcQInPFClick(wxCommandEvent& event);
virtual void OnCheckboxUseCageFactorClick(wxCommandEvent& event);
virtual void OnCancelButtonClick(wxCommandEvent& event) { EndModal(wxID_CANCEL); };
virtual void OnOKButtonClick(wxCommandEvent& event);
virtual void OnStabilityButtonClick(wxCommandEvent& event);
+
+ void UpdateFields();
wxWindow* m_parent = NULL;
IndMotor* m_indMotor = NULL;
diff --git a/Project/PowerFlow.cpp b/Project/PowerFlow.cpp
index 1b2ae13..161a991 100644
--- a/Project/PowerFlow.cpp
+++ b/Project/PowerFlow.cpp
@@ -155,8 +155,19 @@ bool PowerFlow::InitPowerFlow(std::vector<BusType>& busType,
if(indMotor->IsOnline()) {
if(bus == indMotor->GetParentList()[0]) {
IndMotorElectricalData childData = indMotor->GetPUElectricalData(systemPowerBase);
- power[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower);
- loadPower[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower);
+ double reactivePower = childData.reactivePower;
+
+ if(childData.calcQInPowerFlow) {
+ indMotor->InitPowerFlowMotor(systemPowerBase, data.number);
+ if(!indMotor->CalculateReactivePower(std::abs(voltage[childData.busNum]))) {
+ m_errorMsg = _("It was not possible to solve the induction motors.");
+ return false;
+ }
+ reactivePower = indMotor->GetElectricalData().qValue;
+ }
+
+ power[busNumber] += std::complex<double>(-childData.activePower, -reactivePower);
+ loadPower[busNumber] += std::complex<double>(-childData.activePower, -reactivePower);
}
}
}
@@ -221,6 +232,12 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase,
return false;
}
+ // Calculate induction motor reactive power
+ if(!CalculateMotorsReactivePower(voltage, power)) {
+ m_errorMsg = _("It was not possible to solve the induction motors.");
+ return false;
+ }
+
// Update the old voltage array to current iteration values.
for(int i = 0; i < m_numberOfBuses; i++) oldVoltage[i] = voltage[i];
@@ -232,6 +249,7 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase,
iteration++;
}
+ m_iterations = iteration;
// Adjust the power array.
for(int i = 0; i < m_numberOfBuses; i++) {
@@ -245,7 +263,11 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase,
return true;
}
-bool PowerFlow::RunNewtonRaphson(double systemPowerBase, int maxIteration, double error, double initAngle)
+bool PowerFlow::RunNewtonRaphson(double systemPowerBase,
+ int maxIteration,
+ double error,
+ double initAngle,
+ double inertia)
{
std::vector<BusType> busType; // Bus type
std::vector<std::complex<double> > voltage; // Voltage of buses
@@ -273,6 +295,12 @@ bool PowerFlow::RunNewtonRaphson(double systemPowerBase, int maxIteration, doubl
return false;
}
+ // Calculate induction motor reactive power
+ if(!CalculateMotorsReactivePower(voltage, power)) {
+ m_errorMsg = _("It was not possible to solve the induction motors.");
+ return false;
+ }
+
// Calculate dPdQ array
// Fill it with zeros
@@ -321,10 +349,11 @@ bool PowerFlow::RunNewtonRaphson(double systemPowerBase, int maxIteration, doubl
}
}
- NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ);
+ NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ, inertia);
iteration++;
}
+ m_iterations = iteration;
// Adjust the power array.
for(int i = 0; i < m_numberOfBuses; i++) {
@@ -343,7 +372,8 @@ bool PowerFlow::RunGaussNewton(double systemPowerBase,
double error,
double initAngle,
double accFactor,
- double gaussTol)
+ double gaussTol,
+ double inertia)
{
std::vector<BusType> busType; // Bus type
std::vector<std::complex<double> > voltage; // Voltage of buses
@@ -368,6 +398,12 @@ bool PowerFlow::RunGaussNewton(double systemPowerBase,
return false;
}
+ // Calculate induction motor reactive power
+ if(!CalculateMotorsReactivePower(voltage, power)) {
+ m_errorMsg = _("It was not possible to solve the induction motors.");
+ return false;
+ }
+
// Update the old voltage array to current iteration values.
for(int i = 0; i < m_numberOfBuses; i++) oldVoltage[i] = voltage[i];
@@ -394,6 +430,12 @@ bool PowerFlow::RunGaussNewton(double systemPowerBase,
return false;
}
+ // Calculate induction motor reactive power
+ if(!CalculateMotorsReactivePower(voltage, power)) {
+ m_errorMsg = _("It was not possible to solve the induction motors.");
+ return false;
+ }
+
// Calculate dPdQ array
// Fill it with zeros
@@ -442,10 +484,11 @@ bool PowerFlow::RunGaussNewton(double systemPowerBase,
}
}
- NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ);
+ NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ, inertia);
iteration++;
}
+ m_iterations = iteration;
// Adjust the power array.
for(int i = 0; i < m_numberOfBuses; i++) {
@@ -537,11 +580,15 @@ void PowerFlow::NewtonRaphson(std::vector<BusType> busType,
std::vector<std::complex<double> > power,
int numPV,
int numPQ,
- std::vector<double> dPdQ)
+ std::vector<double> dPdQ,
+ double inertia)
{
// Jacobian matrix
std::vector<std::vector<double> > jacobMatrix = CalculateJacobianMatrix(voltage, busType, numPV, numPQ);
+ // Apply inertia
+ for(unsigned int i = 0; i < dPdQ.size(); ++i) { dPdQ[i] = inertia * dPdQ[i]; }
+
// Calculate DeltaTheta DeltaV array
std::vector<double> dTdV = GaussianElimination(jacobMatrix, dPdQ);
@@ -556,7 +603,7 @@ void PowerFlow::NewtonRaphson(std::vector<BusType> busType,
voltage[i] = std::complex<double>(newV * std::cos(newT), newV * std::sin(newT));
indexDT++;
} else {
- double newV = std::abs(voltage[i]) + dTdV[indexDV];
+ double newV = std::abs(voltage[i]) * (1.0 + dTdV[indexDV]);
double newT = std::arg(voltage[i]) + dTdV[indexDT];
voltage[i] = std::complex<double>(newV * std::cos(newT), newV * std::sin(newT));
indexDV++;
@@ -577,10 +624,10 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
for(int i = 0; i < (2 * numPQ + numPV); i++) jacobMatrix[i].resize(2 * numPQ + numPV);
// Calculate the submatrices
- //{ H
- std::vector<std::vector<double> > sMatrixH;
- sMatrixH.resize(numPQ + numPV); // submatrix H size
- for(int i = 0; i < (numPQ + numPV); i++) sMatrixH[i].resize(numPQ + numPV);
+ //{ J11
+ std::vector<std::vector<double> > j11;
+ j11.resize(numPQ + numPV); // submatrix j11 size
+ for(int i = 0; i < (numPQ + numPV); i++) j11[i].resize(numPQ + numPV);
int busNumI = 0;
int busNumJ = 0;
@@ -593,16 +640,14 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
double ti = std::arg(voltage[i]);
double vj = std::abs(voltage[j]);
double tj = std::arg(voltage[j]);
- sMatrixH[busNumI][busNumJ] =
- vi * vj *
- (m_yBus[i][j].real() * std::sin(ti - tj) - m_yBus[i][j].imag() * std::cos(ti - tj));
- } else // busNumI == busNumJ
- {
+ double yij = std::abs(m_yBus[i][j]);
+ double tij = std::arg(m_yBus[i][j]);
+ j11[busNumI][busNumJ] = -vi * vj * yij * std::sin(tij + tj - ti);
+ } else { // busNumI == busNumJ
std::complex<double> sj = std::complex<double>(0.0, 0.0);
for(int k = 0; k < m_numberOfBuses; k++)
sj += voltage[j] * std::conj(m_yBus[j][k]) * std::conj(voltage[k]);
- sMatrixH[busNumI][busNumJ] =
- -sj.imag() - m_yBus[j][j].imag() * std::pow(std::abs(voltage[j]), 2.0);
+ j11[busNumI][busNumJ] = -sj.imag() - m_yBus[j][j].imag() * std::pow(std::abs(voltage[j]), 2.0);
}
busNumJ++;
}
@@ -612,10 +657,10 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
}
}
//}
- //{ N
- std::vector<std::vector<double> > sMatrixN;
- sMatrixN.resize(numPQ + numPV); // submatrix N size
- for(int i = 0; i < (numPQ + numPV); i++) sMatrixN[i].resize(numPQ);
+ //{ J12
+ std::vector<std::vector<double> > j12;
+ j12.resize(numPQ + numPV); // submatrix j12 size
+ for(int i = 0; i < (numPQ + numPV); i++) j12[i].resize(numPQ);
busNumI = 0;
busNumJ = 0;
@@ -629,16 +674,15 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
double ti = std::arg(voltage[i]);
double vj = std::abs(voltage[j]);
double tj = std::arg(voltage[j]);
- sMatrixN[busNumI][busNumJ] =
- vi * vj *
- (m_yBus[i][j].real() * std::cos(ti - tj) + m_yBus[i][j].imag() * std::sin(ti - tj));
- } else // busNumI == busNumJ
- {
+ double yij = std::abs(m_yBus[i][j]);
+ double tij = std::arg(m_yBus[i][j]);
+
+ j12[busNumI][busNumJ] = vj * vi * yij * std::cos(tij + tj - ti);
+ } else { // busNumI == busNumJ
std::complex<double> sj = std::complex<double>(0.0, 0.0);
for(int k = 0; k < m_numberOfBuses; k++)
sj += voltage[j] * std::conj(m_yBus[j][k]) * std::conj(voltage[k]);
- sMatrixN[busNumI][busNumJ] =
- sj.real() + m_yBus[j][j].real() * std::pow(std::abs(voltage[j]), 2.0);
+ j12[busNumI][busNumJ] = sj.real() + m_yBus[j][j].real() * std::pow(std::abs(voltage[j]), 2.0);
}
busNumJ++;
}
@@ -648,10 +692,10 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
}
}
//}
- //{ J
- std::vector<std::vector<double> > sMatrixJ;
- sMatrixJ.resize(numPQ); // submatrix J size
- for(int i = 0; i < (numPQ); i++) sMatrixJ[i].resize(numPQ + numPV);
+ //{ J21
+ std::vector<std::vector<double> > j21;
+ j21.resize(numPQ); // submatrix j21 size
+ for(int i = 0; i < (numPQ); i++) j21[i].resize(numPQ + numPV);
busNumI = 0;
busNumJ = 0;
@@ -665,16 +709,15 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
double ti = std::arg(voltage[i]);
double vj = std::abs(voltage[j]);
double tj = std::arg(voltage[j]);
- sMatrixJ[busNumI][busNumJ] =
- -vi * vj *
- (m_yBus[i][j].real() * std::cos(ti - tj) + m_yBus[i][j].imag() * std::sin(ti - tj));
- } else // busNumI == busNumJ
- {
+ double yij = std::abs(m_yBus[i][j]);
+ double tij = std::arg(m_yBus[i][j]);
+
+ j21[busNumI][busNumJ] = -vi * vj * yij * std::cos(tij + tj - ti);
+ } else { // busNumI == busNumJ
std::complex<double> sj = std::complex<double>(0.0, 0.0);
for(int k = 0; k < m_numberOfBuses; k++)
sj += voltage[j] * std::conj(m_yBus[j][k]) * std::conj(voltage[k]);
- sMatrixJ[busNumI][busNumJ] =
- sj.real() - m_yBus[j][j].real() * std::pow(std::abs(voltage[j]), 2.0);
+ j21[busNumI][busNumJ] = sj.real() - m_yBus[j][j].real() * std::pow(std::abs(voltage[j]), 2.0);
}
busNumJ++;
}
@@ -684,34 +727,31 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
}
}
//}
- //{ L
- std::vector<std::vector<double> > sMatrixL;
- sMatrixL.resize(numPQ); // submatrix L size
- for(int i = 0; i < (numPQ); i++) sMatrixL[i].resize(numPQ);
+ //{ J22
+ std::vector<std::vector<double> > j22;
+ j22.resize(numPQ); // submatrix j22 size
+ for(int i = 0; i < (numPQ); i++) j22[i].resize(numPQ);
busNumI = 0;
busNumJ = 0;
for(int i = 0; i < m_numberOfBuses; i++) {
- if(busType[i] == BUS_PQ) // nćo deve ser referźncia e nćo deve ser PV, ou seja é PQ
- {
+ if(busType[i] == BUS_PQ) {
for(int j = 0; j < m_numberOfBuses; j++) {
- if(busType[j] == BUS_PQ) // nćo deve ser referźncia e nćo deve ser PV, ou seja é PQ
- {
+ if(busType[j] == BUS_PQ) {
if(busNumI != busNumJ) {
double vi = std::abs(voltage[i]);
double ti = std::arg(voltage[i]);
double vj = std::abs(voltage[j]);
double tj = std::arg(voltage[j]);
- sMatrixL[busNumI][busNumJ] =
- vi * vj *
- (m_yBus[i][j].real() * std::sin(ti - tj) - m_yBus[i][j].imag() * std::cos(ti - tj));
- } else // busNumI == busNumJ
- {
+ double yij = std::abs(m_yBus[i][j]);
+ double tij = std::arg(m_yBus[i][j]);
+
+ j22[busNumI][busNumJ] = -vj * vi * yij * std::sin(tij + tj - ti);
+ } else { // busNumI == busNumJ
std::complex<double> sj = std::complex<double>(0.0, 0.0);
for(int k = 0; k < m_numberOfBuses; k++)
sj += voltage[j] * std::conj(m_yBus[j][k]) * std::conj(voltage[k]);
- sMatrixL[busNumI][busNumJ] =
- -sj.imag() - m_yBus[j][j].imag() * std::pow(std::abs(voltage[j]), 2.0);
+ j22[busNumI][busNumJ] = sj.imag() - m_yBus[j][j].imag() * std::pow(std::abs(voltage[j]), 2.0);
}
busNumJ++;
}
@@ -727,15 +767,14 @@ std::vector<std::vector<double> > PowerFlow::CalculateJacobianMatrix(std::vector
for(int j = 0; j < (2 * numPQ + numPV); j++) {
if(i < (numPQ + numPV)) {
if(j < (numPQ + numPV))
- jacobMatrix[i][j] = sMatrixH[i][j];
+ jacobMatrix[i][j] = j11[i][j];
else // j >= numPQ + numPV
- jacobMatrix[i][j] = sMatrixN[i][j - (numPQ + numPV)];
- } else // i >= numPQ + numPV
- {
+ jacobMatrix[i][j] = j12[i][j - (numPQ + numPV)];
+ } else { // i >= numPQ + numPV
if(j < (numPQ + numPV))
- jacobMatrix[i][j] = sMatrixJ[i - (numPQ + numPV)][j];
+ jacobMatrix[i][j] = j21[i - (numPQ + numPV)][j];
else // j >= numPQ + numPV
- jacobMatrix[i][j] = sMatrixL[i - (numPQ + numPV)][j - (numPQ + numPV)];
+ jacobMatrix[i][j] = j22[i - (numPQ + numPV)][j - (numPQ + numPV)];
}
}
}
@@ -770,3 +809,19 @@ bool PowerFlow::CheckReactiveLimits(std::vector<BusType>& busType,
}
return limitReach;
}
+
+bool PowerFlow::CalculateMotorsReactivePower(std::vector<std::complex<double> > voltage,
+ std::vector<std::complex<double> >& power)
+{
+ for(unsigned int i = 0; i < m_indMotorList.size(); ++i) {
+ IndMotor* motor = m_indMotorList[i];
+ auto data = motor->GetElectricalData();
+ if(motor->IsOnline() && data.calcQInPowerFlow) {
+ double oldQ = data.qValue;
+ if(!motor->CalculateReactivePower(std::abs(voltage[data.busNum]))) return false;
+ double dQ = oldQ - motor->GetElectricalData().qValue;
+ power[data.busNum] += std::complex<double>(0.0, dQ);
+ }
+ }
+ return true;
+}
diff --git a/Project/PowerFlow.h b/Project/PowerFlow.h
index 2f3419a..e8945c8 100644
--- a/Project/PowerFlow.h
+++ b/Project/PowerFlow.h
@@ -51,15 +51,18 @@ class PowerFlow : public ElectricCalculation
virtual bool RunNewtonRaphson(double systemPowerBase = 100e6,
int maxIteration = 5000,
double error = 1e-6,
- double initAngle = 0.0);
+ double initAngle = 0.0,
+ double inertia = 1.0);
virtual bool RunGaussNewton(double systemPowerBase = 100e6,
int maxIteration = 5000,
double error = 1e-6,
double initAngle = 0.0,
double accFactor = 1.0,
- double gaussTol = 10);
+ double gaussTol = 1e-2,
+ double inertia = 1.0);
virtual wxString GetErrorMessage() { return m_errorMsg; }
+ virtual int GetIterations() { return m_iterations; }
protected:
void GetNumPVPQ(std::vector<BusType> busType, int &numPQ, int &numPV);
@@ -82,11 +85,15 @@ class PowerFlow : public ElectricCalculation
std::vector<std::complex<double> > power,
int numPV,
int numPQ,
- std::vector<double> dPdQ);
+ std::vector<double> dPdQ,
+ double inertia);
+ bool CalculateMotorsReactivePower(std::vector<std::complex<double> > voltage,
+ std::vector<std::complex<double> > &power);
std::vector<std::vector<std::complex<double> > > m_yBus;
wxString m_errorMsg = "";
int m_numberOfBuses = 0;
+ int m_iterations = 0;
};
#endif // POWERFLOW_H
diff --git a/Project/PropertiesData.h b/Project/PropertiesData.h
index e6c156a..588cc00 100644
--- a/Project/PropertiesData.h
+++ b/Project/PropertiesData.h
@@ -39,6 +39,7 @@ struct SimulationData {
double powerFlowTolerance = 1e-7;
int powerFlowMaxIterations = 5000;
double initAngle = 0.0;
+ double newtonInertia = 1.0;
double gaussTolerance = 1e-2;
// Stability
diff --git a/Project/PropertiesForm.wxcp b/Project/PropertiesForm.wxcp
index e579bf3..63265ec 100644
--- a/Project/PropertiesForm.wxcp
+++ b/Project/PropertiesForm.wxcp
@@ -1,7 +1,7 @@
{
"metadata": {
"m_generatedFilesDir": ".",
- "m_objCounter": 970,
+ "m_objCounter": 976,
"m_includeFiles": [],
"m_bitmapFunction": "wxCDAD0InitBitmapResources",
"m_bitmapsFile": "PropertiesFormBitmaps.cpp",
@@ -3292,6 +3292,196 @@
}, {
"type": "string",
"m_label": "Name:",
+ "m_value": "boxSizerLvl4_22"
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "choice",
+ "m_label": "Orientation:",
+ "m_selection": 0,
+ "m_options": ["wxVERTICAL", "wxHORIZONTAL"]
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4405,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxLEFT", "wxRIGHT", "wxTOP", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_staticTextPFNewtonInertia"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Label:",
+ "m_value": "Newton inertia"
+ }, {
+ "type": "string",
+ "m_label": "Wrap:",
+ "m_value": "-1"
+ }],
+ "m_events": [],
+ "m_children": []
+ }, {
+ "m_type": 4406,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxLEFT", "wxRIGHT", "wxBOTTOM", "wxEXPAND", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "20,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_textCtrlPFNewtonInertia"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Value:",
+ "m_value": "1,0"
+ }, {
+ "type": "string",
+ "m_label": "Text Hint",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Max Length:",
+ "m_value": "0"
+ }, {
+ "type": "bool",
+ "m_label": "Auto Complete Directories:",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Auto Complete Files:",
+ "m_value": false
+ }],
+ "m_events": [],
+ "m_children": []
+ }]
+ }, {
+ "m_type": 4401,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxEXPAND"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
"m_value": "boxSizerLvl4_21"
}, {
"type": "string",
diff --git a/Project/PropertiesFormBase.cpp b/Project/PropertiesFormBase.cpp
index c2fb1ad..f3cddf0 100644
--- a/Project/PropertiesFormBase.cpp
+++ b/Project/PropertiesFormBase.cpp
@@ -356,6 +356,26 @@ SimulationsSettingsFormBase::SimulationsSettingsFormBase(wxWindow* parent,
boxSizerLvl5_17->Add(m_staticTextDeg_1, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, WXC_FROM_DIP(5));
+ wxBoxSizer* boxSizerLvl4_22 = new wxBoxSizer(wxVERTICAL);
+
+ gridSizerLvl_3_4->Add(boxSizerLvl4_22, 0, wxEXPAND, WXC_FROM_DIP(5));
+
+ m_staticTextPFNewtonInertia = new wxStaticText(m_panelPF, wxID_ANY, _("Newton inertia"), wxDefaultPosition,
+ wxDLG_UNIT(m_panelPF, wxSize(-1, -1)), 0);
+
+ boxSizerLvl4_22->Add(m_staticTextPFNewtonInertia, 0, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL,
+ WXC_FROM_DIP(5));
+
+ m_textCtrlPFNewtonInertia =
+ new wxTextCtrl(m_panelPF, wxID_ANY, wxT("1,0"), wxDefaultPosition, wxDLG_UNIT(m_panelPF, wxSize(-1, -1)), 0);
+#if wxVERSION_NUMBER >= 3000
+ m_textCtrlPFNewtonInertia->SetHint(wxT(""));
+#endif
+
+ boxSizerLvl4_22->Add(m_textCtrlPFNewtonInertia, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND | wxALIGN_CENTER_VERTICAL,
+ WXC_FROM_DIP(5));
+ m_textCtrlPFNewtonInertia->SetMinSize(wxSize(20, -1));
+
wxBoxSizer* boxSizerLvl4_21 = new wxBoxSizer(wxVERTICAL);
gridSizerLvl_3_4->Add(boxSizerLvl4_21, 0, wxEXPAND, WXC_FROM_DIP(5));
diff --git a/Project/PropertiesFormBase.h b/Project/PropertiesFormBase.h
index 6b9cd82..dc7439b 100644
--- a/Project/PropertiesFormBase.h
+++ b/Project/PropertiesFormBase.h
@@ -105,6 +105,8 @@ class SimulationsSettingsFormBase : public wxDialog
wxStaticText* m_staticTextPFSlackBusAngle;
wxTextCtrl* m_textCtrlPFSlackBusAngle;
wxStaticText* m_staticTextDeg_1;
+ wxStaticText* m_staticTextPFNewtonInertia;
+ wxTextCtrl* m_textCtrlPFNewtonInertia;
wxStaticText* m_staticTextPFGaussTolerance;
wxTextCtrl* m_textCtrlPFGaussTolerance;
wxPanel* m_panelStability;
@@ -182,6 +184,8 @@ class SimulationsSettingsFormBase : public wxDialog
wxStaticText* GetStaticTextPFSlackBusAngle() { return m_staticTextPFSlackBusAngle; }
wxTextCtrl* GetTextCtrlPFSlackBusAngle() { return m_textCtrlPFSlackBusAngle; }
wxStaticText* GetStaticTextDeg_1() { return m_staticTextDeg_1; }
+ wxStaticText* GetStaticTextPFNewtonInertia() { return m_staticTextPFNewtonInertia; }
+ wxTextCtrl* GetTextCtrlPFNewtonInertia() { return m_textCtrlPFNewtonInertia; }
wxStaticText* GetStaticTextPFGaussTolerance() { return m_staticTextPFGaussTolerance; }
wxTextCtrl* GetTextCtrlPFGaussTolerance() { return m_textCtrlPFGaussTolerance; }
wxPanel* GetPanelPF() { return m_panelPF; }
diff --git a/Project/SimulationsSettingsForm.cpp b/Project/SimulationsSettingsForm.cpp
index a9890a8..5b3cb1c 100644
--- a/Project/SimulationsSettingsForm.cpp
+++ b/Project/SimulationsSettingsForm.cpp
@@ -60,6 +60,7 @@ SimulationsSettingsForm::SimulationsSettingsForm(wxWindow* parent, PropertiesDat
m_textCtrlPFTolerance->SetValue(wxString::Format("%g", data.powerFlowTolerance));
m_textCtrlPFMaxIterations->SetValue(wxString::Format("%d", data.powerFlowMaxIterations));
m_textCtrlPFSlackBusAngle->SetValue(Element::StringFromDouble(data.initAngle));
+ m_textCtrlPFNewtonInertia->SetValue(Element::StringFromDouble(data.newtonInertia));
m_textCtrlPFGaussTolerance->SetValue(wxString::Format("%g", data.gaussTolerance));
m_textCtrlTimeStep->SetValue(wxString::Format("%g", data.timeStep));
m_textCtrlSimTime->SetValue(Element::StringFromDouble(data.stabilitySimulationTime));
@@ -136,6 +137,9 @@ bool SimulationsSettingsForm::ValidateData()
if(!Element::DoubleFromString(this, m_textCtrlPFSlackBusAngle->GetValue(), data.initAngle,
_("Value entered incorrectly in the field \"Slack bus angle\".")))
return false;
+ if(!Element::DoubleFromString(this, m_textCtrlPFNewtonInertia->GetValue(), data.newtonInertia,
+ _("Value entered incorrectly in the field \"Newton inertia (Power flow)\".")))
+ return false;
if(!Element::DoubleFromString(this, m_textCtrlPFGaussTolerance->GetValue(), data.gaussTolerance,
_("Value entered incorrectly in the field \"Gauss tolerance (Power flow)\".")))
return false;
@@ -240,4 +244,8 @@ void SimulationsSettingsForm::UpdatePFFieldStatus()
m_textCtrlPFGaussTolerance->Enable();
else
m_textCtrlPFGaussTolerance->Enable(false);
+ if(m_choicePFMethod->GetSelection() == 1 || m_choicePFMethod->GetSelection() == 2)
+ m_textCtrlPFNewtonInertia->Enable();
+ else
+ m_textCtrlPFNewtonInertia->Enable(false);
}
diff --git a/Project/Workspace.cpp b/Project/Workspace.cpp
index b057bdc..82989b5 100644
--- a/Project/Workspace.cpp
+++ b/Project/Workspace.cpp
@@ -1135,6 +1135,7 @@ bool Workspace::RunPowerFlow()
basePower *= 1e3;
PowerFlow pf(GetElementList());
bool result = false;
+ wxStopWatch sw;
switch(simProp.powerFlowMethod) {
case GAUSS_SEIDEL: {
result = pf.RunGaussSeidel(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
@@ -1142,16 +1143,21 @@ bool Workspace::RunPowerFlow()
} break;
case NEWTON_RAPHSON: {
result = pf.RunNewtonRaphson(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
- simProp.initAngle);
+ simProp.initAngle, simProp.newtonInertia);
} break;
case GAUSS_NEWTON: {
- result = pf.RunGaussNewton(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
- simProp.initAngle, simProp.accFator, simProp.gaussTolerance);
+ result =
+ pf.RunGaussNewton(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
+ simProp.initAngle, simProp.accFator, simProp.gaussTolerance, simProp.newtonInertia);
} break;
}
+ sw.Pause();
if(!result) {
wxMessageDialog msgDialog(this, pf.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
msgDialog.ShowModal();
+ } else {
+ m_statusBar->SetStatusText(
+ wxString::Format(_("Power flow converge with %d iterations (%ld ms)"), pf.GetIterations(), sw.Time()));
}
UpdateTextElements();