Date: 2022-08-02T03:13:55+00:00

Actual source code: cdiagonal.c

      2: #include <petsc/private/matimpl.h>

      4: typedef struct {
      5:   PetscScalar diag;
      6: } Mat_ConstantDiagonal;

      8: static PetscErrorCode MatAXPY_ConstantDiagonal(Mat Y, PetscScalar a, Mat X, MatStructure str)
      9: {
     10:   Mat_ConstantDiagonal *yctx = (Mat_ConstantDiagonal*)Y->data;
     11:   Mat_ConstantDiagonal *xctx = (Mat_ConstantDiagonal*)X->data;

     13:   yctx->diag += a*xctx->diag;
     14:   return 0;
     15: }

     17: static PetscErrorCode MatGetRow_ConstantDiagonal(Mat A, PetscInt row, PetscInt *ncols, PetscInt *cols[], PetscScalar *vals[])
     18: {
     19:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)A->data;

     21:   if (ncols) *ncols = 1;
     22:   if (cols) {
     23:     PetscMalloc1(1,cols);
     24:     (*cols)[0] = row;
     25:   }
     26:   if (vals) {
     27:     PetscMalloc1(1,vals);
     28:     (*vals)[0] = ctx->diag;
     29:   }
     30:   return 0;
     31: }

     33: static PetscErrorCode MatRestoreRow_ConstantDiagonal(Mat A, PetscInt row, PetscInt *ncols, PetscInt *cols[], PetscScalar *vals[])
     34: {
     35:   if (ncols) *ncols = 0;
     36:   if (cols) {
     37:     PetscFree(*cols);
     38:   }
     39:   if (vals) {
     40:     PetscFree(*vals);
     41:   }
     42:   return 0;
     43: }

     45: static PetscErrorCode MatMultTranspose_ConstantDiagonal(Mat A, Vec x, Vec y)
     46: {
     47:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)A->data;

     49:   VecAXPBY(y,ctx->diag,0.0,x);
     50:   return 0;
     51: }

     53: static PetscErrorCode MatMultAdd_ConstantDiagonal(Mat mat,Vec v1,Vec v2,Vec v3)
     54: {
     55:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)mat->data;

     57:   if (v2 == v3) {
     58:     VecAXPBY(v3,ctx->diag,1.0,v1);
     59:   } else {
     60:     VecAXPBYPCZ(v3,ctx->diag,1.0,0.0,v1,v2);
     61:   }
     62:   return 0;
     63: }

     65: static PetscErrorCode MatMultTransposeAdd_ConstantDiagonal(Mat mat,Vec v1,Vec v2,Vec v3)
     66: {
     67:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)mat->data;

     69:   if (v2 == v3) {
     70:     VecAXPBY(v3,ctx->diag,1.0,v1);
     71:   } else {
     72:     VecAXPBYPCZ(v3,ctx->diag,1.0,0.0,v1,v2);
     73:   }
     74:   return 0;
     75: }

     77: static PetscErrorCode MatNorm_ConstantDiagonal(Mat A,NormType type,PetscReal *nrm)
     78: {
     79:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)A->data;

     81:   if (type == NORM_FROBENIUS || type == NORM_2 || type == NORM_1 || type == NORM_INFINITY) *nrm = PetscAbsScalar(ctx->diag);
     82:   else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported norm");
     83:   return 0;
     84: }

     86: static PetscErrorCode MatCreateSubMatrices_ConstantDiagonal(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])

     88: {
     89:   Mat            B;

     91:   MatConvert(A,MATAIJ,MAT_INITIAL_MATRIX,&B);
     92:   MatCreateSubMatrices(B,n,irow,icol,scall,submat);
     93:   MatDestroy(&B);
     94:   return 0;
     95: }

     97: static PetscErrorCode MatDuplicate_ConstantDiagonal(Mat A, MatDuplicateOption op, Mat *B)
     98: {
     99:   Mat_ConstantDiagonal *actx = (Mat_ConstantDiagonal*)A->data;

    101:   MatCreate(PetscObjectComm((PetscObject)A),B);
    102:   MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);
    103:   MatSetBlockSizesFromMats(*B,A,A);
    104:   MatSetType(*B,MATCONSTANTDIAGONAL);
    105:   PetscLayoutReference(A->rmap,&(*B)->rmap);
    106:   PetscLayoutReference(A->cmap,&(*B)->cmap);
    107:   if (op == MAT_COPY_VALUES) {
    108:     Mat_ConstantDiagonal *bctx = (Mat_ConstantDiagonal*)(*B)->data;
    109:     bctx->diag = actx->diag;
    110:   }
    111:   return 0;
    112: }

    114: static PetscErrorCode MatMissingDiagonal_ConstantDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
    115: {
    116:   *missing = PETSC_FALSE;
    117:   return 0;
    118: }

    120: static PetscErrorCode MatDestroy_ConstantDiagonal(Mat mat)
    121: {
    122:   PetscFree(mat->data);
    123:   return 0;
    124: }

    126: static PetscErrorCode MatView_ConstantDiagonal(Mat J,PetscViewer viewer)
    127: {
    128:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)J->data;
    129:   PetscBool            iascii;

    131:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    132:   if (iascii) {
    133:     PetscViewerFormat    format;

    135:     PetscViewerGetFormat(viewer,&format);
    136:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) return 0;
    137: #if defined(PETSC_USE_COMPLEX)
    138:     PetscViewerASCIIPrintf(viewer,"Diagonal value: %g + i %g\n",(double)PetscRealPart(ctx->diag),(double)PetscImaginaryPart(ctx->diag));
    139: #else
    140:     PetscViewerASCIIPrintf(viewer,"Diagonal value: %g\n",(double)(ctx->diag));
    141: #endif
    142:   }
    143:   return 0;
    144: }

    146: static PetscErrorCode MatAssemblyEnd_ConstantDiagonal(Mat J,MatAssemblyType mt)
    147: {
    148:   return 0;
    149: }

    151: static PetscErrorCode MatMult_ConstantDiagonal(Mat J,Vec x,Vec y)
    152: {
    153:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)J->data;

    155:   VecAXPBY(y,ctx->diag,0.0,x);
    156:   return 0;
    157: }

    159: PetscErrorCode MatGetDiagonal_ConstantDiagonal(Mat J,Vec x)
    160: {
    161:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)J->data;

    163:   VecSet(x,ctx->diag);
    164:   return 0;
    165: }

    167: static PetscErrorCode MatShift_ConstantDiagonal(Mat Y,PetscScalar a)
    168: {
    169:   Mat_ConstantDiagonal *ctx = (Mat_ConstantDiagonal*)Y->data;

    171:   ctx->diag += a;
    172:   return 0;
    173: }

    175: static PetscErrorCode MatScale_ConstantDiagonal(Mat Y,PetscScalar a)
    176: {
    177:   Mat_ConstantDiagonal *ctx  = (Mat_ConstantDiagonal*)Y->data;

    179:   ctx->diag *= a;
    180:   return 0;
    181: }

    183: static PetscErrorCode MatZeroEntries_ConstantDiagonal(Mat Y)
    184: {
    185:   Mat_ConstantDiagonal *ctx  = (Mat_ConstantDiagonal*)Y->data;

    187:   ctx->diag = 0.0;
    188:   return 0;
    189: }

    191: PetscErrorCode MatSOR_ConstantDiagonal(Mat matin,Vec x,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec y)
    192: {
    193:   Mat_ConstantDiagonal *ctx  = (Mat_ConstantDiagonal*)matin->data;

    195:   if (ctx->diag == 0.0) matin->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
    196:   else matin->factorerrortype = MAT_FACTOR_NOERROR;
    197:   VecAXPBY(y,1.0/ctx->diag,0.0,x);
    198:   return 0;
    199: }

    201: PetscErrorCode MatGetInfo_ConstantDiagonal(Mat A,MatInfoType flag,MatInfo *info)
    202: {
    203:   info->block_size   = 1.0;
    204:   info->nz_allocated = 1.0;
    205:   info->nz_used      = 1.0;
    206:   info->nz_unneeded  = 0.0;
    207:   info->assemblies   = A->num_ass;
    208:   info->mallocs      = 0.0;
    209:   info->memory       = ((PetscObject)A)->mem;
    210:   if (A->factortype) {
    211:     info->fill_ratio_given  = 1.0;
    212:     info->fill_ratio_needed = 1.0;
    213:     info->factor_mallocs    = 0.0;
    214:   } else {
    215:     info->fill_ratio_given  = 0;
    216:     info->fill_ratio_needed = 0;
    217:     info->factor_mallocs    = 0;
    218:   }
    219:   return 0;
    220: }

    222: /*@
    223:    MatCreateConstantDiagonal - Creates a matrix with a uniform value along the diagonal

    225:    Collective

    227:    Input Parameters:
    228: +  comm - MPI communicator
    229: .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
    230:            This value should be the same as the local size used in creating the
    231:            y vector for the matrix-vector product y = Ax.
    232: .  n - This value should be the same as the local size used in creating the
    233:        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
    234:        calculated if N is given) For square matrices n is almost always m.
    235: .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
    236: .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
    237: -  diag - the diagonal value

    239:    Output Parameter:
    240: .  J - the diagonal matrix

    242:    Level: advanced

    244:    Notes:
    245:     Only supports square matrices with the same number of local rows and columns

    247: .seealso: MatDestroy(), MATCONSTANTDIAGONAL, MatScale(), MatShift(), MatMult(), MatGetDiagonal(), MatGetFactor(), MatSolve()

    249: @*/
    250: PetscErrorCode  MatCreateConstantDiagonal(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscScalar diag,Mat *J)
    251: {
    252:   MatCreate(comm,J);
    253:   MatSetSizes(*J,m,n,M,N);
    254:   MatSetType(*J,MATCONSTANTDIAGONAL);
    255:   MatShift(*J,diag);
    256:   MatSetUp(*J);
    257:   return 0;
    258: }

    260: PETSC_EXTERN PetscErrorCode  MatCreate_ConstantDiagonal(Mat A)
    261: {
    262:   Mat_ConstantDiagonal *ctx;

    264:   PetscNew(&ctx);
    265:   ctx->diag = 0.0;
    266:   A->data   = (void*)ctx;

    268:   A->assembled    = PETSC_TRUE;
    269:   A->preallocated = PETSC_TRUE;

    271:   A->ops->mult             = MatMult_ConstantDiagonal;
    272:   A->ops->multadd          = MatMultAdd_ConstantDiagonal;
    273:   A->ops->multtranspose    = MatMultTranspose_ConstantDiagonal;
    274:   A->ops->multtransposeadd = MatMultTransposeAdd_ConstantDiagonal;
    275:   A->ops->norm             = MatNorm_ConstantDiagonal;
    276:   A->ops->createsubmatrices= MatCreateSubMatrices_ConstantDiagonal;
    277:   A->ops->duplicate        = MatDuplicate_ConstantDiagonal;
    278:   A->ops->missingdiagonal  = MatMissingDiagonal_ConstantDiagonal;
    279:   A->ops->getrow           = MatGetRow_ConstantDiagonal;
    280:   A->ops->restorerow       = MatRestoreRow_ConstantDiagonal;
    281:   A->ops->sor              = MatSOR_ConstantDiagonal;
    282:   A->ops->shift            = MatShift_ConstantDiagonal;
    283:   A->ops->scale            = MatScale_ConstantDiagonal;
    284:   A->ops->getdiagonal      = MatGetDiagonal_ConstantDiagonal;
    285:   A->ops->view             = MatView_ConstantDiagonal;
    286:   A->ops->zeroentries      = MatZeroEntries_ConstantDiagonal;
    287:   A->ops->assemblyend      = MatAssemblyEnd_ConstantDiagonal;
    288:   A->ops->destroy          = MatDestroy_ConstantDiagonal;
    289:   A->ops->getinfo          = MatGetInfo_ConstantDiagonal;
    290:   A->ops->axpy             = MatAXPY_ConstantDiagonal;

    292:   PetscObjectChangeTypeName((PetscObject)A,MATCONSTANTDIAGONAL);
    293:   return 0;
    294: }

    296: static PetscErrorCode MatFactorNumeric_ConstantDiagonal(Mat fact,Mat A,const MatFactorInfo *info)
    297: {
    298:   Mat_ConstantDiagonal *actx = (Mat_ConstantDiagonal*)A->data,*fctx = (Mat_ConstantDiagonal*)fact->data;

    300:   if (actx->diag == 0.0) fact->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
    301:   else fact->factorerrortype = MAT_FACTOR_NOERROR;
    302:   fctx->diag = 1.0/actx->diag;
    303:   fact->ops->solve = MatMult_ConstantDiagonal;
    304:   return 0;
    305: }

    307: static PetscErrorCode MatFactorSymbolic_LU_ConstantDiagonal(Mat fact,Mat A,IS isrow,IS iscol,const MatFactorInfo *info)
    308: {
    309:   fact->ops->lufactornumeric = MatFactorNumeric_ConstantDiagonal;
    310:   return 0;
    311: }

    313: static PetscErrorCode MatFactorSymbolic_Cholesky_ConstantDiagonal(Mat fact,Mat A,IS isrow,const MatFactorInfo *info)
    314: {
    315:   fact->ops->choleskyfactornumeric = MatFactorNumeric_ConstantDiagonal;
    316:   return 0;
    317: }

    319: PETSC_INTERN PetscErrorCode MatGetFactor_constantdiagonal_petsc(Mat A,MatFactorType ftype,Mat *B)
    320: {
    321:   PetscInt       n = A->rmap->n, N = A->rmap->N;

    323:   MatCreateConstantDiagonal(PetscObjectComm((PetscObject)A),n,n,N,N,0,B);

    325:   (*B)->factortype = ftype;
    326:   (*B)->ops->ilufactorsymbolic      = MatFactorSymbolic_LU_ConstantDiagonal;
    327:   (*B)->ops->lufactorsymbolic       = MatFactorSymbolic_LU_ConstantDiagonal;
    328:   (*B)->ops->iccfactorsymbolic      = MatFactorSymbolic_Cholesky_ConstantDiagonal;
    329:   (*B)->ops->choleskyfactorsymbolic = MatFactorSymbolic_Cholesky_ConstantDiagonal;

    331:   (*B)->ops->shift       = NULL;
    332:   (*B)->ops->scale       = NULL;
    333:   (*B)->ops->mult        = NULL;
    334:   (*B)->ops->sor         = NULL;
    335:   (*B)->ops->zeroentries = NULL;

    337:   PetscFree((*B)->solvertype);
    338:   PetscStrallocpy(MATSOLVERPETSC,&(*B)->solvertype);
    339:   return 0;
    340: }