📄 twolevelpreconditioner.java
字号:
/* * Copyright (C) 2003-2006 Bjørn-Ove Heimsund * * This file is part of MTJ. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package no.uib.cipr.matrix.distributed;import java.util.Arrays;import no.uib.cipr.matrix.DenseLU;import no.uib.cipr.matrix.DenseMatrix;import no.uib.cipr.matrix.DenseVector;import no.uib.cipr.matrix.Matrix;import no.uib.cipr.matrix.MatrixEntry;import no.uib.cipr.matrix.Vector;import no.uib.cipr.matrix.VectorEntry;import no.uib.cipr.matrix.sparse.Preconditioner;/** * Two level preconditioner. Uses a block preconditioner as a subdomain solver, * and algebraically constructs a coarse grid correcion operator */public class TwoLevelPreconditioner extends BlockDiagonalPreconditioner { private final static int root = 0; private final DistMatrix A; private final Communicator comm; private final int rank, size; private final int[] indexToRank; private final DistVector z, r; private final DenseMatrix A0; private final DenseVector b0; private final DenseLU lu; private final double[] Ai; private final double[][] Ai0; private final boolean row; private final double[][] zi0; public TwoLevelPreconditioner(Preconditioner prec, DistRowMatrix A, DistVector z) { super(prec); this.A = A; this.z = z; this.r = z.copy(); row = true; indexToRank = createIndexToRank(A.numColumns(), A.getColumnOwnerships()); this.comm = A.getCommunicator(); rank = comm.rank(); size = comm.size(); A0 = new DenseMatrix(size, size); b0 = new DenseVector(size); lu = new DenseLU(size, size); Ai = new double[size]; if (rank == root) { Ai0 = new double[size][size]; zi0 = new double[size][1]; } else { Ai0 = null; zi0 = null; } } public TwoLevelPreconditioner(Preconditioner prec, DistColMatrix A, DistVector z) { super(prec); this.A = A; this.z = z; this.r = z.copy(); row = false; indexToRank = createIndexToRank(A.numColumns(), A.getColumnOwnerships()); this.comm = A.getCommunicator(); rank = comm.rank(); size = comm.size(); A0 = new DenseMatrix(size, size); b0 = new DenseVector(size); lu = new DenseLU(size, size); Ai = new double[size]; if (rank == root) { Ai0 = new double[size][size]; zi0 = new double[size][1]; } else { Ai0 = null; zi0 = null; } } /** * Creates a mapping from a row/column index to the associated rank * * @param size * Number of rows/columns * @param n * Row/column ownerships */ private int[] createIndexToRank(int size, int[] n) { int[] indexToRank = new int[size]; for (int i = 0; i < n.length - 1; ++i) for (int j = n[i]; j < n[i + 1]; ++j) indexToRank[j] = i; return indexToRank; } @Override public Vector apply(Vector b, Vector x) { if (!(b instanceof DistVector) || !(x instanceof DistVector)) throw new IllegalArgumentException("Vectors must be DistVectors"); boolean transpose = false; return apply(b, x, transpose); } @Override public Vector transApply(Vector b, Vector x) { if (!(b instanceof DistVector) || !(x instanceof DistVector)) throw new IllegalArgumentException("Vectors must be DistVectors"); boolean transpose = true; return apply(b, x, transpose); } private Vector apply(Vector b, Vector x, boolean transpose) { // Calculate R * (b - A*x) calculateCoarseResidual(b, x, transpose); // Calculate A0 \ R * (b - A*x) if (rank == root) solveCoarseSystem(transpose); // Update x += R^T A0 \ R * (b - A*x) updateWithCoarseCorrection(x); return applyBlockPreconditioner(b, x, transpose); } /** * Calculates the residual, and projects it onto the coarse grid */ private void calculateCoarseResidual(Vector b, Vector x, boolean transpose) { // z = b - A*x if (transpose) A.transMultAdd(-1, x, z.set(b)); else A.multAdd(-1, x, z.set(b)); // Piecewise constant projection R * (b - A*x) double zi = 0; for (VectorEntry e : z.getLocal()) zi += e.get(); // Gather the results on rank zero double[] zij = new double[] { zi }; comm.gather(zij, zi0, root); } /** * Solves the coarse system. Only the root thread should call */ private void solveCoarseSystem(boolean transpose) { for (int i = 0; i < size; ++i) b0.set(i, zi0[i][0]); if (transpose) lu.transSolve(new DenseMatrix(b0, false)); else lu.solve(new DenseMatrix(b0, false)); double[] data = b0.getData(); for (int i = 0; i < size; ++i) zi0[i][0] = data[i]; } /** * Updates the global solution with the coarse correction */ private void updateWithCoarseCorrection(Vector x) { DistVector xd = (DistVector) x; double[] zij = new double[1]; comm.scatter(zi0, zij, root); for (VectorEntry e : xd.getLocal()) e.set(e.get() + zij[0]); } /** * Applies the local block preconditioner */ private Vector applyBlockPreconditioner(Vector b, Vector x, boolean transpose) { // Recalculate residual if (transpose) A.transMultAdd(-1, x, z.set(b)); else A.multAdd(-1, x, z.set(b)); // Apply block preconditioner on the residual r.set(b); if (transpose) super.transApply(z, r); else super.apply(z, r); return x.add(r); } @Override public void setMatrix(Matrix A) { if (!(A instanceof DistMatrix)) throw new IllegalArgumentException( "A is not a DistRowMatrix or a DistColMatrix"); Matrix Ad = this.A.getBlock(); Matrix Ao = this.A.getOff(); super.setMatrix(A); Arrays.fill(Ai, 0); for (MatrixEntry e : Ad) Ai[rank] += e.get(); if (row) { for (MatrixEntry e : Ao) Ai[indexToRank[e.column()]] += e.get(); comm.gather(Ai, Ai0, root); if (rank == root) for (int i = 0; i < size; ++i) for (int j = 0; j < size; ++j) A0.set(i, j, Ai0[i][j]); } else { for (MatrixEntry e : Ao) Ai[indexToRank[e.row()]] += e.get(); comm.gather(Ai, Ai0, root); if (rank == root) for (int i = 0; i < size; ++i) for (int j = 0; j < size; ++j) A0.set(i, j, Ai0[j][i]); } if (rank == root) lu.factor(A0); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -