⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matrix_indirect.c

📁 利用语言编写的有限元分析软件
💻 C
📖 第 1 页 / 共 5 页
字号:

            if( ii > ij) {
                dSum  = 0.0;
                for (ik = 1; ik < ij; ik = ik + 1)
                     dSum += spA->uMatrix.daa[ ii-1 ][ ik-1 ] *
                             spA->uMatrix.daa[ ij-1 ][ ik-1 ];

                spA->uMatrix.daa[ii-1][ij-1] = (spA->uMatrix.daa[ ii-1 ][ ij-1 ] - dSum) /
                                                spA->uMatrix.daa[ij-1][ij-1];

                spA->uMatrix.daa[ij-1][ii-1] = spA->uMatrix.daa[ii-1][ij-1];
            }

            }
       }

       return ( spA );
}


/* 
 *  =================================================================
 *  SetupScaleFactors() : Initialize vector for scale factors. If [A]
 *  is a (nxn) matrix, then spScale will be a (nx1) vector containing
 *  the maximum absolute value in each row of [A].
 *  
 *  Input :   MATRIX spA       -- Pointer to (nxn) matrix [A].
 *  Output :  VECTOR spScale   -- Pointer to (nx1) vector spScale.
 *  =================================================================
 */ 

#ifdef __STDC__
VECTOR *SetupScaleFactors( MATRIX *spA )
#else  /* Start case not STDC */
VECTOR *SetupScaleFactors( spA )
MATRIX *spA;
#endif /* End case not STDC */
{
VECTOR *spScale;
double    dTemp;
int      ii, ij;

    spScale = VectorAlloc("Scale Factor",  DOUBLE_ARRAY, spA->iNoRows );

    for (ii = 1; ii <= spA->iNoRows; ii = ii + 1) {
         spScale->uVector.da[ii-1] = ABS(spA->uMatrix.daa[ii-1][0]);
         for (ij = 2; ij <= spA->iNoColumns; ij = ij + 1) {
              dTemp = ABS(spA->uMatrix.daa[ii-1][ij-1]);
              spScale->uVector.da[ii-1] = (double) MAX( spScale->uVector.da[ii-1], dTemp );
         }

         if( spScale->uVector.da[ii-1] == 0)
             FatalError("Execution halted in SetupScaleFactors()",
                        "Matrix A is Singular !!",
                        (char *) NULL);
    }

    return ( spScale );
}

/* 
 *  ==================================================================
 *  SetupPivotVector() : Initialize (nx1) vector for row permutations.
 *  
 *  Input :   MATRIX spA       -- Pointer to (nxn) matrix [A].
 *  Output :  VECTOR spPivot   -- Pointer to (nx1) vector spPivot.
 *  ==================================================================
 */ 

#ifdef __STDC__
VECTOR *SetupPivotVector( MATRIX *spA )
#else  /* Start case not STDC */
VECTOR *SetupPivotVector( spA )
MATRIX *spA;
#endif /* End case not STDC */
{
VECTOR *spPivot;
int          ii;

    spPivot = VectorAlloc(  "Row Pivots", INTEGER_ARRAY, spA->iNoRows );

    for (ii = 1; ii <= spA->iNoRows; ii = ii + 1)
         spPivot->uVector.ia[ii-1] = ii;

    return ( spPivot );
}


/* 
 *  ==================================================================
 *  Pivot() : Find largest element below diagonal and pivot rows
 *  
 *  Input  :   MATRIX spA       -- Pointer to (nxn) matrix [A].
 *         :   VECTOR spScale   -- Pointer to (nx1) vector spScale.
 *         :   VECTOR spPivot   -- Pointer to (nx1) vector spPivot.
 *         :   int iColumnNo    -- Column No for Pivoting
 *  Output :   MATRIX spA       -- [A] and [spPivot] are rearranged by
 *                                 the pivoting procedure.
 *  ==================================================================
 */ 

#ifdef __STDC__
Pivot( MATRIX *spA, VECTOR *spScale, VECTOR *spPivot, int iColumnNo )
#else  /* Start case not STDC */
Pivot( spA, spScale, spPivot, iColumnNo )
VECTOR *spScale, *spPivot;
MATRIX     *spA;
int   iColumnNo;
#endif /* End case not STDC */
{
double dLargest,     dTemp;
int  ii , iTemp,    iOrder;
int      iPivot;

    /* [a] : Find Row No of Largest Scaled Equation  */

       iPivot  = iColumnNo;
       iOrder  = spPivot->uVector.ia[ iColumnNo - 1 ];

       dLargest = spA->uMatrix.daa[ iOrder-1 ][ iColumnNo - 1 ] /
                  spScale->uVector.da[ iOrder-1 ];
       dLargest = ABS( dLargest );

       for (ii = iColumnNo + 1; ii <= spA->iNoColumns; ii = ii + 1) {
            iOrder = spPivot->uVector.ia[ ii - 1 ];

            dTemp  = spA->uMatrix.daa[ iOrder-1 ][ iColumnNo - 1 ] /
                     spScale->uVector.da[ iOrder-1 ];
            dTemp  = ABS( dTemp );

            if( dTemp > dLargest ) {
                dLargest = dTemp;
                iPivot   = ii;
            }
       }

       if( dLargest == 0 )
           FatalError("Execution halted in Pivot()",
                      "Matrix A is Singular !!",
                      (char *) NULL);

    /* [b] : Swap Row Nos in Order Vector */

       iTemp  = spPivot->uVector.ia[ iPivot - 1 ];
       spPivot->uVector.ia[ iPivot - 1 ]    = spPivot->uVector.ia[ iColumnNo - 1 ];
       spPivot->uVector.ia[ iColumnNo - 1 ] = iTemp;
}


