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

📄 matrix_indirect.c

📁 利用语言编写的有限元分析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
       if( CheckUnits() == ON ) {
          for(ii = 1; ii <= spA->iNoRows; ii++)
              UnitsCopy(&(spB->spColUnits[ii-1]), &(spA->spRowUnits[ii-1]));
          for(ij = 1; ij <= spA->iNoColumns; ij++)
              UnitsCopy(&(spB->spRowUnits[ij-1]), &(spA->spColUnits[ij-1]));
       }
           
       return (spB);
}

/*
 *  ===================================================
 *  MatrixCopyIndirectDouble() : Matrix Copy [B] = [A].
 *  
 *  Input  :  MATRIX *spA  -- Pointer to matrix A.
 *  Output :  MATRIX *spB  -- Pointer to matrix B.
 *  ===================================================
 */

#ifdef __STDC__
MATRIX *MatrixCopyIndirectDouble( MATRIX *spA )
#else  /* Start case not STDC */
MATRIX *MatrixCopyIndirectDouble( spA )
MATRIX *spA;
#endif /* End case not STDC */
{
MATRIX *spB;
int  ii, ij;
int  length;
int UNITS_SWITCH;

     UNITS_SWITCH = CheckUnits();
    /* [a] : Make Copy of Matrix */

       spB = MatrixAllocIndirect( spA->cpMatrixName, DOUBLE_ARRAY, spA->iNoRows, spA->iNoColumns);

       switch( UNITS_SWITCH) {
         case ON:
             for(ii = 1; ii <= spA->iNoRows; ii++) {
                 UnitsCopy(&(spB->spRowUnits[ii-1]), &(spA->spRowUnits[ii-1]));
                 for(ij = 1; ij <= spA->iNoColumns; ij++) {
                    spB->uMatrix.daa[ii-1][ij-1] = spA->uMatrix.daa[ii-1][ij-1];
                 }
             }
             for(ij = 1; ij <= spA->iNoColumns; ij++)
                 UnitsCopy(&(spB->spColUnits[ij-1]), &(spA->spColUnits[ij-1]));
             break;
         case OFF:
             for(ii = 1; ii <= spA->iNoRows; ii++)
                 for(ij = 1; ij <= spA->iNoColumns; ij++)
                    spB->uMatrix.daa[ii-1][ij-1] = spA->uMatrix.daa[ii-1][ij-1];
             break;
         default:
             break;
       }

       return ( spB );
}


#ifdef __STDC__
MATRIX *MatrixInverseIndirectDouble ( MATRIX *spA )
#else  /* Start case not STDC */
MATRIX *MatrixInverseIndirectDouble ( spA )
MATRIX *spA;
#endif /* End case not STDC */
{
MATRIX     *spAinv;
MATRIX *lu, *F, *X;
double          *d;
VECTOR       *indx;
int           i, j;
int         length;
int   UNITS_SWITCH;
     
     UNITS_SWITCH = CheckUnits();
     /* [0] : Check whether matrix spA is a square matrix    */
        
        if(spA->iNoRows != spA->iNoColumns) {
           printf("******matrix %s is not a square matrix :\n", spA->cpMatrixName);
           printf("******       %s->iNoRows    = %d\n", spA->cpMatrixName, spA->iNoRows); 
           printf("******       %s->iNoColumns = %d\n", spA->cpMatrixName, spA->iNoColumns); 
           printf("******check input file \n");
           FatalError("****** Only the square matrix has inverse. In MatrixInverse()",(char *)NULL);
        }

     /* [a] : Set up the column vector of ones */

     F    = MatrixAllocIndirect("F", DOUBLE_ARRAY, spA->iNoRows, 1);
     for(j = 1; j<= spA->iNoRows; j++)
            F->uMatrix.daa[j-1][0] = 0.0;

     if( UNITS_SWITCH == ON ) {
        ZeroUnits(&(F->spColUnits[0]));
        for(i = 1; i <= spA->iNoRows; i++)
            ZeroUnits(&(F->spRowUnits[i-1]));
     }

     /* [b] : Compute [L][U] decomposition of spA (copy) */

     indx = SetupPivotVector(spA);
     lu   = LUDecompositionIndirect(spA,indx);

     /* [c] : Solve series of equations for inverse */

     spAinv = MatrixAllocIndirect("Inverse(spA)", DOUBLE_ARRAY, spA->iNoRows, spA->iNoColumns);
     for(i = 1; i <= spA->iNoColumns; i++) {
         F->uMatrix.daa[i-1][0] = 1.0;
         X = LUSubstitutionIndirect((char *)NULL,indx,lu,F);
         for(j = 1; j<= spA->iNoRows; j++)
             spAinv->uMatrix.daa[j-1][i-1] = X->uMatrix.daa[j-1][0];
         MatrixFreeIndirect(X);
         F->uMatrix.daa[i-1][0] = 0.0;
     }

     /* [d] : Assign units to spAinv */
     if( UNITS_SWITCH == ON ) {
        for(i = 1; i <= spA->iNoRows; i++){
           UnitsPowerRep( &(spAinv->spColUnits[i-1]), &(spA->spRowUnits[i-1]), -1.0, YES );
           UnitsPowerRep( &(spAinv->spRowUnits[i-1]), &(spA->spColUnits[i-1]), -1.0, YES );
        }
     }

     /* [e] : Free memory, return result */

     VectorFree(indx);
     MatrixFree( lu );
     MatrixFree( F );

     return (spAinv);
}

