Foam::word Foam::lduMatrix::preconditioner::getName
(
    const dictionary& solverControls
)
{
    word name;

    // handle primitive or dictionary entry
    const entry& e = solverControls.lookupEntry("preconditioner", false, false);
    if (e.isDict())
    {
        e.dict().lookup("preconditioner") >> name;
    }
Foam::word Foam::coupledLduSmoother::getName
(
    const dictionary& dict
)
{
    word name;

    // handle primitive or dictionary entry
    const entry& e = dict.lookupEntry("smoother", false, false);
    if (e.isDict())
    {
        e.dict().lookup("smoother") >> name;
    }
Foam::autoPtr<Foam::BlockLduPrecon<Type> > Foam::BlockLduPrecon<Type>::New
(
    const BlockLduMatrix<Type>& matrix,
    const dictionary& dict
)
{
    word preconName;

    // handle primitive or dictionary entry
    const entry& e = dict.lookupEntry("preconditioner", false, false);
    if (e.isDict())
    {
        e.dict().lookup("preconditioner") >> preconName;
    }
Foam::autoPtr<Foam::BlockLduSmoother<Type> > Foam::BlockLduSmoother<Type>::New
(
    const BlockLduMatrix<Type>& matrix,
    const dictionary& dict
)
{
    word smootherName;

    // Handle primitive or dictionary entry
    const entry& e = dict.lookupEntry("smoother", false, false);
    if (e.isDict())
    {
        e.dict().lookup("smoother") >> smootherName;
    }
Foam::autoPtr<Foam::lduMatrix::smoother> Foam::lduMatrix::smoother::New
(
    const lduMatrix& matrix,
    const FieldField<Field, scalar>& coupleBouCoeffs,
    const FieldField<Field, scalar>& coupleIntCoeffs,
    const lduInterfaceFieldPtrsList& interfaces,
    const dictionary& dict,
    const word keyword
)
{
    word smootherName;

    // Handle primitive or dictionary entry
    const entry& e = dict.lookupEntry(keyword, false, false);
    if (e.isDict())
    {
        e.dict().lookup(keyword) >> smootherName;
    }
Foam::word
Foam::lduMatrix::smoother::getName
(
    const dictionary& solverControls
)
{
    word name;

    // Handle primitive or dictionary entry
    const entry& e =
        solverControls.lookupEntry("smoother", keyType::LITERAL);

    if (e.isDict())
    {
        e.dict().readEntry("smoother", name);
    }
    else
    {
        e.stream() >> name;
    }

    return name;
}
Foam::dynamicCodeContext::dynamicCodeContext(const dictionary& dict)
:
    dict_(dict),
    code_(),
    localCode_(),
    include_(),
    options_(),
    libs_()
{
    // expand dictionary entries

    {
        const entry& codeEntry = dict.lookupEntry("code", false, false);
        code_ = stringOps::trim(codeEntry.stream());
        stringOps::inplaceExpand(code_, dict);
    }

    // note: removes any leading/trailing whitespace
    // - necessary for compilation options, convenient for includes
    // and body.

    // optional
    const entry* includePtr = dict.lookupEntryPtr
    (
        "codeInclude",
        false,
        false
    );
    if (includePtr)
    {
        include_ = stringOps::trim(includePtr->stream());
        stringOps::inplaceExpand(include_, dict);
    }

    // optional
    const entry* optionsPtr = dict.lookupEntryPtr
    (
        "codeOptions",
        false,
        false
    );
    if (optionsPtr)
    {
        options_ = stringOps::trim(optionsPtr->stream());
        stringOps::inplaceExpand(options_, dict);
    }

    // optional
    const entry* libsPtr = dict.lookupEntryPtr("codeLibs", false, false);
    if (libsPtr)
    {
        libs_ = stringOps::trim(libsPtr->stream());
        stringOps::inplaceExpand(libs_, dict);
    }

    // optional
    const entry* localPtr = dict.lookupEntryPtr("localCode", false, false);
    if (localPtr)
    {
        localCode_ = stringOps::trim(localPtr->stream());
        stringOps::inplaceExpand(localCode_, dict);
    }

    // calculate SHA1 digest from include, options, localCode, code
    OSHA1stream os;
    os  << include_ << options_ << libs_ << localCode_ << code_;
    sha1_ = os.digest();



    // Add line number after calculating sha1 since includes processorDDD
    // in path which differs between processors.

    {
        const entry& codeEntry = dict.lookupEntry("code", false, false);
        addLineDirective(code_, codeEntry.startLineNumber(), dict.name());
    }
    if (includePtr)
    {
        addLineDirective(include_, includePtr->startLineNumber(), dict.name());
    }

    // Do not add line directive to options_ (Make/options) and libs since
    // they are preprocessed as a single line at this point. Can be fixed.

    if (localPtr)
    {
        addLineDirective(localCode_, localPtr->startLineNumber(), dict.name());
    }
}
Foam::autoPtr<Foam::lduMatrix::smoother> Foam::lduMatrix::smoother::New
(
    const word& fieldName,
    const lduMatrix& matrix,
    const FieldField<Field, scalar>& interfaceBouCoeffs,
    const FieldField<Field, scalar>& interfaceIntCoeffs,
    const lduInterfaceFieldPtrsList& interfaces,
    const dictionary& solverControls
)
{
    word name;

    // Handle primitive or dictionary entry
    const entry& e =
        solverControls.lookupEntry("smoother", keyType::LITERAL);

    if (e.isDict())
    {
        e.dict().readEntry("smoother", name);
    }
    else
    {
        e.stream() >> name;
    }

    // not (yet?) needed:
    // const dictionary& controls = e.isDict() ? e.dict() : dictionary::null;

    if (matrix.symmetric())
    {
        auto cstrIter = symMatrixConstructorTablePtr_->cfind(name);

        if (!cstrIter.found())
        {
            FatalIOErrorInFunction(solverControls)
                << "Unknown symmetric matrix smoother "
                << name << nl << nl
                << "Valid symmetric matrix smoothers are :" << endl
                << symMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<lduMatrix::smoother>
        (
            cstrIter()
            (
                fieldName,
                matrix,
                interfaceBouCoeffs,
                interfaceIntCoeffs,
                interfaces
            )
        );
    }
    else if (matrix.asymmetric())
    {
        auto cstrIter = asymMatrixConstructorTablePtr_->cfind(name);

        if (!cstrIter.found())
        {
            FatalIOErrorInFunction(solverControls)
                << "Unknown asymmetric matrix smoother "
                << name << nl << nl
                << "Valid asymmetric matrix smoothers are :" << endl
                << asymMatrixConstructorTablePtr_->sortedToc()
                << exit(FatalIOError);
        }

        return autoPtr<lduMatrix::smoother>
        (
            cstrIter()
            (
                fieldName,
                matrix,
                interfaceBouCoeffs,
                interfaceIntCoeffs,
                interfaces
            )
        );
    }

    FatalIOErrorInFunction(solverControls)
        << "cannot solve incomplete matrix, "
        "no diagonal or off-diagonal coefficient"
        << exit(FatalIOError);

    return nullptr;
}