Foam::autoPtr<Foam::amgPolicy> Foam::amgPolicy::New
(
    const word& policyType,
    const lduMatrix& matrix,
    const label groupSize,
    const label nCoarseCells
)
{
    matrixConstructorTable::iterator constructorIter =
        matrixConstructorTablePtr_->find(policyType);

    if (constructorIter == matrixConstructorTablePtr_->end())
    {
        FatalErrorIn
        (
            "autoPtr<amgPolicy> amgPolicy::New\n"
            "(\n"
            "    const word& policyType,\n"
            "    const lduMatrix& matrix,\n"
            "    const label groupSize\n"
            "    const label nCoarseCells\n"
            ")"
        )   << "Unknown AMG policy " << policyType
            << endl << endl
            << "Valid AMG policies are :" << endl
            << matrixConstructorTablePtr_->toc()
            << exit(FatalError);
    }

    return autoPtr<amgPolicy>
    (
        constructorIter()
        (
            matrix,
            groupSize,
            nCoarseCells
        )
    );
}
Foam::autoPtr<Foam::lduMatrix::solver> Foam::lduMatrix::solver::New
(
    const word& fieldName,
    const lduMatrix& matrix,
    const FieldField<Field, scalar>& interfaceBouCoeffs,
    const FieldField<Field, scalar>& interfaceIntCoeffs,
    const lduInterfaceFieldPtrsList& interfaces,
    const dictionary& solverControls
)
{
    const word name(solverControls.lookup("solver"));

    if (matrix.diagonal())
    {
        return autoPtr<lduMatrix::solver>
        (
            new diagonalSolver
            (
                fieldName,
                matrix,
                interfaceBouCoeffs,
                interfaceIntCoeffs,
                interfaces,
                solverControls
            )
        );
    }
    else if (matrix.symmetric())
    {
        symMatrixConstructorTable::iterator constructorIter =
            symMatrixConstructorTablePtr_->find(name);

        if (constructorIter == symMatrixConstructorTablePtr_->end())
        {
            FatalIOErrorIn
            (
                "lduMatrix::solver::New", solverControls
            )   << "Unknown symmetric matrix solver " << name << nl << nl
                << "Valid symmetric matrix solvers are :" << endl
                << symMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<lduMatrix::solver>
        (
            constructorIter()
            (
                fieldName,
                matrix,
                interfaceBouCoeffs,
                interfaceIntCoeffs,
                interfaces,
                solverControls
            )
        );
    }
    else if (matrix.asymmetric())
    {
        asymMatrixConstructorTable::iterator constructorIter =
            asymMatrixConstructorTablePtr_->find(name);

        if (constructorIter == asymMatrixConstructorTablePtr_->end())
        {
            FatalIOErrorIn
            (
                "lduMatrix::solver::New", solverControls
            )   << "Unknown asymmetric matrix solver " << name << nl << nl
                << "Valid asymmetric matrix solvers are :" << endl
                << asymMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<lduMatrix::solver>
        (
            constructorIter()
            (
                fieldName,
                matrix,
                interfaceBouCoeffs,
                interfaceIntCoeffs,
                interfaces,
                solverControls
            )
        );
    }
    else
    {
        FatalIOErrorIn
        (
            "lduMatrix::solver::New", solverControls
        )   << "cannot solve incomplete matrix, "
               "no diagonal or off-diagonal coefficient"
            << exit(FatalIOError);

        return autoPtr<lduMatrix::solver>(NULL);
    }
}
autoPtr<coupledLduSolver> coupledLduSolver::New
(
    const word& fieldName,
    const coupledLduMatrix& matrix,
    const PtrList<FieldField<Field, scalar> >& bouCoeffs,
    const PtrList<FieldField<Field, scalar> >& intCoeffs,
    const lduInterfaceFieldPtrsListList& interfaces,
    const dictionary& dict
)
{
    word solverName(dict.lookup("solver"));

    if (matrix.diagonal())
    {
        return autoPtr<coupledLduSolver>
        (
            new coupledDiagonalSolver
            (
                fieldName,
                matrix,
                bouCoeffs,
                intCoeffs,
                interfaces
            )
        );
    }
    else if (matrix.symmetric())
    {
        symMatrixConstructorTable::iterator constructorIter =
            symMatrixConstructorTablePtr_->find(solverName);

        if (constructorIter == symMatrixConstructorTablePtr_->end())
        {
            FatalIOErrorIn
            (
                "autoPtr<coupledLduSolver> coupledLduSolver::New\n"
                "(\n"
                "    const word& fieldName,\n"
                "    const coupledLduMatrix& matrix,\n"
                "    const PtrList<FieldField<Field, scalar> >& bouCoeffs,\n"
                "    const PtrList<FieldField<Field, scalar> >& intCoeffs,\n"
                "    const lduInterfaceFieldPtrsListList& interfaces,\n"
                "    const dictionary& dict\n"
                ")",
                dict
            )   << "Unknown symmetric matrix solver " << solverName
                << endl << endl
                << "Valid symmetric matrix solvers are :" << endl
                << symMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<coupledLduSolver>
        (
            constructorIter()
            (
                fieldName,
                matrix,
                bouCoeffs,
                intCoeffs,
                interfaces,
                dict
            )
        );
    }
    else if (matrix.asymmetric())
    {
        asymMatrixConstructorTable::iterator constructorIter =
            asymMatrixConstructorTablePtr_->find(solverName);

        if (constructorIter == asymMatrixConstructorTablePtr_->end())
        {
            FatalIOErrorIn
            (
                "autoPtr<coupledLduSolver> coupledLduSolver::New\n"
                "(\n"
                "    const word& fieldName,\n"
                "    const coupledLduMatrix& matrix,\n"
                "    const PtrList<FieldField<Field, scalar> >& bouCoeffs,\n"
                "    const PtrList<FieldField<Field, scalar> >& intCoeffs,\n"
                "    const lduInterfaceFieldPtrsListList& interfaces,\n"
                "    const dictionary& dict\n"
                ")",
                dict
            )   << "Unknown asymmetric matrix solver " << solverName
                << endl << endl
                << "Valid asymmetric matrix solvers are :" << endl
                << asymMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<coupledLduSolver>
        (
            constructorIter()
            (
                fieldName,
                matrix,
                bouCoeffs,
                intCoeffs,
                interfaces,
                dict
            )
        );
    }
    else
    {
        FatalErrorIn
        (
            "autoPtr<coupledLduSolver> coupledLduSolver::New\n"
            "(\n"
            "    const word& fieldName,\n"
            "    const coupledLduMatrix& matrix,\n"
            "    const direction cmpt,\n"
            "    const PtrList<FieldField<Field, scalar> >& bouCoeffs,\n"
            "    const PtrList<FieldField<Field, scalar> >& intCoeffs,\n"
            "    const lduInterfaceFieldPtrsListList& interfaces,\n"
            "    const dictionary& dict\n"
            ")"
        )   << "cannot solve incomplete matrix, "
               "no diagonal or off-diagonal coefficient"
            << exit(FatalError);

        return autoPtr<coupledLduSolver>(NULL);
    }
}