diff options
-rw-r--r-- | Project/Electromechanical.cpp | 108 | ||||
-rw-r--r-- | Project/IndMotor.cpp | 5 | ||||
-rw-r--r-- | Project/IndMotor.h | 2 |
3 files changed, 81 insertions, 34 deletions
diff --git a/Project/Electromechanical.cpp b/Project/Electromechanical.cpp index 1a8a0d0..64fdb9a 100644 --- a/Project/Electromechanical.cpp +++ b/Project/Electromechanical.cpp @@ -224,6 +224,32 @@ void Electromechanical::SetEvent(double currentTime) } } + // Induction motor switching + for(auto it = m_indMotorList.begin(), itEnd = m_indMotorList.end(); it != itEnd; ++it) { + IndMotor* motor = *it; + auto swData = motor->GetSwitchingData(); + for(unsigned int i = 0; i < swData.swType.size(); ++i) { + if(EventTrigger(swData.swTime[i], currentTime)) { + // Remove machine (only connected machines) + if(swData.swType[i] == SW_REMOVE && motor->IsOnline() && motor->GetParentList().size() == 1) { + auto data = motor->GetElectricalData(); + motor->SetOnline(false); + int n = static_cast<Bus*>(motor->GetParentList()[0])->GetElectricalData().number; + m_yBus[n][n] -= (std::complex<double>(1, 0) / std::complex<double>(data.r1t, data.xt)); + } + + // Insert machine (only disconnected machines) + if(swData.swType[i] == SW_INSERT && !motor->IsOnline() && motor->GetParentList().size() == 1) { + auto data = motor->GetElectricalData(); + if(motor->SetOnline(true)) { + int n = static_cast<Bus*>(motor->GetParentList()[0])->GetElectricalData().number; + m_yBus[n][n] += (std::complex<double>(1, 0) / std::complex<double>(data.r1t, data.xt)); + } + } + } + } + } + // Load switching for(auto it = m_loadList.begin(), itEnd = m_loadList.end(); it != itEnd; ++it) { Load* load = *it; @@ -231,7 +257,7 @@ void Electromechanical::SetEvent(double currentTime) for(unsigned int i = 0; i < swData.swType.size(); ++i) { if(EventTrigger(swData.swTime[i], currentTime)) { // Remove load (only connected loads) - if(swData.swType[i] == SW_REMOVE && load->IsOnline()) { + if(swData.swType[i] == SW_REMOVE && load->IsOnline() && load->GetParentList().size() == 1) { load->SetOnline(false); auto data = load->GetPUElectricalData(m_powerSystemBase); Bus* parentBus = static_cast<Bus*>(load->GetParentList()[0]); @@ -731,25 +757,36 @@ bool Electromechanical::InitializeDynamicElements() auto data = indMotor->GetElectricalData(); double w0 = 2.0 * M_PI * m_systemFreq; - std::complex<double> i1 = std::complex<double>(dataPU.activePower, -data.q0) / std::conj(data.terminalVoltage); - data.ir = std::real(i1); - data.im = std::imag(i1); + double ir = std::real(i1); + double im = std::imag(i1); std::complex<double> e = data.terminalVoltage - std::complex<double>(data.r1t, data.x1t) * i1; - data.te = std::real(e * std::conj(i1)) / w0; + double te = std::real(e * std::conj(i1)) / w0; double wi = w0 * (1 - data.s0); // Initial velocity - data.as = data.te * (data.aw + (data.bw * w0) / wi + (data.cw * w0 * w0) / (wi * wi)); - data.bs = data.te * ((data.bw * w0) / wi + (2.0 * data.cw * w0 * w0) / (wi * wi)); - data.cs = (data.te * data.cw * w0 * w0) / (wi * wi); + data.as = te * (data.aw + (data.bw * w0) / wi + (data.cw * w0 * w0) / (wi * wi)); + data.bs = te * ((data.bw * w0) / wi + (2.0 * data.cw * w0 * w0) / (wi * wi)); + data.cs = (te * data.cw * w0 * w0) / (wi * wi); - std::complex<double> tranE = - (std::complex<double>(0, data.x0 - data.xt) * i1) / std::complex<double>(1.0, w0 * data.s0 * data.t0); - - data.tranEr = std::real(tranE); - data.tranEm = std::imag(tranE); - - data.slip = data.s0; + if(indMotor->IsOnline()) { + std::complex<double> tranE = + (std::complex<double>(0, data.x0 - data.xt) * i1) / std::complex<double>(1.0, w0 * data.s0 * data.t0); + + data.tranEr = std::real(tranE); + data.tranEm = std::imag(tranE); + + data.slip = data.s0; + data.ir = ir; + data.im = im; + data.te = te; + } else { // Offline + data.tranEr = 0.0; + data.tranEm = 0.0; + data.slip = 1.0 - 1e-7; + data.ir = 0.0; + data.im = 0.0; + data.te = 0.0; + } // Reset plot data data.slipVector.clear(); @@ -757,7 +794,11 @@ bool Electromechanical::InitializeDynamicElements() data.electricalTorqueVector.clear(); data.electricalTorqueVector.shrink_to_fit(); data.mechanicalTorqueVector.clear(); - data.mechanicalTorqueVector.shrink_to_fit(); + data.mechanicalTorqueVector.shrink_to_fit(); + data.velocityVector.clear(); + data.velocityVector.shrink_to_fit(); + data.currentVector.clear(); + data.currentVector.shrink_to_fit(); indMotor->SetElectricalData(data); } @@ -860,15 +901,8 @@ bool Electromechanical::CalculateInjectedCurrents() std::complex<double> iMachine = y0 * (v - e); - // wxMessageBox(wxString::Format("%f\n%f", data.ir, data.im)); - data.ir = std::real(iMachine); data.im = std::imag(iMachine); - // double y = (1.0 / (data.r1t * data.r1t + data.xt * data.xt)); - // data.ir = y * (data.r1t * data.tranEr + data.xt * data.tranEm); - // data.im = y * (-data.xt * data.tranEr + data.r1t * data.tranEm); - - // wxMessageBox(wxString::Format("%f\n%f", data.ir, data.im)); } else { data.ir = 0.0; data.im = 0.0; @@ -1002,7 +1036,7 @@ void Electromechanical::CalculateIntegrationConstants(IndMotor* indMotor, double // Mechanical equations // s - data.icSlip.m = m_timeStep / (4.0f * data.inertia / k + data.bs * m_timeStep); + data.icSlip.m = m_timeStep / ((4.0f * data.inertia / w0) / k + data.bs * m_timeStep); data.icSlip.c = data.slip * (1.0 - 2.0 * data.bs * data.icSlip.m) + data.icSlip.m * (2.0 * data.as + data.cs * data.slip * data.slip - data.te); @@ -1080,9 +1114,9 @@ bool Electromechanical::SolveMachines() if(!CalculateNonIntVariables(indMotor, ir, im, te, k)) return false; // Extrapolate nonintegrable variables. - // ir = 2.0 * ir - data.oldIr; - // im = 2.0 * im - data.oldIm; - // te = 2.0 * te - data.oldTe; + ir = 2.0 * ir - data.oldIr; + im = 2.0 * im - data.oldIm; + te = 2.0 * te - data.oldTe; CalculateIntVariables(indMotor, ir, im, te, k); } else { @@ -1230,11 +1264,13 @@ void Electromechanical::SaveData() auto data = motor->GetElectricalData(); if(data.plotIndMachine) { data.slipVector.emplace_back(data.slip * 100.0); - double te = std::real(std::complex<double>(data.tranEr, data.tranEm) * std::complex<double>(data.ir, -data.im)); - data.electricalTorqueVector.emplace_back(te); - //data.electricalTorqueVector.emplace_back(data.te * 2.0 * M_PI * m_systemFreq); + data.electricalTorqueVector.emplace_back(data.te * 2.0 * M_PI * m_systemFreq); double tm = (data.as - data.bs * data.slip + data.cs * data.slip * data.slip) * 2.0 * M_PI * m_systemFreq; data.mechanicalTorqueVector.emplace_back(tm); + double w = (1.0 - data.slip) * 2.0 * M_PI * m_systemFreq; + data.velocityVector.emplace_back(w); + double i1 = std::sqrt(data.ir * data.ir + data.im * data.im); + data.currentVector.emplace_back(i1); motor->SetElectricalData(data); } } @@ -1449,7 +1485,7 @@ double Electromechanical::CalculateIntVariables(IndMotor* indMotor, double ir, d // Mechanical differential equations // Using Newton method to solve the non-linear slip equation: s = Cs + Ms * (C * s^2 - Te): - double slip = data.slip; // Initial value + double slip = data.slip; // Initial value. CAN BE THE PROBLEM ON MOTOR START! double ds = (data.icSlip.c + data.icSlip.m * (data.cs * slip * slip - te) - slip) / (1.0 - 2.0 * data.icSlip.m * data.cs * slip * slip); int iteration = 0; @@ -1460,7 +1496,8 @@ double Electromechanical::CalculateIntVariables(IndMotor* indMotor, double ir, d iteration++; if(iteration > m_maxIterations) break; } - + + if(!indMotor->IsOnline()) slip = 1.0 - 1e-7; error = std::max(error, std::abs(data.slip - slip)); data.slip = slip; @@ -1696,9 +1733,10 @@ std::complex<double> Electromechanical::GetIndMachineAdmittance(IndMotor* motor) { auto data = motor->GetElectricalData(); auto dataPU = motor->GetPUElectricalData(m_powerSystemBase); + std::complex<double> v = static_cast<Bus*>(motor->GetParentList()[0])->GetElectricalData().voltage; std::complex<double> y0 = (std::complex<double>(1, 0) / std::complex<double>(data.r1t, data.xt)); // The difference between calculated and defined reactive power - std::complex<double> yq = std::complex<double>(0.0, data.q0 - dataPU.reactivePower); + std::complex<double> yq = std::complex<double>(0.0, data.q0 - dataPU.reactivePower) / (std::abs(v) * std::abs(v)); return y0 + yq; } @@ -1706,8 +1744,8 @@ bool Electromechanical::InsertIndMachinesOnYBus() { for(auto it = m_indMotorList.begin(), itEnd = m_indMotorList.end(); it != itEnd; ++it) { IndMotor* motor = *it; + if(!CalculateIndMachinesTransientValues(motor)) return false; if(motor->IsOnline()) { - if(!CalculateIndMachinesTransientValues(motor)) return false; int n = static_cast<Bus*>(motor->GetParentList()[0])->GetElectricalData().number; m_yBus[n][n] += GetIndMachineAdmittance(motor); } @@ -1749,6 +1787,8 @@ bool Electromechanical::CalculateIndMachinesTransientValues(IndMotor* motor) //[Ref.] Induction Motor Static Models for Power Flow and Voltage Stability Studies double p = dataPU.activePower; double v = std::abs(data.terminalVoltage); + // If the motor is offline, calculate the nominal slip to user-defined power input and 1.0 p.u. voltage + if(!motor->IsOnline()) v = 1.0; double r1 = data.r1t; double r2 = data.r2t; double x1 = data.x1t; diff --git a/Project/IndMotor.cpp b/Project/IndMotor.cpp index 93dc38c..8d84608 100644 --- a/Project/IndMotor.cpp +++ b/Project/IndMotor.cpp @@ -229,6 +229,9 @@ bool IndMotor::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Elemen m_electricalData.aw = XMLParser::GetNodeValueDouble(loadChar, "Constant"); m_electricalData.bw = XMLParser::GetNodeValueDouble(loadChar, "Linear"); m_electricalData.cw = XMLParser::GetNodeValueDouble(loadChar, "Quadratic"); + + if(!OpenSwitchingData(electricalProp)) return false; + if(m_swData.swTime.size() != 0) SetDynamicEvent(true); m_inserted = true; @@ -244,5 +247,7 @@ bool IndMotor::GetPlotData(ElementPlotData& plotData, PlotStudy study) plotData.AddData(m_electricalData.slipVector, _("Slip")); plotData.AddData(m_electricalData.electricalTorqueVector, _("Electrical torque")); plotData.AddData(m_electricalData.mechanicalTorqueVector, _("Mechanical torque")); + plotData.AddData(m_electricalData.velocityVector, _("Velocity")); + plotData.AddData(m_electricalData.currentVector, _("Current")); return true; } diff --git a/Project/IndMotor.h b/Project/IndMotor.h index 98e3414..4137e6f 100644 --- a/Project/IndMotor.h +++ b/Project/IndMotor.h @@ -86,6 +86,8 @@ struct IndMotorElectricalData { double te; std::vector<double> electricalTorqueVector; std::vector<double> mechanicalTorqueVector; + std::vector<double> velocityVector; + std::vector<double> currentVector; std::complex<double> electricalPower; std::vector<std::complex<double> > electricalPowerVector; }; |