@@ -60,6 +60,8 @@ topology alone, at the cost of potential [ill-conditioned pivot elements](#pivot
60
60
61
61
### Power system equation properties
62
62
63
+ #### Matrix properties of power system equations
64
+
63
65
[ Power flow equations] ( ../../user_manual/calculations.md#power-flow-algorithms ) are not Hermitian
64
66
and also not positive (semi-)definite. As a result, methods that depend on these properties cannot
65
67
be used.
@@ -69,6 +71,12 @@ intrinsically positive definite and Hermitian, but for
69
71
[ performance reasons] ( #performance-considerations ) , the matrix equation is augmented to achieve
70
72
a consistent structure across the entire topology using Lagrange multipliers.
71
73
74
+ #### Element size properties of power system equations
75
+
76
+ Power system equations may contain elements of several orders of magnitude. This may lead to
77
+ instabilities when solving the (matrix) equations due to non-linearly propagating (rounding) errors.
78
+ Stability checks that limit those rounding errors need to function under these extreme conditions.
79
+
72
80
### Block-sparsity considerations
73
81
74
82
The power flow and state estimation equations involve block-sparse matrices: dense blocks, with a
@@ -92,16 +100,61 @@ The choice for a custom LU solver implementation comes from a number of consider
92
100
93
101
The LU solver implemented in the power grid model consists of 3 components:
94
102
95
- * A sparse LU solver that:
103
+ * A block- sparse LU solver that:
96
104
* handles factorization using the topological structure up to block-level
97
105
* solves the sparse matrix equation given the factorization
98
106
* A dense LU factor that handles individual blocks within the matrix equation
99
107
108
+ ### Dense LU factorization
109
+
110
+ The power grid model uses a modified version of the
111
+ [ ` LUFullPiv ` defined in Eigen] ( https://gitlab.com/libeigen/eigen/-/blob/3.4/Eigen/src/LU/FullPivLU.h )
112
+ (credits go to the original author). The modification adds opt-in support for
113
+ [ pivot perturbation] ( #pivot-perturbation ) .
114
+
115
+ Let $M\equiv M\left[ 0: N , 0: N \right] $ be the $N\times N$-matrix and $M\left[ i,j\right] $ its element
116
+ at (0-based) indices $(i,j)$, where $i,j = 0..(N-1)$.
117
+
118
+ 1 . Loop over all rows: $p = 0..(N-1)$:
119
+ 1 . Set the remaining matrix: $M_p \gets M\left[ p: N ,p: N \right] $ with size $N_p\times N_p$.
120
+ 2 . Find largest element $M_p\left[ i_p,j_p\right] $ in $M_p$ by magnitude. This is the pivot
121
+ element.
122
+ 3 . If the magnitude of the pivot element is too small:
123
+ 1 . If pivot perturbation is enabled, then:
124
+ 1 . Apply [ pivot perturbation] ( #pivot-perturbation ) .
125
+ 2 . Proceed.
126
+ 2 . Else, if the matrix is singular (pivot element is identically $0$), then:
127
+ 1 . Raise a ` SparseMatrixError ` .
128
+ 3 . Else:
129
+ 1 . Proceed.
130
+ 4 . Else:
131
+ 1 . Proceed.
132
+ 5 . Swap the first and pivot row and column of $M_p$, so that the pivot element is in the
133
+ top-left corner of the remaining matrix:
134
+ 1 . $M_p\left[ 0,0: N_p \right] \leftrightarrow M\left[ i_p,0: N_p \right] $
135
+ 2 . $M_p\left[ 0: N_p ,0\right] \leftrightarrow M\left[ 0: N_p ,j_p\right] $
136
+ 6 . Apply Gaussian elimination for the current pivot element:
137
+ 1 . $M_p\left[ 0,0: N_p \right] \gets \frac{1}{M_p[ 0,0] }M_p\left[ 0,0: N_p \right] $
138
+ 2 . $M_p\left[ 1: N_p ,0: N_p \right] \gets M_p\left[ 1: N_p ,0: N_p \right] - M_p\left[ 1: N_p ,0\right] \otimes M_p\left[ 0,0: N_p \right] $
139
+ 7 . Continue with the next $p$ to factorize the the bottom-right block.
140
+
141
+ ``` {note}
142
+ In the actual implementation, we use a slightly different order of operations: instead of raising
143
+ the `SparseMatrixError` immediately, we break from the loop and throw after that. This does not
144
+ change the functional behavior.
145
+ ```
146
+
147
+ ### Block-sparse LU decomposition
148
+
149
+ TODO
150
+
100
151
### Pivot perturbation
101
152
102
153
The LU solver implemented in the power grid model has support for pivot perturbation. The methods
103
- are described in [ Li99] ( https://portal.nersc.gov/project/sparse/superlu/siam_pp99.pdf ) and
104
- [ Schenk04] ( http://ftp.gwdg.de/pub/misc/EMIS/journals/ETNA/vol.23.2006/pp158-179.dir/pp158-179.pdf ) .
154
+ are described in
155
+ [ Li99] ( https://www.semanticscholar.org/paper/A-Scalable-Sparse-Direct-Solver-Using-Static-Li-Demmel/7ea1c3360826ad3996f387eeb6d70815e1eb3761 )
156
+ and
157
+ [ Schenk06] ( https://etna.math.kent.edu/volumes/2001-2010/vol23/abstract.php?vol=23&pages=158-179 ) .
105
158
Pivot perturbation consists of selecting a pivot element. If its magnitude is too small compared
106
159
to that of the other elements in the matrix, then it cannot be used in its current form. Selecting
107
160
another pivot element is not desirable, as described in the section on
@@ -113,24 +166,86 @@ slightly different matrix that is then iteratively refined.
113
166
114
167
#### Pivot perturbation algorithm
115
168
116
- \begin{align* }
117
- A = B && C = D \\
118
- && E = F
119
- \end{align* }
120
- <!-- if (|pivot_element| < perturbation_threshold) then
121
- pivot_element = perturbation_threshold
122
- endif -->
123
-
124
- ### Dense LU factorization
125
-
126
- The power grid model uses a modified version of the
127
- [ ` LUFullPiv ` defined in Eigen] ( https://gitlab.com/libeigen/eigen/-/blob/3.4/Eigen/src/LU/FullPivLU.h )
128
- (credits go to the original author). The modification adds opt-in support for
129
- [ pivot perturbation] ( #pivot-perturbation ) .
130
-
131
- 1 . Set the remaining square matrix
132
- 2 . Find largest element in the remaining matrix by magnitude. This is the pivot element.
133
- 3 . If the magnitude of the pivot element is too small:
134
- 1 . If pivot perturbation is enabled, apply [ pivot perturbation] ( #pivot-perturbation ) .
135
- 2 . Otherwise, if the matrix is exactly singular (pivot element is identically $0$) is disabled,
136
- raise a ` SparseMatrixError ` .
169
+ The following pivot perturbation algorithm works for both real and complex matrix equations. Let $M$
170
+ be the matrix, $\left\| |A\right\| |_ {\infty ,\text{bwod}}$ the
171
+ [ block-wise off-diagonal infinite norm] ( #block-wise-off-diagonal-infinite-matrix-norm ) of the matrix.
172
+
173
+ 1 . Set $\epsilon \gets \text{perturbation_threshold} * \left\| |A\right\| |_ {\text{bwod}}$
174
+ 2 . If $|\text{pivot_element}| < \epsilon$, then:
175
+ 1 . Set $\text{phase}\left(\text{pivot_element}\right) \gets \text{pivot_element} / |\text{pivot_element}|$.
176
+ 2 . Set $\text{pivot_element} \gets \text{perturbation_threshold} * \text{phase}\left(\text{pivot_element}\right)$.
177
+
178
+ <!-- In this equation, $\left\||A\right\||$ denotes the absolute value of the maximum element, as defined in
179
+ [Arioli89](https://epubs.siam.org/doi/10.1137/0610013). -->
180
+
181
+ #### Iterative refinement
182
+
183
+ TODO
184
+
185
+ #### Differences with literature
186
+
187
+ There are several differences between our implementation and the ones described in
188
+ [ Li99] ( https://www.semanticscholar.org/paper/A-Scalable-Sparse-Direct-Solver-Using-Static-Li-Demmel/7ea1c3360826ad3996f387eeb6d70815e1eb3761 )
189
+ and
190
+ [ Schenk06] ( https://etna.math.kent.edu/volumes/2001-2010/vol23/abstract.php?vol=23&pages=158-179 ) .
191
+ They are summarized below.
192
+
193
+ ##### No check for diminishing returns
194
+
195
+ [ Li99] ( https://www.semanticscholar.org/paper/A-Scalable-Sparse-Direct-Solver-Using-Static-Li-Demmel/7ea1c3360826ad3996f387eeb6d70815e1eb3761 )
196
+ contains an early-out criterion for the iterative refinement that checks for deminishing returns in
197
+ consecutive iterations. It amounts to (in reverse order):
198
+
199
+ 1 . If $$ \text{backward_error} \gt \frac{1}{2}\text{last_backward_error} $$ , then:
200
+ 1 . Stop iterative refinement.
201
+ 2 . Else:
202
+ 1 . Go to next refinement iteration.
203
+
204
+ In power systems, however, the fact that the matrix may contain elements
205
+ [ spanning several orders of magnitude] ( #element-size-properties-of-power-system-equations ) may cause
206
+ slow convergence far away from the optimum. The diminishing return criterion would cause the
207
+ algorithm to exit before the actual solution is found. Multiple refinement iterations may still
208
+ yield better results. The power grid model therefore does not stop on deminishing returns. Instead,
209
+ a maximum amount of iterations is used in combination with the error tolerance.
210
+
211
+ ##### Block-wise off-diagonal infinite matrix norm
212
+
213
+ For the pivot perturbation algorithm, a matrix norm is used to determine the relative size of the
214
+ current pivot element compared to the rest of the matrix as a measure for the ill-conditioning. The
215
+ norm is a variant to the $L_ {\infty}$ norm of a matrix, which we call the block-wise off-diagonal
216
+ infinite matrix norm ($L_ {\infty ,\text{bwod}}$).
217
+
218
+ Since the power grid model solves the matrix equations using a multi-scale matrix solver (dense
219
+ intra-block, block-sparse for the full topological structure of the grid), the norm is also taken on
220
+ two levels.
221
+
222
+ In addition, because the diagonal blocks may have much larger elements than the off-diagonal
223
+ elements, while the relevant information is contained mostly in in the off-diagonal blocks. As a
224
+ result, the block-diagonal elements would undesirably dominate the norm. The power grid model
225
+ therefore skips the diagonal blocks when calculating the norm.
226
+
227
+ In short, the $L_ {\infty ,\text{bwod}}$ norm it is the $L_ {\infty}$ norm of the block-sparse matrix
228
+ with the $L_ {\infty}$ norm of the individual blocks as elements, where the block-diagonal elements
229
+ are skipped at the block-level. The algorithm is as follows:
230
+
231
+ Let $M\equiv M\left[ 0: N , 0: N \right] $ be the $N\times N$-matrix with a block-sparse structure and
232
+ $M\left[ i,j\right] $ its block element at (0-based) indices $(i,j)$, where $i,j = 0..(N-1)$. In turn,
233
+ let $M[ i,j] \equiv M_ {i,j}\left[ 0: N_ {i,j},0: N_ {i,j}\right] $ be the dense block with dimensions
234
+
235
+ 1 . Set $\text{norm} \gets 0$.
236
+ 2 . Loop over all block-rows: $i = 0..(N-1)$:
237
+ 1 . Set $\text{row_norm} \gets 0$.
238
+ 2 . Loop over all block-columns: $j = 0..(N-1)$ (beware of sparse structure):
239
+ 1 . If $i = j$, then:
240
+ 1 . Skip this block: continue with the next block-column.
241
+ 2 . Else, calculate the $L_ {\infty}$ norm of the current block and add to the current row norm:
242
+ 1 . Set the current block: $M_ {i,j} \gets M[ i,j] $.
243
+ 2 . Set $\text{block_norm} \gets 0$.
244
+ 3 . Loop over all rows of the current block: $k = 0..(N_ {i,j} - 1)$:
245
+ 1 . Set $\text{block_row_norm} \gets 0$.
246
+ 2 . Loop over all columns of the current block: $l = 0..(N_ {i,j} - 1)$:
247
+ 1 . Set $\text{block_row_norm} \gets \text{block_row_norm} + \left\| M_ {i,j}\left[ k,l\right] \right\| $.
248
+ 3 . Calculate the new block norm: set
249
+ $\text{block_norm} \gets \max\left\{ \text{block_norm}, \text{block_row_norm}\right\} $.
250
+ 4 . Set $\text{row_norm} \gets \text{row_norm} + \text{block_norm}$.
251
+ 3 . Calculate the new norm: set $\text{norm} \gets \max\left\{ \text{norm}, \text{row_norm}\right\} $.
0 commit comments