/* 
 *  =====================================================================
 *  LUDecompositionDouble() : Use method of Crout Reduction with pivoting
 *  and scaled equtions to decompose a (nxn) matrix [A] into [L][U].
 *  
 *  Input  :  MATRIX     *spA  -- Pointer to (nxn) matrix A.
 *         :  VECTOR *spPivot  -- Pointer to (nx1) pivot vector.
 *  Output :  MATRIX     *spA  -- Pointer to (nxn) [L][U] product.
 *  =====================================================================
 */

#ifdef __STDC__
MATRIX *LUDecompositionIndirect( MATRIX *spA, VECTOR *spPivot)
#else  /* Start case not STDC */
MATRIX *LUDecompositionIndirect( spA, spPivot )
MATRIX      *spA;
VECTOR *spPivot;
#endif /* End case not STDC */
{
MATRIX         *spLU;
VECTOR      *spScale;
double          dSum;
double    dNumerator;
double  dDenominator;
int iOrder1, iOrder2;
int       ii, ij, ik;

    /* [a] : Make sure that Matrix spA is square    */

       if((spA->iNoRows != spA->iNoColumns)) {
           (void) printf("Problem : spA->iNoRows = %4d spA->iNoColumns = %4d\n",
                                    spA->iNoRows,      spA->iNoColumns);
           FatalError("Execution halted in LUDecomposition()",
                      "Matrix spA must be square",
                      (char *) NULL);
       }

    /* [b] : Setup Matrix of Scale Factors */

       spLU    = MatrixCopyIndirectDouble( spA );
       spScale = SetupScaleFactors( spLU );
    
    /* [c] : Loop over Columns and Compute Crout Reduction */

       ij = 1;
       Pivot( spLU, spScale, spPivot, ij );
       for (ij = 2; ij <= spLU->iNoColumns; ij = ij + 1) {
            iOrder1 = spPivot->uVector.ia[ 0 ];

            spLU->uMatrix.daa[iOrder1-1][ij - 1] =
                 spLU->uMatrix.daa[iOrder1-1][ij - 1]/spLU->uMatrix.daa[iOrder1-1][ 0 ];
       }

       for (ij = 2; ij <= spLU->iNoColumns - 1; ij = ij + 1) {
            for (ii = ij; ii <= spLU->iNoColumns; ii = ii + 1) {

                 iOrder1 = spPivot->uVector.ia[ ii - 1 ];

                 dSum = 0.0;
                 for (ik = 1; ik <= ij - 1; ik = ik + 1) {
                      iOrder2 = spPivot->uVector.ia[ ik - 1 ];
                      dSum += spLU->uMatrix.daa[ iOrder1-1 ][ ik - 1 ] *
                              spLU->uMatrix.daa[ iOrder2-1 ][ ij - 1 ];
                 }

                 spLU->uMatrix.daa[ iOrder1-1 ][ ij - 1 ] -= dSum;
            }

            Pivot( spLU, spScale, spPivot, ij );

            iOrder1 = spPivot->uVector.ia[ ij - 1 ];

            for (ik = ij + 1; ik <= spLU->iNoColumns; ik = ik + 1) {

                 dSum = 0.0;
                 for (ii = 1; ii <= ij - 1; ii = ii + 1) {
                      iOrder2 = spPivot->uVector.ia[ ii - 1 ];
                      dSum += spLU->uMatrix.daa[ iOrder1-1 ][ ii - 1 ] *
                              spLU->uMatrix.daa[ iOrder2-1 ][ ik - 1 ];
                 }

                 dNumerator   = spLU->uMatrix.daa[ iOrder1-1 ][ ik-1 ] - dSum;
                 dDenominator = spLU->uMatrix.daa[ iOrder1-1 ][ ij-1 ];

                 spLU->uMatrix.daa[ iOrder1-1 ][ ik - 1 ] = dNumerator/dDenominator;
            }
       }

       iOrder1 = spPivot->uVector.ia[ spLU->iNoColumns - 1 ];

       dSum = 0.0;
       for (ik = 1; ik <= spLU->iNoColumns - 1; ik = ik + 1) {
            iOrder2 = spPivot->uVector.ia[ ik - 1 ];
            dSum += spLU->uMatrix.daa[ iOrder1-1 ][ ik - 1 ] *
                    spLU->uMatrix.daa[ iOrder2-1 ][ spLU->iNoColumns - 1 ];
       }

       spLU->uMatrix.daa[ iOrder1 - 1 ][ spLU->iNoColumns - 1 ] -= dSum;

       VectorFree( spScale );
       return( spLU );
}


