1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
\par
\chapter{{\tt FrontMtx}: \break Front matrix}
\par
This object computes, stores and solves linear
systems using two types of factorizations:
\begin{enumerate}
\item
$(A + \sigma B) = P(U^T + I)D(I + U)P^T$ for a symmetric matrix $A$.
If pivoting is not enabled, $D$ is a diagonal matrix.
If pivoting is enabled, $D$ has $1 \times 1$ and $2 \times 2$
blocks on its diagonal.
$U$ is strictly upper triangular, and the nonzero structures
of $U$ and $D$ are disjoint.
$P$ is a permutation matrix.
\item
$(A + \sigma B) = P(L + I)D(I + U)Q^T$ for a nonsymmetric matrix $A$
with symmetric structure.
$D$ is a diagonal matrix.
$U$ is strictly upper triangular.
$L$ is strictly lower triangular.
$P$ and $Q$ are permutation matrices.
\end{enumerate}
Pivoting for numerical stability is an optional feature,
and the storage of the factors $L$ and $U$ may be sparse,
i.e., entries of small magnitude can be dropped from the matrix.
\par
Let us take a quick look at the necessary data structures.
\begin{itemize}
\item
There is a pointer to a {\tt ETree} object that contains the front
tree that governs the factorization and solve.
Inside this object are the dimensions of each front (the number of
internal and external rows and columns), the tree connectivity of
the fronts, and a map from each vertex to the front that contains
it as an internal row and column.
\item
There is a pointer to an {\tt IVL} object that contains the
symbolic factorization.
For each front, it gives the list of internal and external rows and
columns, used to initialize a front prior to its factorization.
For a factorization without pivoting, this object stores the index
information for the factors, and so is used during the forward and
backsolves.
For a factorization with pivoting, the index information for a
front may change, so this object is not used during the solves.
\item
For a factorization with pivoting, the composition of a front
(its dimensions and the row and column indices) may change, so we
need additional data structures to store this information.
We use an {\tt IV} object to store the front size --- the number of
rows and columns that were eliminated when the front was factored.
We use an {\tt IVL} object to store the column indices --- internal
and external --- and if the matrix is nonsymmetric, another {\tt
IVL} object to store the row indices.
\item
If we have a multithreaded factorization and use pivoting or an
approximate factorization, we need exclusive access
to the {\tt IV} object that stores the final front size,
and the {\tt IVL} object(s) that store the final row and column
indices for the front.
Therefore we use a {\tt Lock} object to govern exclusive
access to these objects.
\end{itemize}
\par
The $(L+I)D(I+U)$ and $(U^T+I)D(I+U)$ factorizations are computed
using a {\it 1-dimensional} decomposition of the matrix.
Consider a matrix partitioned into eight fronts.
\begin{center}
\setlength{\unitlength}{0.04in}
\begin{picture}(80,80)
\put(-10,40){\makebox(0,0){$A = $}}
\put(0,0){\framebox(80,80){}}
% \put(0,0){\framebox(10,70){}}
% \put(10,0){\framebox(10,60){}}
% \put(20,0){\framebox(10,50){}}
% \put(30,0){\framebox(10,40){}}
% \put(40,0){\framebox(10,30){}}
% \put(50,0){\framebox(10,20){}}
% \put(60,0){\framebox(10,10){}}
\put( 0, 70){\line(1,0){80}}
\put(10, 60){\line(1,0){70}}
\put(20, 50){\line(1,0){60}}
\put(30, 40){\line(1,0){50}}
\put(40, 30){\line(1,0){40}}
\put(50, 20){\line(1,0){30}}
\put(60, 10){\line(1,0){20}}
\put(10, 80){\line(0,-1){80}}
\put(20, 70){\line(0,-1){70}}
\put(30, 60){\line(0,-1){60}}
\put(40, 50){\line(0,-1){50}}
\put(50, 40){\line(0,-1){40}}
\put(60, 30){\line(0,-1){30}}
\put(70, 20){\line(0,-1){20}}
\put( 5, 75){\makebox(0,0){$A_{0,0}$}}
\put(15, 65){\makebox(0,0){$A_{1,1}$}}
\put(25, 55){\makebox(0,0){$A_{2,2}$}}
\put(35, 45){\makebox(0,0){$A_{3,3}$}}
\put(45, 35){\makebox(0,0){$A_{4,4}$}}
\put(55, 25){\makebox(0,0){$A_{5,5}$}}
\put(65, 15){\makebox(0,0){$A_{6,6}$}}
\put(75, 5){\makebox(0,0){$A_{7,7}$}}
\put( 5, 35){\makebox(0,0){$A_{*,0}$}}
\put(15, 30){\makebox(0,0){$A_{*,1}$}}
\put(25, 25){\makebox(0,0){$A_{*,2}$}}
\put(35, 20){\makebox(0,0){$A_{*,3}$}}
\put(45, 15){\makebox(0,0){$A_{*,4}$}}
\put(55, 10){\makebox(0,0){$A_{*,5}$}}
\put(65, 5){\makebox(0,0){$A_{*,6}$}}
\put(45, 75){\makebox(0,0){$A_{0,*}$}}
\put(50, 65){\makebox(0,0){$A_{1,*}$}}
\put(55, 55){\makebox(0,0){$A_{2,*}$}}
\put(60, 45){\makebox(0,0){$A_{3,*}$}}
\put(65, 35){\makebox(0,0){$A_{4,*}$}}
\put(70, 25){\makebox(0,0){$A_{5,*}$}}
\put(75, 15){\makebox(0,0){$A_{6,*}$}}
\end{picture}
\end{center}
The $A_{i,i}$ matrices on the diagonal are square, but they need
not be the same size.
The off-diagonal matrices $A_{*,i}$ and $A_{i,*}$ use a $*$
notation for their rows and columns, respectively, where $*$ means
all indices that follow the $i$'th block.
We shall associate with each front a set of row and column indices,
so we write $A_{J,J}$ for $A_{i,i}$, where $J$ is the set of row
and column indices for front $i$.
\par
Consider the case where $A$ is structurally symmetric.
We factor $A$ into $(L + I)D(I + U)$, where $L$ is strictly lower
triangular, $D $ is diagonal, and $U$ is strictly upper triangular.
$L$, $D$ and $U$ inherit the block structure of $A$, so we have
$L_{*,J}$, $L_{J,J}$, $D_{J,J}$, $U_{J,J}$ and $U_{J,*}$ matrices.
\par
The off-diagonal matrices of $A$, $L$ and $U$ are usually very sparse.
We use special notation to define their nonzero rows and columns.
% We write $A_{\bnd{J},J}$ for $A_{*,J}$ and $A_{J,\bnd{J}}$ for
% $A_{J,*}$, and similar notation for $L$ and $U$.
The set $\bnd{J}$ is the set of indices $k$ such that
$l_{k,j} \ne 0$ or $u_{j,k} \ne 0$ for some $j \in J$.
$U_{J,*}$ and $U_{J,\bnd{J}}$ are related by some permutation matrix
$A$ where
$
U_{J,*} Q =
\left \lbrack \begin{array}{cc}
U_{J,\bnd{J}} & 0
\end{array} \right \rbrack
$.
Similar relations hold for $A_{J,*}$, $A_{*,J}$ and $L_{*,J}$.
We never operate on or store $U_{J,*}$, for this would waste
storage and operations.
Rather we store and operate on $U_{J,\bnd{J}}$ instead.
\par
By multiplying the matrices on the right of
$A = (L + I)D(I + U)$, we arrive at the three equations that define
the factorization.
\begin{eqnarray*}
A_{J,J} & = & (L_{J,J}+I) D_{J,J} (I+U_{J,J})
+ \sum_{I < J} L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J} \\
A_{J,\bnd{J}} & = & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}}
+ \sum_{I < J} L_{\bnd{I} \cap J, I}
D_{I, I} U_{I, \bnd{I} \cap \bnd{J}} \\
A_{\bnd{J},J} & = & L_{\bnd{J},J} D_{J,J} (I+U_{J,J})
+ \sum_{I < J} L_{\bnd{I} \cap \bnd{J}, I}
D_{I, I} U_{I, \bnd{I} \cap J}
\end{eqnarray*}
Since we are somewhat informal with our notation above, let us take
a moment to make it more precise.
\begin{itemize}
\item
In the summation $\sum_{I < J}$, $I$ and $J$ are index sets.
We use the convention that $I < J$ when the front that has index
set $I$ is numbered before the front that has index set $J$.
In the following we will use $I$ to refer to the front with index
set $I$, as well as the index set itself.
\item
The row index set for $L_{\bnd{I} \cap J,I}$ is the intersection of
the indices in $\bnd{I}$ with those of $J$.
The index set $\bnd{I} \cap \bnd{J}$ is similarly defined.
\item
The multiplication
$L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$
generates a matrix whose rows are
$\bnd{I} \cap J$ and whose columns are $\bnd{I} \cap J$,
and this matrix is to be added into a matrix whose rows and columns
are $J$.
If $\bnd{I} \cap J \ne J$, then this operation is not well defined.
We use the convention that the entries in
$L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$
are {\it scatter/add}'ed into their proper location.
This is a generalization of an indexed {\tt axpy} operation
applied to matrices.
\end{itemize}
Just because front $I$ precedes front $J$ does not mean the there
is any nonempty intersection between $\bnd{I}$ and $J$.
(A sparse matrix should also have a sparse block structure!)
If $\bnd{I} \cap J = \emptyset$, then
$L_{\bnd{I} \cap J,I}$ and $U_{I,\bnd{I} \cap J}$
are zero matrices.
We can rewrite the above equations to take advantage of this
ohservation.
\begin{eqnarray*}
A_{J,J} & = & (L_{J,J}+I) D_{J,J} (I+U_{J,J})
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J} \\
A_{J,\bnd{J}} & = & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}}
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}} \\
A_{\bnd{J},J} & = & L_{\bnd{J},J} D_{J,J} (I+U_{J,J})
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}
\end{eqnarray*}
These are the defining equations to compute an $A = (L+I)D(I+U)$
factorization without pivoting. We can rearrange the terms and
order the steps to give the factorization algorithm.
\begin{figure}
\caption{Serial factorization without pivoting}
\label{figure:serial-factorization}
\begin{center}
\fbox{
\begin{minipage}{4 in}
\begin{tabbing}
XXX\=XXX\=XXX\=\kill
for $I$ = 0, $\ldots$, \# of fronts \\
\> compute
$\displaystyle
T_{J,J} = A_{J,J}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$ \\
\> compute
$\displaystyle
T_{J,\bnd{J}} = A_{J,\bnd{J}}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}$ \\
\> compute
$\displaystyle
T_{\bnd{J},J} = A_{\bnd{J},J}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}$ \\
\> solve
$
\left \lbrack \begin{array}{cc}
(L_{J,J}+I) D_{J,J} (I+U_{J,J}) & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}} \\
L_{\bnd{J},J} D_{J,J} (I+U_{J,J}) & 0
\end{array} \right \rbrack
=
\left \lbrack \begin{array}{cc}
T_{J,J} & T_{J,\bnd{J}} \\
T_{\bnd{J},J} & 0 \\
\end{array} \right \rbrack
$ \\
\>\> for $D_{J,J}$, $L_{J,J}$, $L_{\bnd{J},J}$,
$U_{J,J}$ and $U_{J,\bnd{J}}$
\end{tabbing}
\end{minipage}
}
\end{center}
\end{figure}
|