28 m_systemPowerBase = systemPowerBase;
29 int numberOfBuses =
static_cast<int>(
m_busList.size());
30 if (numberOfBuses == 0) {
31 m_errorMsg = _(
"There is no buses in the system.");
36 std::vector<std::complex<double> > preFaultVoltages;
37 preFaultVoltages.resize(
m_busList.size());
40 std::vector<std::vector<std::complex<double> > > yBusPos;
42 std::vector<std::vector<std::complex<double> > > yBusNeg;
44 std::vector<std::vector<std::complex<double> > > yBusZero;
52 std::complex<double> fImpedance = std::complex<double>(0.0, 0.0);
57 preFaultVoltages[data.number] = data.voltage;
59 if (data.hasFault && data.isConnected) {
60 fNumber = data.number;
61 fType = data.faultType;
62 fLocation = data.faultLocation;
63 fImpedance = std::complex<double>(data.faultResistance, data.faultReactance);
68 m_errorMsg = _(
"There is no fault in the system or the faulty bus is disconnected.");
71 else if (nBusFaulted > 1) {
72 wxMessageDialog msgDialog(
nullptr, _(
"There is more than one fault in the system, and this can lead to inconsistent results.\nDo you wish to proceed?"), _(
"Warning"), wxYES_NO | wxCENTRE | wxICON_WARNING);
73 if (msgDialog.ShowModal() == wxID_NO) {
74 m_errorMsg = _(
"Fault calculation was cancelled by the user.");
83 m_errorMsg = _(
"Fail to invert the positive sequence admittance matrix.");
87 m_errorMsg = _(
"Fail to invert the negative sequence admittance matrix.");
91 m_errorMsg = _(
"Fail to invert the zero sequence admittance matrix.");
96 std::complex<double> fCurrentPos = std::complex<double>(0.0, 0.0);
97 std::complex<double> fCurrentNeg = std::complex<double>(0.0, 0.0);
98 std::complex<double> fCurrentZero = std::complex<double>(0.0, 0.0);
100 std::complex<double> preFaultVoltage = preFaultVoltages[fNumber];
101 std::complex<double> a = std::complex<double>(-0.5, 0.866025403784);
102 std::complex<double> a2 = std::complex<double>(-0.5, -0.866025403784);
106 fCurrentPos = preFaultVoltage / (m_zBusPos[fNumber][fNumber] + fImpedance);
109 fCurrentPos = preFaultVoltage / (m_zBusPos[fNumber][fNumber] + m_zBusNeg[fNumber][fNumber] + fImpedance);
113 fCurrentNeg = -a2 * fCurrentPos;
116 fCurrentNeg = -fCurrentPos;
119 fCurrentNeg = -a * fCurrentPos;
126 std::complex<double> z1 = m_zBusPos[fNumber][fNumber];
127 std::complex<double> z2 = m_zBusNeg[fNumber][fNumber];
128 std::complex<double> z0 = m_zBusZero[fNumber][fNumber];
129 std::complex<double> zf_3 = std::complex<double>(3.0, 0.0) * fImpedance;
131 fCurrentPos = (preFaultVoltage * (z2 + z0 + zf_3)) / (z1 * z2 + z2 * z0 + z2 * zf_3 + z1 * z0 + z1 * zf_3);
135 fCurrentNeg = -a2 * ((preFaultVoltage - z1 * fCurrentPos) / z2);
136 fCurrentZero = -a * ((preFaultVoltage - z1 * fCurrentPos) / (z0 + zf_3));
139 fCurrentNeg = -((preFaultVoltage - z1 * fCurrentPos) / z2);
140 fCurrentZero = -((preFaultVoltage - z1 * fCurrentPos) / (z0 + zf_3));
143 fCurrentNeg = -a * ((preFaultVoltage - z1 * fCurrentPos) / z2);
144 fCurrentZero = -a2 * ((preFaultVoltage - z1 * fCurrentPos) / (z0 + zf_3));
152 preFaultVoltage / (m_zBusPos[fNumber][fNumber] + m_zBusNeg[fNumber][fNumber] +
153 m_zBusZero[fNumber][fNumber] + std::complex<double>(3.0, 0.0) * fImpedance);
156 fCurrentNeg = fCurrentPos;
157 fCurrentZero = fCurrentPos;
160 fCurrentNeg = a * fCurrentPos;
161 fCurrentZero = a2 * fCurrentPos;
164 fCurrentNeg = a2 * fCurrentPos;
165 fCurrentZero = a * fCurrentPos;
176 m_fCurrentA = fCurrentZero + fCurrentPos + fCurrentNeg;
177 m_fCurrentB = fCurrentZero + a2 * fCurrentPos + a * fCurrentNeg;
178 m_fCurrentC = fCurrentZero + a * fCurrentPos + a2 * fCurrentNeg;
181 m_posFaultVoltagePos.clear();
182 m_posFaultVoltageNeg.clear();
183 m_posFaultVoltageZero.clear();
184 m_posFaultVoltageA.clear();
185 m_posFaultVoltageB.clear();
186 m_posFaultVoltageC.clear();
188 int connectedBusIndex = 0;
189 for (
int i = 0; i < numberOfBuses; ++i) {
190 if (std::abs(preFaultVoltages[i]) > 1e-6) {
191 m_posFaultVoltagePos.push_back(preFaultVoltages[i] - m_zBusPos[connectedBusIndex][fNumber] * fCurrentPos);
192 m_posFaultVoltageNeg.push_back(-m_zBusNeg[connectedBusIndex][fNumber] * fCurrentNeg);
193 m_posFaultVoltageZero.push_back(-m_zBusZero[connectedBusIndex][fNumber] * fCurrentZero);
197 m_posFaultVoltagePos.push_back(std::complex<double>(0.0, 0.0));
198 m_posFaultVoltageNeg.push_back(std::complex<double>(0.0, 0.0));
199 m_posFaultVoltageZero.push_back(std::complex<double>(0.0, 0.0));
203 m_posFaultVoltageA.push_back(m_posFaultVoltageZero[i] + m_posFaultVoltagePos[i] + m_posFaultVoltageNeg[i]);
204 m_posFaultVoltageB.push_back(m_posFaultVoltageZero[i] + a2 * m_posFaultVoltagePos[i] +
205 a * m_posFaultVoltageNeg[i]);
206 m_posFaultVoltageC.push_back(m_posFaultVoltageZero[i] + a * m_posFaultVoltagePos[i] +
207 a2 * m_posFaultVoltageNeg[i]);
216 std::complex<double> a = std::complex<double>(-0.5, 0.866025403784);
217 std::complex<double> a2 = std::complex<double>(-0.5, -0.866025403784);
221 auto data = bus->GetElectricalData();
223 data.faultCurrent[0] = m_fCurrentA;
224 data.faultCurrent[1] = m_fCurrentB;
225 data.faultCurrent[2] = m_fCurrentC;
228 data.faultCurrent[0] = data.faultCurrent[1] = data.faultCurrent[2] = std::complex<double>(0.0, 0.0);
230 data.faultVoltage[0] = data.number >= 0 ? m_posFaultVoltageA[data.number] : 0.0;
231 data.faultVoltage[1] = data.number >= 0 ? m_posFaultVoltageB[data.number] : 0.0;
232 data.faultVoltage[2] = data.number >= 0 ? m_posFaultVoltageC[data.number] : 0.0;
233 bus->SetElectricalData(data);
239 int n1 =
static_cast<Bus*
>(line->
GetParentList()[0])->GetElectricalData().number;
240 int n2 =
static_cast<Bus*
>(line->
GetParentList()[1])->GetElectricalData().number;
241 auto data = line->GetElectricalData();
242 auto puData = line->GetPUElectricalData(m_systemPowerBase);
243 std::complex<double> vPos[2] = { n1 >= 0 ? m_posFaultVoltagePos[n1] : 0.0, n2 >= 0 ? m_posFaultVoltagePos[n2] : 0.0 };
244 std::complex<double> vNeg[2] = { n1 >= 0 ? m_posFaultVoltageNeg[n1] : 0.0, n2 >= 0 ? m_posFaultVoltageNeg[n2] : 0.0 };
245 std::complex<double> vZero[2] = { n1 >= 0 ? m_posFaultVoltageZero[n1] : 0.0, n2 >= 0 ? m_posFaultVoltageZero[n2] : 0.0 };
246 std::complex<double> zPos(puData.resistance, puData.indReactance);
247 std::complex<double> bPos(0.0, puData.capSusceptance / 2.0);
248 std::complex<double> zZero(puData.zeroResistance, puData.zeroIndReactance);
249 std::complex<double> bZero(0.0, puData.zeroCapSusceptance / 2.0);
251 std::complex<double> lineCurrentPos[2];
252 std::complex<double> lineCurrentNeg[2];
253 std::complex<double> lineCurrentZero[2];
255 lineCurrentPos[0] = ((vPos[0] - vPos[1]) / zPos) + (vPos[0] * bPos);
256 lineCurrentNeg[0] = ((vNeg[0] - vNeg[1]) / zPos) + (vNeg[0] * bPos);
257 lineCurrentZero[0] = ((vZero[0] - vZero[1]) / zZero) + (vZero[0] * bZero);
258 lineCurrentPos[1] = ((vPos[1] - vPos[0]) / zPos) + (vPos[1] * bPos);
259 lineCurrentNeg[1] = ((vNeg[1] - vNeg[0]) / zPos) + (vNeg[1] * bPos);
260 lineCurrentZero[1] = ((vZero[1] - vZero[0]) / zZero) + (vZero[1] * bZero);
262 data.faultCurrent[0][0] = lineCurrentZero[0] + lineCurrentPos[0] + lineCurrentNeg[0];
263 data.faultCurrent[0][1] = lineCurrentZero[0] + a2 * lineCurrentPos[0] + a * lineCurrentNeg[0];
264 data.faultCurrent[0][2] = lineCurrentZero[0] + a * lineCurrentPos[0] + a2 * lineCurrentNeg[0];
265 data.faultCurrent[1][0] = lineCurrentZero[1] + lineCurrentPos[1] + lineCurrentNeg[1];
266 data.faultCurrent[1][1] = lineCurrentZero[1] + a2 * lineCurrentPos[1] + a * lineCurrentNeg[1];
267 data.faultCurrent[1][2] = lineCurrentZero[1] + a * lineCurrentPos[1] + a2 * lineCurrentNeg[1];
269 line->SetElectricalData(data);
276 int n1 =
static_cast<Bus*
>(transformer->
GetParentList()[0])->GetElectricalData().number;
277 int n2 =
static_cast<Bus*
>(transformer->
GetParentList()[1])->GetElectricalData().number;
278 auto data = transformer->GetElectricalData();
279 auto puData = transformer->GetPUElectricalData(m_systemPowerBase);
281 std::complex<double> vPos[2] = { n1 >= 0 ? m_posFaultVoltagePos[n1] : 0.0, n2 >= 0 ? m_posFaultVoltagePos[n2] : 0.0 };
282 std::complex<double> vNeg[2] = { n1 >= 0 ? m_posFaultVoltageNeg[n1] : 0.0, n2 >= 0 ? m_posFaultVoltageNeg[n2] : 0.0 };
283 std::complex<double> vZero[2] = { n1 >= 0 ? m_posFaultVoltageZero[n1] : 0.0, n2 >= 0 ? m_posFaultVoltageZero[n2] : 0.0 };
284 std::complex<double> zPos(puData.resistance, puData.indReactance);
285 std::complex<double> zZero(puData.zeroResistance, puData.zeroIndReactance);
287 std::complex<double> transformerCurrentPos[2];
288 std::complex<double> transformerCurrentNeg[2];
289 std::complex<double> transformerCurrentZero[2];
291 if (data.turnsRatio == 1.0 && data.phaseShift == 0.0) {
292 transformerCurrentPos[0] = (vPos[0] - vPos[1]) / zPos;
293 transformerCurrentNeg[0] = (vNeg[0] - vNeg[1]) / zPos;
294 transformerCurrentZero[0] = (vZero[0] - vZero[1]) / zZero;
295 transformerCurrentPos[1] = (vPos[1] - vPos[0]) / zPos;
296 transformerCurrentNeg[1] = (vNeg[1] - vNeg[0]) / zPos;
297 transformerCurrentZero[1] = (vZero[1] - vZero[0]) / zZero;
300 double radPhaseShift = wxDegToRad(data.phaseShift);
301 std::complex<double> t = std::complex<double>(data.turnsRatio * std::cos(radPhaseShift),
302 -data.turnsRatio * std::sin(radPhaseShift));
304 transformerCurrentPos[0] =
305 vPos[0] * (1.0 / (std::pow(std::abs(t), 2.0) * zPos)) - vPos[1] * (1.0 / (std::conj(t) * zPos));
306 transformerCurrentNeg[0] =
307 vNeg[0] * (1.0 / (std::pow(std::abs(t), 2.0) * zPos)) - vNeg[1] * (1.0 / (t * zPos));
309 transformerCurrentPos[1] = -vPos[0] * (1.0 / (t * zPos)) + vPos[1] / zPos;
310 transformerCurrentNeg[1] = -vNeg[0] * (1.0 / (std::conj(t) * zPos)) + vNeg[1] / zPos;
313 switch (data.connection) {
315 transformerCurrentZero[0] = (vZero[0] - vZero[1]) / zZero;
316 transformerCurrentZero[1] = (vZero[1] - vZero[0]) / zZero;
320 transformerCurrentZero[0] = vZero[0] / zZero;
321 transformerCurrentZero[1] = std::complex<double>(0.0, 0.0);
325 transformerCurrentZero[0] = std::complex<double>(0.0, 0.0);
326 transformerCurrentZero[1] = vZero[1] / zZero;
330 transformerCurrentZero[0] = std::complex<double>(0.0, 0.0);
331 transformerCurrentZero[1] = std::complex<double>(0.0, 0.0);
336 data.faultCurrent[0][0] = transformerCurrentZero[0] + transformerCurrentPos[0] + transformerCurrentNeg[0];
337 data.faultCurrent[0][1] =
338 transformerCurrentZero[0] + a2 * transformerCurrentPos[0] + a * transformerCurrentNeg[0];
339 data.faultCurrent[0][2] =
340 transformerCurrentZero[0] + a * transformerCurrentPos[0] + a2 * transformerCurrentNeg[0];
341 data.faultCurrent[1][0] = transformerCurrentZero[1] + transformerCurrentPos[1] + transformerCurrentNeg[1];
342 data.faultCurrent[1][1] =
343 transformerCurrentZero[1] + a2 * transformerCurrentPos[1] + a * transformerCurrentNeg[1];
344 data.faultCurrent[1][2] =
345 transformerCurrentZero[1] + a * transformerCurrentPos[1] + a2 * transformerCurrentNeg[1];
347 transformer->SetElectricaData(data);
355 int n = bus->GetElectricalData().number;
356 std::complex<double> v = bus->GetElectricalData().voltage;
357 auto data = syncGenerator->GetElectricalData();
358 auto puData = syncGenerator->GetPUElectricalData(m_systemPowerBase);
360 std::complex<double> vPos = n >= 0 ? m_posFaultVoltagePos[n] : 0.0;
361 std::complex<double> vNeg = n >= 0 ? m_posFaultVoltageNeg[n] : 0.0;
362 std::complex<double> vZero = n >= 0 ? m_posFaultVoltageZero[n] : 0.0;
364 std::complex<double> zPos(puData.positiveResistance, puData.positiveReactance);
365 std::complex<double> zNeg(puData.negativeResistance, puData.negativeReactance);
366 std::complex<double> zZero(puData.zeroResistance + 3.0 * puData.groundResistance,
367 puData.zeroReactance + 3.0 * puData.groundReactance);
370 std::complex<double> i = std::complex<double>(puData.activePower, -puData.reactivePower) / std::conj(v);
371 std::complex<double> e = v + zPos * i;
373 std::complex<double> syncGeneratorCurrentPos = n >= 0 ? (e - vPos) / zPos : 0.0;
374 std::complex<double> syncGeneratorCurrentNeg = n >= 0 ? (-vNeg) / zNeg : 0.0;
375 std::complex<double> syncGeneratorCurrentZero(0.0, 0.0);
376 if (data.groundNeutral) syncGeneratorCurrentZero = n >= 0 ? (-vZero) / zZero : 0.0;
378 data.faultCurrent[0] = syncGeneratorCurrentZero + syncGeneratorCurrentPos + syncGeneratorCurrentNeg;
379 data.faultCurrent[1] =
380 syncGeneratorCurrentZero + a2 * syncGeneratorCurrentPos + a * syncGeneratorCurrentNeg;
381 data.faultCurrent[2] =
382 syncGeneratorCurrentZero + a * syncGeneratorCurrentPos + a2 * syncGeneratorCurrentNeg;
384 syncGenerator->SetElectricalData(data);
392 int n = bus->GetElectricalData().number;
393 std::complex<double> v = bus->GetElectricalData().voltage;
394 auto data = syncMotor->GetElectricalData();
395 auto puData = syncMotor->GetPUElectricalData(m_systemPowerBase);
397 std::complex<double> vPos = n >= 0 ? m_posFaultVoltagePos[n] : 0.0;
398 std::complex<double> vNeg = n >= 0 ? m_posFaultVoltageNeg[n] : 0.0;
399 std::complex<double> vZero = n >= 0 ? m_posFaultVoltageZero[n] : 0.0;
401 std::complex<double> zPos(puData.positiveResistance, puData.positiveReactance);
402 std::complex<double> zNeg(puData.negativeResistance, puData.negativeReactance);
403 std::complex<double> zZero(puData.zeroResistance + 3.0 * puData.groundResistance,
404 puData.zeroReactance + 3.0 * puData.groundReactance);
406 std::complex<double> syncMotorCurrentPos = n >= 0 ? (v - vPos) / zPos : 0.0;
407 std::complex<double> syncMotorCurrentNeg = n >= 0 ? (-vNeg) / zNeg : 0.0;
408 std::complex<double> syncMotorCurrentZero(0.0, 0.0);
409 if (data.groundNeutral) syncMotorCurrentZero = n >= 0 ? (-vZero) / zZero : 0.0;
411 data.faultCurrent[0] = syncMotorCurrentZero + syncMotorCurrentPos + syncMotorCurrentNeg;
412 data.faultCurrent[1] =
413 syncMotorCurrentZero + a2 * syncMotorCurrentPos + a * syncMotorCurrentNeg;
414 data.faultCurrent[2] =
415 syncMotorCurrentZero + a * syncMotorCurrentPos + a2 * syncMotorCurrentNeg;
417 syncMotor->SetElectricalData(data);