/* 
 *  =====================================================================
 *  LUSubstitutionDouble() : Compute Forward and Backward Substitution.
 *  
 *  Input  :  cpMatrixNameOfSolution -- Name of Solution Matrix
 *         :  VECTOR *spPivot        -- Pointer to (nx1) pivot vector.
 *         :  MATRIX    *spLU        -- Pointer to (nxn) matrix [L][U].
 *         :  MATRIX     *spB        -- Pointer to (nx1) matrix [B].
 *  Output :  MATRIX      spX        -- Pointer to (nx1) solution matrix.
 *  =====================================================================
 */

#ifdef __STDC__
MATRIX *LUSubstitutionIndirect( char *cpMatrixNameOfSolution, VECTOR *spPivot, MATRIX *spLU, MATRIX *spB )
#else  /* Start case not STDC */
MATRIX *LUSubstitutionIndirect( cpMatrixNameOfSolution, spPivot, spLU, spB)
char *cpMatrixNameOfSolution;
VECTOR              *spPivot;
MATRIX                 *spLU;
MATRIX                  *spB;
#endif /* End case not STDC */
{
MATRIX            *spDisp;
double       dDenominator;
double         dNumerator;
double               dSum;
int       iOrder1, ii, ij;
int                length;
DIMENSIONS   *d, *d1, *d2;
int UNITS_SWITCH;

     UNITS_SWITCH = CheckUnits();
   /* [a] : Allocate Memory for Displacement Vector */

      spDisp = MatrixAllocIndirect( cpMatrixNameOfSolution, DOUBLE_ARRAY, spLU->iNoRows, 1 );

   /* [0] : Calculate the units of displacements */

   if( UNITS_SWITCH == ON ) {
      for (ii = 1; ii <= spLU->iNoRows; ii++) {
         d1 = UnitsMult( &(spB->spRowUnits[ii-1]), &(spB->spColUnits[0]) );
         d2 = UnitsMult( &(spLU->spRowUnits[ii-1]), &(spLU->spColUnits[ii-1]) );
         UnitsDivRep( &(spDisp->spRowUnits[ii-1]), d1, d2, YES); 

         free((char *) d1->units_name);
         free((char *) d1);
         free((char *) d2->units_name);
         free((char *) d2);
      }
      ZeroUnits(&(spDisp->spColUnits[0]));
   }

   /* [b] : Forward Substitution with Unscrambling of Permutations */

      iOrder1 = spPivot->uVector.ia[ 0 ];
      spDisp->uMatrix.daa[0][0] = spB->uMatrix.daa[ iOrder1 - 1 ][ 0 ] /
                                  spLU->uMatrix.daa[ iOrder1 - 1 ][ 0 ];

      for( ii = 2; ii <= spLU->iNoRows; ii = ii + 1) {

           iOrder1 = spPivot->uVector.ia[ ii - 1 ];

           dSum = 0.0;
           for( ij = 1; ij <= ii - 1; ij = ij + 1) {
                dSum += spLU->uMatrix.daa[ iOrder1 - 1 ][ ij - 1] *
                        spDisp->uMatrix.daa[ ij - 1][0];
           }               

           dNumerator   = spB->uMatrix.daa[ iOrder1-1 ][0] - dSum;
           dDenominator = spLU->uMatrix.daa[ iOrder1-1 ][ ii-1 ];

           spDisp->uMatrix.daa[ ii - 1 ][0] = dNumerator/dDenominator;
      }               

   /* [c] : Backsubstitution with Unscrambling of Permutations */

      for( ii = spLU->iNoRows - 1; ii >= 1; ii = ii - 1) {

           iOrder1 = spPivot->uVector.ia[ ii - 1 ];

           dSum = 0.0;
           for( ij = ii + 1; ij <= spLU->iNoRows; ij = ij + 1) {
                dSum += spLU->uMatrix.daa[ iOrder1 - 1 ][ ij - 1] *
                        spDisp->uMatrix.daa[ ij - 1][0];
           }               

           spDisp->uMatrix.daa[ ii - 1 ][0] -= dSum;
      }               

      return(spDisp);
}


