Esempio n. 1
0
void multiply
(
    scalarSquareMatrix& ans,         // value changed in return
    const scalarDiagonalMatrix& A,
    const scalarSquareMatrix& B,
    const scalarDiagonalMatrix& C
)
{
    if (A.size() != B.n())
    {
        FatalErrorIn
        (
            "multiply("
            "scalarRectangularMatrix& answer),"
            "const DiagonalMatrix<scalar>& A, "
            "const scalarRectangularMatrix& B, "
            "const DiagonalMatrix<scalar>& C"
        )   << "A and B must have identical inner dimensions but A.m = "
            << A.size() << " and B.n = " << B.n()
            << abort(FatalError);
    }
    
    if (B.m() != C.size())
    {
        FatalErrorIn
        (
             "multiply("
            "scalarRectangularMatrix& answer),"
            "const DiagonalMatrix<scalar>& A, "
            "const scalarRectangularMatrix& B, "
            "const DiagonalMatrix<scalar>& C"
        )   << "B and C must have identical inner dimensions but B.m = "
            << B.m() << " and C.n = " << C.size()
            << abort(FatalError);
    }
    
    
    ans = scalarSquareMatrix(B.n(), B.n(), scalar(0));

    for (register label i = 0; i < A.size(); i++)
    {
        for (register label j = 0; j < C.size(); j++)
        {               
            ans[i][j] = A[i] * B[i][j] * C[j];
        }
    }

}
Esempio n. 2
0
bool Foam::chemPointISAT<CompType, ThermoType>::grow(const scalarField& phiq)
{
    scalarField dphi(phiq - phi());
    label dim = completeSpaceSize();
    label initNActiveSpecies(nActiveSpecies_);
    bool isMechRedActive = chemistry_.mechRed()->active();

    if (isMechRedActive)
    {
        label activeAdded(0);
        DynamicList<label> dimToAdd(0);

        // check if the difference of active species is lower than the maximum
        // number of new dimensions allowed
        for (label i=0; i<completeSpaceSize()-nAdditionalEqns_; i++)
        {
            // first test if the current chemPoint has an inactive species
            // corresponding to an active one in the query point
            if
            (
                completeToSimplifiedIndex_[i] == -1
             && chemistry_.completeToSimplifiedIndex()[i]!=-1
            )
            {
                activeAdded++;
                dimToAdd.append(i);
            }
            // then test if an active species in the current chemPoint
            // corresponds to an inactive on the query side
            if
            (
                completeToSimplifiedIndex_[i] != -1
             && chemistry_.completeToSimplifiedIndex()[i] == -1
            )
            {
                activeAdded++;
                // we don't need to add a new dimension but we count it to have
                // control on the difference through maxNumNewDim
            }
            // finally test if both points have inactive species but
            // with a dphi!=0
            if
            (
                completeToSimplifiedIndex_[i] == -1
             && chemistry_.completeToSimplifiedIndex()[i] == -1
             && dphi[i] != 0
            )
            {
                activeAdded++;
                dimToAdd.append(i);
            }
        }

        // if the number of added dimension is too large, growth fail
        if (activeAdded > maxNumNewDim_)
        {
            return false;
        }

        // the number of added dimension to the current chemPoint
        nActiveSpecies_ += dimToAdd.size();
        simplifiedToCompleteIndex_.setSize(nActiveSpecies_);
        forAll(dimToAdd, i)
        {
            label si = nActiveSpecies_ - dimToAdd.size() + i;
            // add the new active species
            simplifiedToCompleteIndex_[si] = dimToAdd[i];
            completeToSimplifiedIndex_[dimToAdd[i]] = si;
        }

        // update LT and A :
        //-add new column and line for the new active species
        //-transfer last two lines of the previous matrix (p and T) to the end
        //  (change the diagonal position)
        //-set all element of the new lines and columns to zero except diagonal
        //  (=1/(tolerance*scaleFactor))
        if (nActiveSpecies_ > initNActiveSpecies)
        {
            scalarSquareMatrix LTvar = LT_; // take a copy of LT_
            scalarSquareMatrix Avar = A_; // take a copy of A_
            LT_ = scalarSquareMatrix(nActiveSpecies_+nAdditionalEqns_, Zero);
            A_ = scalarSquareMatrix(nActiveSpecies_+nAdditionalEqns_, Zero);

            // write the initial active species
            for (label i=0; i<initNActiveSpecies; i++)
            {
                for (label j=0; j<initNActiveSpecies; j++)
                {
                    LT_(i, j) = LTvar(i, j);
                    A_(i, j) = Avar(i, j);
                }
            }

            // write the columns for temperature and pressure
            for (label i=0; i<initNActiveSpecies; i++)
            {
                for (label j=1; j>=0; j--)
                {
                    LT_(i, nActiveSpecies_+j)=LTvar(i, initNActiveSpecies+j);
                    A_(i, nActiveSpecies_+j)=Avar(i, initNActiveSpecies+j);
                    LT_(nActiveSpecies_+j, i)=LTvar(initNActiveSpecies+j, i);
                    A_(nActiveSpecies_+j, i)=Avar(initNActiveSpecies+j, i);
                }
            }
            // end with the diagonal elements for temperature and pressure
            LT_(nActiveSpecies_, nActiveSpecies_)=
                LTvar(initNActiveSpecies, initNActiveSpecies);
            A_(nActiveSpecies_, nActiveSpecies_)=
                Avar(initNActiveSpecies, initNActiveSpecies);
            LT_(nActiveSpecies_+1, nActiveSpecies_+1)=
                LTvar(initNActiveSpecies+1, initNActiveSpecies+1);
            A_(nActiveSpecies_+1, nActiveSpecies_+1)=
                Avar(initNActiveSpecies+1, initNActiveSpecies+1);

            if (variableTimeStep())
            {
                LT_(nActiveSpecies_+2, nActiveSpecies_+2)=
                    LTvar(initNActiveSpecies+2, initNActiveSpecies+2);
                A_(nActiveSpecies_+2, nActiveSpecies_+2)=
                    Avar(initNActiveSpecies+2, initNActiveSpecies+2);
            }

            for (label i=initNActiveSpecies; i<nActiveSpecies_;i++)
            {
                LT_(i, i)=
                    1.0
                   /(tolerance_*scaleFactor_[simplifiedToCompleteIndex_[i]]);
                A_(i, i) = 1;
            }
        }

        dim = nActiveSpecies_ + nAdditionalEqns_;
    }
Esempio n. 3
0
Foam::chemPointISAT<CompType, ThermoType>::chemPointISAT
(
    TDACChemistryModel<CompType, ThermoType>& chemistry,
    const scalarField& phi,
    const scalarField& Rphi,
    const scalarSquareMatrix& A,
    const scalarField& scaleFactor,
    const scalar& tolerance,
    const label& completeSpaceSize,
    const dictionary& coeffsDict,
    binaryNode<CompType, ThermoType>* node
)
:
    chemistry_(chemistry),
    phi_(phi),
    Rphi_(Rphi),
    A_(A),
    scaleFactor_(scaleFactor),
    node_(node),
    completeSpaceSize_(completeSpaceSize),
    nGrowth_(0),
    nActiveSpecies_(chemistry.mechRed()->NsSimp()),
    simplifiedToCompleteIndex_(nActiveSpecies_),
    timeTag_(chemistry_.timeSteps()),
    lastTimeUsed_(chemistry_.timeSteps()),
    toRemove_(false),
    maxNumNewDim_(coeffsDict.lookupOrDefault("maxNumNewDim",0)),
    printProportion_(coeffsDict.lookupOrDefault("printProportion",false)),
    numRetrieve_(0),
    nLifeTime_(0),
    completeToSimplifiedIndex_
    (
        completeSpaceSize - (2 + (variableTimeStep() == 1 ? 1 : 0))
    )
{
    tolerance_ = tolerance;

    if (variableTimeStep())
    {
        nAdditionalEqns_ = 3;
        iddeltaT_ = completeSpaceSize - 1;
        scaleFactor_[iddeltaT_] *= phi_[iddeltaT_] / tolerance_;
    }
    else
    {
        nAdditionalEqns_ = 2;
        iddeltaT_ = completeSpaceSize; // will not be used
    }
    idT_ = completeSpaceSize - nAdditionalEqns_;
    idp_ = completeSpaceSize - nAdditionalEqns_ + 1;

    bool isMechRedActive = chemistry_.mechRed()->active();
    if (isMechRedActive)
    {
        for (label i=0; i<completeSpaceSize-nAdditionalEqns_; i++)
        {
            completeToSimplifiedIndex_[i] =
                chemistry.completeToSimplifiedIndex()[i];
        }
        for (label i=0; i<nActiveSpecies_; i++)
        {
            simplifiedToCompleteIndex_[i] =
                chemistry.simplifiedToCompleteIndex()[i];
        }
    }

    label reduOrCompDim = completeSpaceSize;
    if (isMechRedActive)
    {
        reduOrCompDim = nActiveSpecies_+nAdditionalEqns_;
    }

    // SVD decomposition A = U*D*V^T
    SVD svdA(A);

    scalarDiagonalMatrix D(reduOrCompDim);
    const scalarDiagonalMatrix& S = svdA.S();

    // Replace the value of vector D by max(D, 1/2), first ISAT paper
    for (label i=0; i<reduOrCompDim; i++)
    {
        D[i] = max(S[i], 0.5);
    }

    // Rebuild A with max length, tol and scale factor before QR decomposition
    scalarRectangularMatrix Atilde(reduOrCompDim);

    // Result stored in Atilde
    multiply(Atilde, svdA.U(), D, svdA.V().T());

    for (label i=0; i<reduOrCompDim; i++)
    {
        for (label j=0; j<reduOrCompDim; j++)
        {
            label compi = i;

            if (isMechRedActive)
            {
                compi = simplifiedToCompleteIndex(i);
            }

            // SF*A/tolerance
            // (where SF is diagonal with inverse of scale factors)
            // SF*A is the same as dividing each line by the scale factor
            // corresponding to the species of this line
            Atilde(i, j) /= (tolerance*scaleFactor[compi]);
        }
    }

    // The object LT_ (the transpose of the Q) describe the EOA, since we have
    // A^T B^T B A that should be factorized into L Q^T Q L^T and is set in the
    // qrDecompose function
    LT_ = scalarSquareMatrix(Atilde);

    qrDecompose(reduOrCompDim, LT_);
}
Esempio n. 4
0
void multiply
(
    scalarSquareMatrix& ans,         // value changed in return
    const scalarRectangularMatrix& A,
    const scalarRectangularMatrix& B,
    const scalarRectangularMatrix& C,
    const scalarDiagonalMatrix& D
)
{
    if (A.m() != B.n())
    {
        FatalErrorIn
        (
            "multiply("
            "scalarRectangularMatrix& answer),"
            "const scalarRectangularMatrix& A, "
            "const scalarRectangularMatrix& B, "
            "const scalarRectangularMatrix& C, "
            "const DiagonalMatrix<scalar>& D"
        )   << "A and B must have identical inner dimensions but A.m = "
            << A.m() << " and B.n = " << B.n()
            << abort(FatalError);
    }
    
    if (B.m() != C.n())
    {
        FatalErrorIn
        (
              "multiply("
            "scalarRectangularMatrix& answer),"
            "const scalarRectangularMatrix& A, "
            "const scalarRectangularMatrix& B, "
            "const scalarRectangularMatrix& C, "
            "const DiagonalMatrix<scalar>& D"
        )   << "B and C must have identical inner dimensions but B.m = "
            << B.m() << " and C.n = " << C.n()
            << abort(FatalError);
    }
    
    
    if (C.m() != D.size())
    {
        FatalErrorIn
        (
            "multiply("
            "scalarRectangularMatrix& answer),"
            "const scalarRectangularMatrix& A, "
            "const scalarRectangularMatrix& B, "
            "const scalarRectangularMatrix& C, "
            "const DiagonalMatrix<scalar>& D"
        )   << "C and D must have identical inner dimensions but C.m = "
            << C.m() << " and D.n = " << D.size()
            << abort(FatalError);
    }


    ans = scalarSquareMatrix(D.size(), D.size(), scalar(0));

    for (register label i = 0; i < A.n(); i++)
    {
        for (register label g = 0; g < C.m(); g++)
        {
            for (register label l = 0; l < C.n(); l++)
            {
                scalar ab = 0;
                for (register label j = 0; j < A.m(); j++)
                {   
                    ab += A[i][j]*B[j][l];
                }
                ans[i][g] += C[l][g] * ab;
            }
            
            ans[i][g] = ans[i][g] * D[g];
        }
    }

}