template<class PreconditionerA, class PreconditionerS1, class PreconditionerS2>
class BlockLowerTriangularPreconditioner : public Subscriptor
{
public:
BlockLowerTriangularPreconditioner( const PreconditionerA &M11,
const PreconditionerS1 &M22,
const PreconditionerS2 &M33,
const LA::MPI::BlockSparseMatrix &L,
const std::vector<IndexSet> &owned_dofs)
: M1(M11), M2(M22), M3(M33), L(&L),
owned_dofs(owned_dofs),
R21(owned_dofs[1], MPI_COMM_WORLD),
R32(owned_dofs[2], MPI_COMM_WORLD) {}
void vmult( LA::MPI::BlockVector &dst,
const LA::MPI::BlockVector &src ) const;
private:
const PreconditionerA &M1;
const PreconditionerS1 &M2;
const PreconditionerS2 &M3;
const SmartPointer<const LA::MPI::BlockSparseMatrix> L;
const std::vector<IndexSet> &owned_dofs;
mutable LA::MPI::Vector R21, R32;
};
template<class PreconditionerA, class PreconditionerS1, class PreconditionerS2>
void BlockLowerTriangularPreconditioner<PreconditionerA, PreconditionerS1, PreconditionerS2>::vmult(
LA::MPI::BlockVector &dst,
const LA::MPI::BlockVector &src) const
{
M1.vmult(dst.block(0), src.block(0));
L->block(1,0).vmult(R21, dst.block(0));
R21 *= -1.0;
R21 += src.block(1);
M2.vmult(dst.block(1), R21);
// M2.vmult(dst.block(1), src.block(1));
// L.block(2,0).vmult(R31, dst.block(0));
L->block(2,1).vmult(R32, dst.block(1));
R32 *= -1.0;
R32 += src.block(2);
M3.vmult(dst.block(2), R32);
// M3.vmult(dst.block(2), src.block(2));
}