/*
 *  ================================================================
 *  CholeskyDecompositionIndirect() : [L][L]^T Cholesky Factorization 
 *                                    of Symmetric Indirect Matrix.
 * 
 *  Input  :  MATRIX *spA   -- Pointer to symmetric matrix [A].
 *  Output :  MATRIX *spA   -- Pointer to [L][L]^T.
 *  ================================================================
 */

#ifdef __STDC__
MATRIX *CholeskyDecompositionIndirect( MATRIX *spA )
#else  /* Start case not STDC */
MATRIX *CholeskyDecompositionIndirect( spA )
MATRIX *spA;
#endif /* End case not STDC */
{
double     dSum;
int  ii, ij, ik;

    /* [a] : Check Input matrix [A] */

       if( spA == NULL )
           FatalError("In CholeskyDecompositionIndirect() : Pointer to matrix is NULL",
                     (char *) NULL);

       if( spA->eType != DOUBLE_ARRAY ) 
           FatalError("In CholeskyDecompositionIndirect() : spA->eType != DOUBLE_ARRAY",
                     (char *) NULL);

       if( spA->eRep != INDIRECT ) 
           FatalError("In CholeskyDecompositionIndirect() : spA->eRep != INDIRECT",
                     (char *) NULL);

    /* [c] : Compute [A] = [L][L]^T */

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

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

                if(spA->uMatrix.daa[ ii-1 ][ ii-1 ] > dSum)
                   spA->uMatrix.daa[ii-1][ii-1] = sqrt(spA->uMatrix.daa[ ii-1 ][ ii-1 ] - dSum);
                else
                   FatalError("In CholeskyDecompositionIndirect()",
                              "Matrix is not positive definite",
                              (char *) NULL);
            }

⌨️ 快捷键说明

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