/*
 *  =================================================================
 *  GeneralizedEigen() : Solve Eigen Problem [A][x] = [B][x][Lambda].
 *                       where [A] and [B] are small fully populated  
 *                       symmetric matrices.  
 *  
 *  We convert [A][x] = [B][x][Lambda] into [A*][y] = [y][Lambda] in
 *  a four-step procedure:  
 *  
 *        (a) : Compute [B] = [L].[L]^T  
 *        (b) : Solve   [L][C] = [A].
 *        (c) : Compute [C]^T.
 *        (d) : Solve   [L][A*]^T = [C]^T; matrix [A*] is symmetric.  
 *  
 *  Use Householder method to solve [A*][y] = [y][Lamda], followed by 
 *  backward substitutution for [L]^T.[x] = [y].
 *  
 *  Written By : M. Austin                              November 1993 
 *  =================================================================
 */

GeneralizedEigen( spA, spB, spEigenvalue, spEigenvector )
MATRIX   *spA,    *spB;
MATRIX   *spEigenvalue;
MATRIX  *spEigenvector;
{
MATRIX *spEigenvectorY;
MATRIX       *spCwork2;
MATRIX        *spAwork;
MATRIX        *spCwork;
MATRIX          *spLLT;
int        iSize;
int   ii, ij, ik;
double       sum;

#ifdef MYDEBUG
       printf("\n*** Enter GeneralizedEigen()\n");
       MatrixPrint ( spA );
       MatrixPrint ( spB );
#endif

    /* [a] : Check Input and Allocate Working Arrays */

       iSize = spA->iNoRows;
       spCwork = MatrixAllocIndirect("Working [C]", DOUBLE_ARRAY, iSize, iSize );
       spAwork = MatrixAllocIndirect("Working [A]", DOUBLE_ARRAY, iSize, iSize );

    /* [b] : Compute Cholesky Decomposition [B] = [L].[L]^T */

       spLLT = MatrixCopy( spB );
       spLLT = CholeskyDecompositionIndirect( spLLT );

    /* [c] : Solve [L][C] = [A] via Forward Substitution */

       for (ij = 1; ij <= spA->iNoRows; ij = ij + 1) {
            for (ii = 1; ii <= spA->iNoColumns; ii = ii + 1) {

            sum  = 0.0;
            for (ik = 1; ik < ii; ik = ik + 1)
                 sum += spLLT->uMatrix.daa[ ii-1 ][ ik-1 ] *
                               spCwork->uMatrix.daa[ ik-1 ][ij-1];

            spCwork->uMatrix.daa[ii-1][ij-1] = (spA->uMatrix.daa[ ii-1 ][ ij-1 ] - sum) /
                                                spLLT->uMatrix.daa[ ii-1 ][ ii-1 ];

            }
       }

    /* [d] : Replace [C] by [C]^T. */

       spCwork2 = MatrixTranspose ( spCwork );

    /* [e] : Solve [L][A*] = [C]^T via Forward Substitution */

       for (ij = 1; ij <= spA->iNoRows; ij = ij + 1) {
            for (ii = 1; ii <= spA->iNoColumns; ii = ii + 1) {

            sum  = 0.0;
            for (ik = 1; ik < ii; ik = ik + 1)
                 sum += spLLT->uMatrix.daa[ ii-1 ][ ik-1 ] *
                               spAwork->uMatrix.daa[ ik-1 ][ij-1];

            spAwork->uMatrix.daa[ii-1][ij-1] =
                    (spCwork2->uMatrix.daa[ ii-1 ][ ij-1 ] - sum) /
                     spLLT->uMatrix.daa[ ii-1 ][ ii-1 ];
            }
       }

    /* [f] : Use Householder Method to Solve Standard Eigenvalue Problem */

       iSize = spAwork->iNoRows;
       spEigenvectorY = MatrixAllocIndirect("Eigenvector [Y]", DOUBLE_ARRAY, iSize, iSize);

    /* [e] : Use Householder Transformation to convert [spStiff] to Triangular form */

       Householder( spAwork, spEigenvalue, spEigenvectorY );

    /* [g] : Compute [L]^T.[X] = [Y] via Back Substitution */

       for (ij = spAwork->iNoRows; ij >= 1 ; ij = ij - 1) {
            for (ii = 1; ii <= spAwork->iNoColumns; ii = ii + 1) {

            sum  = 0.0;
            for (ik = ij + 1; ik <= spAwork->iNoRows; ik = ik + 1)
                 sum += spLLT->uMatrix.daa[ ij-1 ][ ik-1 ] *
                               spEigenvector->uMatrix.daa[ ik-1 ][ii-1];

            spEigenvector->uMatrix.daa[ij-1][ii-1] =
                          (spEigenvectorY->uMatrix.daa[ ij-1 ][ ii-1 ] - sum) /
                           spLLT->uMatrix.daa[ ij-1 ][ ij-1 ];

            }
       }

    /* [h] : Cleanup before leaving */

       MatrixFree( spAwork );
       MatrixFree( spCwork );
       MatrixFree( spCwork2 );
       MatrixFree( spEigenvectorY );
       MatrixFree( spLLT );

#ifdef MYDEBUG
       printf("\n*** Leave GeneralizedEigen()\n");
#endif

}


