|
1 | 1 | #include <iomanip> |
2 | 2 | #include <iostream> |
3 | 3 |
|
| 4 | +#include <LinearAlgebra/SparsityPattern/Variable.hpp> |
4 | 5 | #include <Model/PhasorDynamics/Branch/Branch.hpp> |
5 | 6 | #include <Model/PhasorDynamics/Bus/Bus.hpp> |
6 | 7 | #include <Model/PhasorDynamics/Bus/BusInfinite.hpp> |
@@ -77,6 +78,46 @@ namespace GridKit |
77 | 78 | return success.report(__func__); |
78 | 79 | } |
79 | 80 |
|
| 81 | + TestOutcome jacobian() |
| 82 | + { |
| 83 | + TestStatus success = true; |
| 84 | + |
| 85 | + real_type R{2.0}; ///< Branch series resistance |
| 86 | + real_type X{4.0}; ///< Branch series reactance |
| 87 | + real_type G{0.2}; ///< Branch shunt conductance |
| 88 | + real_type B{1.2}; ///< Branch shunt charging |
| 89 | + |
| 90 | + Sparse::Variable Vr1{10.0}; ///< Bus-1 real voltage |
| 91 | + Sparse::Variable Vi1{20.0}; ///< Bus-1 imaginary voltage |
| 92 | + Sparse::Variable Vr2{30.0}; ///< Bus-2 real voltage |
| 93 | + Sparse::Variable Vi2{40.0}; ///< Bus-2 imaginary voltage |
| 94 | + |
| 95 | + Vr1.setVariableNumber(0); ///< Independent variables: first |
| 96 | + Vi1.setVariableNumber(1); ///< Independent variables: second |
| 97 | + Vr2.setVariableNumber(2); ///< Independent variables: third |
| 98 | + Vi2.setVariableNumber(3); ///< Independent variables: fourth |
| 99 | + |
| 100 | + PhasorDynamics::BusInfinite<Sparse::Variable, IdxT> bus1(Vr1, Vi1); |
| 101 | + PhasorDynamics::BusInfinite<Sparse::Variable, IdxT> bus2(Vr2, Vi2); |
| 102 | + |
| 103 | + PhasorDynamics::Branch<Sparse::Variable, IdxT> branch(&bus1, &bus2, R, X, G, B); |
| 104 | + branch.evaluateResidual(); ///< Computes the residual and the Jacobian values by tracking |
| 105 | + ///< the dependencies |
| 106 | + |
| 107 | + std::vector<Sparse::Variable> residuals{bus1.Ir(), bus1.Ii(), bus2.Ir(), bus2.Ii()}; |
| 108 | + std::vector<Sparse::Variable::DependencyMap> ref = analyticalJacobian(R, X, G, B); |
| 109 | + |
| 110 | + /// Compare dependencies computed automatically to the ones computed analytically |
| 111 | + for (size_t i = 0; i < residuals.size(); ++i) |
| 112 | + { |
| 113 | + Sparse::Variable res = residuals[i]; |
| 114 | + const Sparse::Variable::DependencyMap& dependencies = res.getDependencies(); |
| 115 | + success *= (GridKit::Testing::isEqual(dependencies, ref[i])); |
| 116 | + } |
| 117 | + |
| 118 | + return success.report(__func__); |
| 119 | + } |
| 120 | + |
80 | 121 | TestOutcome accessors() |
81 | 122 | { |
82 | 123 | TestStatus success = true; |
@@ -139,6 +180,44 @@ namespace GridKit |
139 | 180 |
|
140 | 181 | return success.report(__func__); |
141 | 182 | } |
| 183 | + |
| 184 | + private: |
| 185 | + std::vector<Sparse::Variable::DependencyMap> analyticalJacobian(const real_type R, |
| 186 | + const real_type X, |
| 187 | + const real_type G, |
| 188 | + const real_type B) |
| 189 | + { |
| 190 | + const real_type b = -X / (R * R + X * X); |
| 191 | + const real_type g = R / (R * R + X * X); |
| 192 | + |
| 193 | + real_type dIr1_dVr1 = -(g + 0.5 * G); |
| 194 | + real_type dIr1_dVi1 = (b + 0.5 * B); |
| 195 | + real_type dIr1_dVr2 = g; |
| 196 | + real_type dIr1_dVi2 = -b; |
| 197 | + |
| 198 | + real_type dIi1_dVr1 = -(b + 0.5 * B); |
| 199 | + real_type dIi1_dVi1 = -(g + 0.5 * G); |
| 200 | + real_type dIi1_dVr2 = b; |
| 201 | + real_type dIi1_dVi2 = g; |
| 202 | + |
| 203 | + real_type dIr2_dVr1 = g; |
| 204 | + real_type dIr2_dVi1 = -b; |
| 205 | + real_type dIr2_dVr2 = -(g + 0.5 * G); |
| 206 | + real_type dIr2_dVi2 = (b + 0.5 * B); |
| 207 | + |
| 208 | + real_type dIi2_dVr1 = b; |
| 209 | + real_type dIi2_dVi1 = g; |
| 210 | + real_type dIi2_dVr2 = -(b + 0.5 * B); |
| 211 | + real_type dIi2_dVi2 = -(g + 0.5 * G); |
| 212 | + |
| 213 | + std::vector<Sparse::Variable::DependencyMap> dependencies(4); |
| 214 | + dependencies[0] = {{0, dIr1_dVr1}, {1, dIr1_dVi1}, {2, dIr1_dVr2}, {3, dIr1_dVi2}}; |
| 215 | + dependencies[1] = {{0, dIi1_dVr1}, {1, dIi1_dVi1}, {2, dIi1_dVr2}, {3, dIi1_dVi2}}; |
| 216 | + dependencies[2] = {{0, dIr2_dVr1}, {1, dIr2_dVi1}, {2, dIr2_dVr2}, {3, dIr2_dVi2}}; |
| 217 | + dependencies[3] = {{0, dIi2_dVr1}, {1, dIi2_dVi1}, {2, dIi2_dVr2}, {3, dIi2_dVi2}}; |
| 218 | + |
| 219 | + return dependencies; |
| 220 | + } |
142 | 221 | }; // class BranchTest |
143 | 222 |
|
144 | 223 | } // namespace Testing |
|
0 commit comments