Point to Point Case
This page presents a simple point-to-point AC/DC case. This example serves as a starting point to learn the workflow of building, solving, and analyzing OPF and HPS problems within HARMONY before moving to more complex multi-terminal or large-scale systems.
Main Procedure
Define Components
We take adding generators and converters, as the example. First, we need to declare the components, includes name, grid areas, and fundamental parameters. See Figure 1.
Then, we need to make connection to the bus. Here as we can see, For the generator, it has one terminal, which is connected to AC bus1. For the converter, it has two terminals, which are connected to AC bus2 and DC bus1. See Figure 2.
Lastly, we need to supplement some information, that are especially for OPF computation. See Figure 3.
Make a AC/DC Network
We need to make a AC/DC network through connecting each components. See Figure 4, Figure 5, and Figure 6.
Access OPF and HPS results
The results will be printed and you can observe OPF results, and the HPS results with the updated operating points from the OPF. See Figure 7.
Code Explanation
Code Script
#include "Examples.h"
#include "../network.h"
#include "../Bus.h"
#include "../Include_components.h"
#include "../Solver/OPF/powerflow.h"
#include "../Solver/Stability_Estimate/Stability_estimate.h"
void example_point2point_case() {
///* ---------- 0 Set Network Object ---------- */
Network net;
///* ---------- 1.1 Create AC Buses ---------- */
Bus* bus1_ac = new Bus("ACBUS01", "AC1", 3);
Bus* bus2_ac = new Bus("ACBUS02", "AC1", 3);
Bus* bus3_ac = new Bus("ACBUS03", "AC2", 3);
Bus* bus4_ac = new Bus("ACBUS04", "AC2", 3); //
///* ---------- 1.2 Add AC Loads ---------- */
// using RLC model
std::vector<double> load_params2 = { 2.28e3, 1.457, 0 };
Load* load2 = new Load("LOAD02", "AC2", 3, load_params2);
// using PQ load model
// LoadPQ* load2 = new LoadPQ("LOAD02", "AC2", 3, { 50e6, 5e6 });
net.connectElementToBus(load2, 1, bus4_ac);
///* ---------- 1.3 Add AC Generators ---------- */
/// Generator 1
double Zsrc = 5;
AC_source* src1 = new AC_source("SRC01", "AC1", 3, 345e3, Zsrc);
net.connectElementToBus(src1, 1, bus1_ac);
map<string, double> src_info1 = {
{"Pmax", 250.0}, // Maximum active power output (MW)
{"Pmin", 10.0}, // Minimum active power output (MW)
{"Qmax", 10.0}, // Maximum reactive power output (MVar)
{"Qmin", -10.0}, // Minimum reactive power output (MVar)
{"c2", 0.11}, // Quadratic coefficient of the generation cost function (c2*P^2 + c1*P + c0)
{"c1", 5.0}, // Linear coefficient of the generation cost function
{"c0", 150}, // Constant term of the generation cost function (fixed operation cost)
{"Ref", 1}, // Reference bus flag (1 = set as slack/reference bus)
{"Vg", 345 * 1.06} // Generator terminal voltage reference
};
src1->setOPFInfo(src_info1);
///* ---------- 1.4 Add Branches ---------- */
double ACR1 = 5; double ACX1 = 140;
std::complex<double> ACZ1(ACR1, ACX1);
Impedance* br1_ac = new Impedance("br1_ac", "AC1", 3, ACZ1);
net.connectElementToBus(br1_ac, /*terminal=*/1, bus1_ac);
net.connectElementToBus(br1_ac, /*terminal=*/2, bus2_ac);
double ACR2 = 5; double ACX2 = 140;
std::complex<double> ACZ2(ACR2, ACX2);
Impedance* br2_ac = new Impedance("br2_ac", "AC2", 3, ACZ2);
net.connectElementToBus(br2_ac, /*terminal=*/1, bus3_ac);
net.connectElementToBus(br2_ac, /*terminal=*/2, bus4_ac);
///* ---------- 2.1 Create DC Buses ---------- */
Bus* bus1_dc = new Bus("DCBUS01", "DC1", 1);
Bus* bus2_dc = new Bus("DCBUS02", "DC1", 1);
///* ---------- 2.2 Create DC Buses ---------- */
double DCR1 = 20;
Impedance* br1_dc = new Impedance("br1_dc", "DC1", 1, DCR1);
net.connectElementToBus(br1_dc, /*terminal=*/1, bus1_dc);
net.connectElementToBus(br1_dc, /*terminal=*/2, bus2_dc);
///* ---------- 2.3 Create Converters ---------- */
vector<double> converter_params1 = {
2 * M_PI * 50, // Omega (Nominal Frequency in rad/s)
50.0 * 1e6, // Active Power (P) in W
0 * 1e6, // Reactive Power (Q) in VA
0.0, // Theta (Voltage Angle in rad)
345.0 * 1e3, // AC Voltage (V_m) in V
50 * 1e6, // DC power (P_dc) in W
440.0 * 1e3, // DC Voltage (V_dc) in kV
0.05, // Arm Inductance (L_arm) in H
1.07, // Arm Resistance (R_arm) in Ω
0.01, // Capacitance per Submodule (C_arm) in F
400, // Number of Submodules (N)
0.0005, // Reactor Inductance (L_reactor) in H
0.0001, // Reactor Resistance (R_reactor) in Ω
0.0 // Time Delay (t_delay) in seconds
};
std::vector<double> controller_params1 = {
1, 0, 0.001103374, 0.00073, 1, 0, // PLL controller parameters
0, // DC voltage controller parameters
1, 0, 6.6667e-07, 3.3333e-04, 1, 50e6, // active power
0, // AC voltage
1, 0, 6.6667e-07, 3.3333e-04, 1, 0, // reactive power
1, 0, 120, 400, 1, 0, // energy controller parameters
1, 0, 19.93, 4500, 1, 166.67, // zcc controller parameters
1, 0, 117.93, 8.5e4, 2, 666.67, 0, // occ controller parameters
1, 0, 19.93, 4500, 2, 0, 0, // ccc controller parameters
0 // droop control
};
MMC* mmc1 = new MMC("MMC1", "AC1_DC1", converter_params1, controller_params1);
net.connectElementToBus(mmc1, 1, bus2_ac);
net.connectElementToBus(mmc1, 2, bus1_dc);
vector<double> converter_params2 = {
2 * M_PI * 50, // Omega (Nominal Frequency in rad/s)
-50.0 * 1e6, // Active Power (P) in W
-20e6, // Reactive Power (Q) in VA
0.0, // Theta (Voltage Angle in rad)
345.0 * 1e3, // AC Voltage (V_m) in V
-50 * 1e6, // DC power (P_dc) in W
440.0 * 1e3, // DC Voltage (V_dc) in kV
0.05, // Arm Inductance (L_arm) in H
1.07, // Arm Resistance (R_arm) in Ω
0.01, // Capacitance per Submodule (C_arm) in F
400, // Number of Submodules (N)
0.0005, // Reactor Inductance (L_reactor) in H
0.0001, // Reactor Resistance (R_reactor) in Ω
0.0 // Time Delay (t_delay) in seconds
};
std::vector<double> controller_params2 = {
1, 0, 0.001103374, 0.00073, 1, 0, // PLL controller parameters
1, 0, 2, 82, 2, 0, 440e3, // DC voltage controller parameters
0, // active power
0, // AC voltage
1, 0, 6.6667e-07, 3.3333e-04, 1, -20e6, // reactive power
1, 0, 120, 400, 1, 0, // energy controller parameters
1, 0, 19.93, 4500, 1, -41.66, // zcc controller parameters
1, 0, 117.93, 8.5e4, 2, -89.71, 0, // occ controller parameters
1, 0, 19.93, 4500, 2, 0, 0, // ccc controller parameters
0 // droop control
};
MMC* mmc2 = new MMC("MMC2", "AC2_DC1", converter_params2, controller_params2);
net.connectElementToBus(mmc2, 1, bus3_ac);
net.connectElementToBus(mmc2, 2, bus2_dc);
///*----- 3 OPF Implementatiopn ----- */
PowerFlow pf;
//const auto& data = net.getNetData();
std::map<std::string, double> global_params;
double omega = 2 * M_PI * 50;
global_params["omega"] = omega;
global_params["baseMVA"] = 100;
global_params["ACbaseKV"] = 345.0; // Base voltage in kV, can be adjusted as needed
global_params["DCbaseKV"] = 400.0; // Base voltage for DC, can be adjusted as needed
global_params["Z_base"] = global_params["ACbaseKV"] * global_params["ACbaseKV"] / global_params["baseMVA"]; // Base impedance, can be adjusted as needed
pf.make_OPF(&net, global_params, false, false, false, true);
}Execution Results
Optimization succeeded. Solution found!
=================================================================================================
| AC Grid Bus Data |
=================================================================================================
Area Bus Voltage Generation Load RES
# # Mag [pu]/Ang [deg] Pg [MW] Qg [MVAr] P [MW] Q [MVAr] Pres [MW] Qres[MVAr]
----- ----- ------------------ -------- --------- ------- ------- --------- -----------
1 1 1.060 / 0.00* - - 0.00 0.00 - -
1 2 1.059 / 3.17 - - 0.00 0.00 - -
1 3 1.060 / -0.11 52.87 4.47 0.00 0.00 - -
2 1 1.100 / 0.00 - - 0.00 0.00 - -
2 2 1.086 / 2.81 - - 50.18 10.07 - -
----- ----- ------------------ -------- --------- ------- ------- --------- -----------
The total generation cost is $721.77/MWh (€668.31/MWh)
===========================================================================================
| AC Grids Branch Data |
===========================================================================================
Area Branch From To From Branch Flow To Branch Flow Branch Loss
# # Bus# Bus# Pij [MW] Qij [MVAr] Pij [MW] Qij [MVAr] Pij_loss [MW]
---- ------ ----- ----- --------- ---------- ---------- ---------- -------------
1 1 2 1 -52.762 2.878 52.867 0.052 0.105
1 2 1 3 -52.867 -0.052 52.867 4.474 0.000
2 1 1 2 50.275 12.688 -50.181 -10.074 0.093
---- ------ ----- ----- --------- ----------- -------- ---------- -------------
The total AC network losses is 0.198 MW.
================================================================================
| MTDC Bus Data |
==================================================================================
Bus Bus AC DC Voltage DC Power PCC Bus Injection Converter loss
DC # AC # Area Vdc [pu] Pdc [MW] Ps [MW] Qs [MVAr] Conv_Ploss [MW]
----- ---- ---- --------- -------- ------- -------- ------------
1 1 2 1.272 -51.431 -50.275 -12.688 1.157
2 2 1 1.275 51.568 52.762 -2.878 1.194
----- ---- ---- --------- -------- ------- -------- --------
The total converter losses is 2.351 MW
===================================================================
| MTDC Branch Data |
=====================================================================
Branch From To From Branch To Branch Branch Loss
# Bus# Bus# Flow Pij [MW] Flow Pij [MW] Pij_loss [MW]
------ ----- ----- --------- --------- ---------
1 1 2 -51.431 51.568 0.137
------ ----- ----- --------- --------- ---------
The total DC network losses is 0.137 MW.
Execution time is 0.166 s
=== Updating 2 MMC elements with OPF results ===
Converged (small step) in 990 iterations.
[Updated MMC] MMC2 | Vm=379.494 kV, theta=0.000 deg, Pac=-50.275 MW, Qac=-12.688 MVar, Vdc=438.827 kV, Pdc=-51.431 MW
Equilibrium state:
-90.379 22.289 -39.067 0.000 0.000 -719.733 1427.202 0.237 1.017 303.461 -1246.133 438824.453
Converged (small step) in 217753 iterations.
[Updated MMC] MMC1 | Vm=365.519 kV, theta=3.174 deg, Pac=52.762 MW, Qac=-2.878 MVar, Vdc=439.999 kV, Pdc=51.568 MW
Equilibrium state:
96.232 5.249 39.985 -0.000 -0.000 -177.615 -1168.105 -0.337 -0.269 65.655 1273.031 439997.138