/*
 *  ========================================================================
 *  Householder() : Compute Eigenvalues/Eigenvectors of Symmetric Matrix Via
 *  Householder's Transformation and QL-Algorithm.
 *  
 *  Input  :  MATRIX *spK           -- Pointer to large matrix [K].
 *         :  MATRIX *spEigenvalue  -- Pointer to (nx1) eigenvalue matrix.
 *         :  MATRIX *spEigenvector -- Pointer to (nxn) eigenvector matrix.
 *  Output :  MATRIX *spEigenvalue  -- Pointer to (nx1) eigenvalue matrix.
 *         :  MATRIX *spEigenvector -- Pointer to (nxn) eigenvector matrix.
 *  
 *  Written By: Mark Austin                                    November 1993
 *  ========================================================================
 */

Householder( spK, spEigenvalue, spEigenvector )
MATRIX            *spK;
MATRIX   *spEigenvalue;
MATRIX  *spEigenvector;
{
double  *t1, *t2;
int         stat;
int       ii, ij;
int iNoEquations;

 /* [a] : Setup Working Matrices for Eigenvalues and Eigenvectors */

    iNoEquations = spK->iNoRows;
    t1 = (double *) MyCalloc( iNoEquations, sizeof(double));
    t2 = (double *) MyCalloc( iNoEquations, sizeof(double));

    for( ii = 1; ii <= iNoEquations; ii = ii + 1)
    for( ij = 1; ij <= iNoEquations; ij = ij + 1)
         spEigenvector->uMatrix.daa[ ii-1 ][ ij-1 ] = spK->uMatrix.daa[ ii-1 ][ ij-1 ];

 /* [b] : Convert [K] to Tridiagonal Form with Householder Transformation */

    HouseHolderTransformation( spEigenvector, t1, t2, iNoEquations);

 /* [c] : Use ql Algorithm to compute Eigenvalues and Eigenvectors */

    stat = QlAlgorithm( spEigenvector, t1, t2, iNoEquations);

 /* [d] : Transfer Working Matrix to Eigenvalues */

    for( ii = 1; ii <= iNoEquations; ii = ii + 1)
         spEigenvalue->uMatrix.daa[ ii-1 ][0] = t1[ ii-1 ];

    free((char *) t1);
    free((char *) t2);

    return stat;
}


/*
 *  ==============================================================
 *  HouseHolderTrans() : Use HouseHolder Transformation to convert
 *                       Symmetric Matrix to tridiagonal form.
 *  ==============================================================
 */

static double TOLERANCE = 1.3e-16;

HouseHolderTransformation( spK , d, e, iNoEquations)
MATRIX      *spK;
double    *d, *e;
int iNoEquations;
{
int    ii, ij, ik, im;
double dTempf, dTempg;
double dTemph, dTempk;

    ii = iNoEquations;
    while (--ii) {

        im = ii - 2;
        dTempf = spK->uMatrix.daa[ii][ii-1];
        dTempg = 0.0;
        for (ij = 0; ij <= im; ij++)
             dTempg += spK->uMatrix.daa[ii][ij] * spK->uMatrix.daa[ii][ij];

        dTemph = dTempg + dTempf * dTempf;
        if (dTempg < TOLERANCE) {
                 e[ii]  = dTempf;
                 dTemph = 0.0;
        } else {
             im++;
             if (dTempf >= 0)
                 dTempg = -sqrt( dTemph );
             else
                 dTempg =  sqrt( dTemph );

             e[ii] = dTempg;
             dTemph -= dTempf * dTempg;
             spK->uMatrix.daa[ii][ii-1] = dTempf - dTempg;

             dTempf = 0;
             for (ij = 0; ij <= im; ij++) {
                  spK->uMatrix.daa[ij][ii] = spK->uMatrix.daa[ii][ij] / dTemph;
                  dTempg 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -