1ebda224cSfranklin5 2ebda224cSfranklin5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 3ebda224cSfranklin5 4ebda224cSfranklin5 typedef struct { 5ebda224cSfranklin5 Mat A; 6ebda224cSfranklin5 Vec w,left,right,leftwork,rightwork; 7ebda224cSfranklin5 PetscScalar scale; 8ebda224cSfranklin5 } Mat_Normal; 9ebda224cSfranklin5 10ebda224cSfranklin5 #undef __FUNCT__ 11ebda224cSfranklin5 #define __FUNCT__ "MatScaleHermitian_Normal" 12ebda224cSfranklin5 PetscErrorCode MatScaleHermitian_Normal(Mat inA,PetscScalar scale) 13ebda224cSfranklin5 { 14ebda224cSfranklin5 Mat_Normal *a = (Mat_Normal*)inA->data; 15ebda224cSfranklin5 16ebda224cSfranklin5 PetscFunctionBegin; 17ebda224cSfranklin5 a->scale *= scale; 18ebda224cSfranklin5 PetscFunctionReturn(0); 19ebda224cSfranklin5 } 20ebda224cSfranklin5 21ebda224cSfranklin5 #undef __FUNCT__ 22ebda224cSfranklin5 #define __FUNCT__ "MatDiagonalScaleHermitian_Normal" 23ebda224cSfranklin5 PetscErrorCode MatDiagonalScaleHermitian_Normal(Mat inA,Vec left,Vec right) 24ebda224cSfranklin5 { 25ebda224cSfranklin5 Mat_Normal *a = (Mat_Normal*)inA->data; 26ebda224cSfranklin5 PetscErrorCode ierr; 27ebda224cSfranklin5 28ebda224cSfranklin5 PetscFunctionBegin; 29ebda224cSfranklin5 if (left) { 30ebda224cSfranklin5 if (!a->left) { 31ebda224cSfranklin5 ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); 32ebda224cSfranklin5 ierr = VecCopy(left,a->left);CHKERRQ(ierr); 33ebda224cSfranklin5 } else { 34ebda224cSfranklin5 ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); 35ebda224cSfranklin5 } 36ebda224cSfranklin5 } 37ebda224cSfranklin5 if (right) { 38ebda224cSfranklin5 if (!a->right) { 39ebda224cSfranklin5 ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); 40ebda224cSfranklin5 ierr = VecCopy(right,a->right);CHKERRQ(ierr); 41ebda224cSfranklin5 } else { 42ebda224cSfranklin5 ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); 43ebda224cSfranklin5 } 44ebda224cSfranklin5 } 45ebda224cSfranklin5 PetscFunctionReturn(0); 46ebda224cSfranklin5 } 47ebda224cSfranklin5 48ebda224cSfranklin5 #undef __FUNCT__ 49ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitian_Normal" 50ebda224cSfranklin5 PetscErrorCode MatMultHermitian_Normal(Mat N,Vec x,Vec y) 51ebda224cSfranklin5 { 52ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 53ebda224cSfranklin5 PetscErrorCode ierr; 54ebda224cSfranklin5 Vec in; 55ebda224cSfranklin5 56ebda224cSfranklin5 PetscFunctionBegin; 57ebda224cSfranklin5 in = x; 58ebda224cSfranklin5 if (Na->right) { 59ebda224cSfranklin5 if (!Na->rightwork) { 60ebda224cSfranklin5 ierr = VecDuplicate(Na->right,&Na->rightwork);CHKERRQ(ierr); 61ebda224cSfranklin5 } 62ebda224cSfranklin5 ierr = VecPointwiseMult(Na->rightwork,Na->right,in);CHKERRQ(ierr); 63ebda224cSfranklin5 in = Na->rightwork; 64ebda224cSfranklin5 } 65ebda224cSfranklin5 ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr); 66ebda224cSfranklin5 ierr = MatMultHermitianTranspose(Na->A,Na->w,y);CHKERRQ(ierr); 67ebda224cSfranklin5 if (Na->left) { 68ebda224cSfranklin5 ierr = VecPointwiseMult(y,Na->left,y);CHKERRQ(ierr); 69ebda224cSfranklin5 } 70ebda224cSfranklin5 ierr = VecScale(y,Na->scale);CHKERRQ(ierr); 71ebda224cSfranklin5 PetscFunctionReturn(0); 72ebda224cSfranklin5 } 73ebda224cSfranklin5 74ebda224cSfranklin5 #undef __FUNCT__ 75ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianAdd_Normal" 76ebda224cSfranklin5 PetscErrorCode MatMultHermitianAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3) 77ebda224cSfranklin5 { 78ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 79ebda224cSfranklin5 PetscErrorCode ierr; 80ebda224cSfranklin5 Vec in; 81ebda224cSfranklin5 82ebda224cSfranklin5 PetscFunctionBegin; 83ebda224cSfranklin5 in = v1; 84ebda224cSfranklin5 if (Na->right) { 85ebda224cSfranklin5 if (!Na->rightwork) { 86ebda224cSfranklin5 ierr = VecDuplicate(Na->right,&Na->rightwork);CHKERRQ(ierr); 87ebda224cSfranklin5 } 88ebda224cSfranklin5 ierr = VecPointwiseMult(Na->rightwork,Na->right,in);CHKERRQ(ierr); 89ebda224cSfranklin5 in = Na->rightwork; 90ebda224cSfranklin5 } 91ebda224cSfranklin5 ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr); 92ebda224cSfranklin5 ierr = VecScale(Na->w,Na->scale);CHKERRQ(ierr); 93ebda224cSfranklin5 if (Na->left) { 94ebda224cSfranklin5 ierr = MatMultHermitianTranspose(Na->A,Na->w,v3);CHKERRQ(ierr); 95ebda224cSfranklin5 ierr = VecPointwiseMult(v3,Na->left,v3);CHKERRQ(ierr); 96ebda224cSfranklin5 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 97ebda224cSfranklin5 } else { 98ebda224cSfranklin5 ierr = MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);CHKERRQ(ierr); 99ebda224cSfranklin5 } 100ebda224cSfranklin5 PetscFunctionReturn(0); 101ebda224cSfranklin5 } 102ebda224cSfranklin5 103ebda224cSfranklin5 #undef __FUNCT__ 104ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianTranspose_Normal" 105ebda224cSfranklin5 PetscErrorCode MatMultHermitianTranspose_Normal(Mat N,Vec x,Vec y) 106ebda224cSfranklin5 { 107ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 108ebda224cSfranklin5 PetscErrorCode ierr; 109ebda224cSfranklin5 Vec in; 110ebda224cSfranklin5 111ebda224cSfranklin5 PetscFunctionBegin; 112ebda224cSfranklin5 in = x; 113ebda224cSfranklin5 if (Na->left) { 114ebda224cSfranklin5 if (!Na->leftwork) { 115ebda224cSfranklin5 ierr = VecDuplicate(Na->left,&Na->leftwork);CHKERRQ(ierr); 116ebda224cSfranklin5 } 117ebda224cSfranklin5 ierr = VecPointwiseMult(Na->leftwork,Na->left,in);CHKERRQ(ierr); 118ebda224cSfranklin5 in = Na->leftwork; 119ebda224cSfranklin5 } 120ebda224cSfranklin5 ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr); 121ebda224cSfranklin5 ierr = MatMultHermitianTranspose(Na->A,Na->w,y);CHKERRQ(ierr); 122ebda224cSfranklin5 if (Na->right) { 123ebda224cSfranklin5 ierr = VecPointwiseMult(y,Na->right,y);CHKERRQ(ierr); 124ebda224cSfranklin5 } 125ebda224cSfranklin5 ierr = VecScale(y,Na->scale);CHKERRQ(ierr); 126ebda224cSfranklin5 PetscFunctionReturn(0); 127ebda224cSfranklin5 } 128ebda224cSfranklin5 129ebda224cSfranklin5 #undef __FUNCT__ 130ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianTransposeAdd_Normal" 131ebda224cSfranklin5 PetscErrorCode MatMultHermitianTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3) 132ebda224cSfranklin5 { 133ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 134ebda224cSfranklin5 PetscErrorCode ierr; 135ebda224cSfranklin5 Vec in; 136ebda224cSfranklin5 137ebda224cSfranklin5 PetscFunctionBegin; 138ebda224cSfranklin5 in = v1; 139ebda224cSfranklin5 if (Na->left) { 140ebda224cSfranklin5 if (!Na->leftwork) { 141ebda224cSfranklin5 ierr = VecDuplicate(Na->left,&Na->leftwork);CHKERRQ(ierr); 142ebda224cSfranklin5 } 143ebda224cSfranklin5 ierr = VecPointwiseMult(Na->leftwork,Na->left,in);CHKERRQ(ierr); 144ebda224cSfranklin5 in = Na->leftwork; 145ebda224cSfranklin5 } 146ebda224cSfranklin5 ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr); 147ebda224cSfranklin5 ierr = VecScale(Na->w,Na->scale);CHKERRQ(ierr); 148ebda224cSfranklin5 if (Na->right) { 149ebda224cSfranklin5 ierr = MatMultHermitianTranspose(Na->A,Na->w,v3);CHKERRQ(ierr); 150ebda224cSfranklin5 ierr = VecPointwiseMult(v3,Na->right,v3);CHKERRQ(ierr); 151ebda224cSfranklin5 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 152ebda224cSfranklin5 } else { 153ebda224cSfranklin5 ierr = MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);CHKERRQ(ierr); 154ebda224cSfranklin5 } 155ebda224cSfranklin5 PetscFunctionReturn(0); 156ebda224cSfranklin5 } 157ebda224cSfranklin5 158ebda224cSfranklin5 #undef __FUNCT__ 159ebda224cSfranklin5 #define __FUNCT__ "MatDestroyHermitian_Normal" 160ebda224cSfranklin5 PetscErrorCode MatDestroyHermitian_Normal(Mat N) 161ebda224cSfranklin5 { 162ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 163ebda224cSfranklin5 PetscErrorCode ierr; 164ebda224cSfranklin5 165ebda224cSfranklin5 PetscFunctionBegin; 166ebda224cSfranklin5 ierr = MatDestroy(&Na->A);CHKERRQ(ierr); 167ebda224cSfranklin5 ierr = VecDestroy(&Na->w);CHKERRQ(ierr); 168ebda224cSfranklin5 ierr = VecDestroy(&Na->left);CHKERRQ(ierr); 169ebda224cSfranklin5 ierr = VecDestroy(&Na->right);CHKERRQ(ierr); 170ebda224cSfranklin5 ierr = VecDestroy(&Na->leftwork);CHKERRQ(ierr); 171ebda224cSfranklin5 ierr = VecDestroy(&Na->rightwork);CHKERRQ(ierr); 172ebda224cSfranklin5 ierr = PetscFree(N->data);CHKERRQ(ierr); 173ebda224cSfranklin5 PetscFunctionReturn(0); 174ebda224cSfranklin5 } 175ebda224cSfranklin5 176ebda224cSfranklin5 /* 177ebda224cSfranklin5 Slow, nonscalable version 178ebda224cSfranklin5 */ 179ebda224cSfranklin5 #undef __FUNCT__ 180ebda224cSfranklin5 #define __FUNCT__ "MatGetDiagonalHermitian_Normal" 181ebda224cSfranklin5 PetscErrorCode MatGetDiagonalHermitian_Normal(Mat N,Vec v) 182ebda224cSfranklin5 { 183ebda224cSfranklin5 Mat_Normal *Na = (Mat_Normal*)N->data; 184ebda224cSfranklin5 Mat A = Na->A; 185ebda224cSfranklin5 PetscErrorCode ierr; 186ebda224cSfranklin5 PetscInt i,j,rstart,rend,nnz; 187ebda224cSfranklin5 const PetscInt *cols; 188ebda224cSfranklin5 PetscScalar *diag,*work,*values; 189ebda224cSfranklin5 const PetscScalar *mvalues; 190ebda224cSfranklin5 191ebda224cSfranklin5 PetscFunctionBegin; 192ebda224cSfranklin5 ierr = PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work);CHKERRQ(ierr); 193ebda224cSfranklin5 ierr = PetscMemzero(work,A->cmap->N*sizeof(PetscScalar));CHKERRQ(ierr); 194ebda224cSfranklin5 ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); 195ebda224cSfranklin5 for (i=rstart; i<rend; i++) { 196ebda224cSfranklin5 ierr = MatGetRow(A,i,&nnz,&cols,&mvalues);CHKERRQ(ierr); 197ebda224cSfranklin5 for (j=0; j<nnz; j++) { 198a8f6171dSBarry Smith work[cols[j]] += mvalues[j]*PetscConj(mvalues[j]); 199ebda224cSfranklin5 } 200ebda224cSfranklin5 ierr = MatRestoreRow(A,i,&nnz,&cols,&mvalues);CHKERRQ(ierr); 201ebda224cSfranklin5 } 202*b2566f29SBarry Smith ierr = MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N));CHKERRQ(ierr); 203ebda224cSfranklin5 rstart = N->cmap->rstart; 204ebda224cSfranklin5 rend = N->cmap->rend; 205ebda224cSfranklin5 ierr = VecGetArray(v,&values);CHKERRQ(ierr); 206ebda224cSfranklin5 ierr = PetscMemcpy(values,diag+rstart,(rend-rstart)*sizeof(PetscScalar));CHKERRQ(ierr); 207ebda224cSfranklin5 ierr = VecRestoreArray(v,&values);CHKERRQ(ierr); 208ebda224cSfranklin5 ierr = PetscFree2(diag,work);CHKERRQ(ierr); 209ebda224cSfranklin5 ierr = VecScale(v,Na->scale);CHKERRQ(ierr); 210ebda224cSfranklin5 PetscFunctionReturn(0); 211ebda224cSfranklin5 } 212ebda224cSfranklin5 213ebda224cSfranklin5 #undef __FUNCT__ 214ebda224cSfranklin5 #define __FUNCT__ "MatCreateNormalHermitian" 215ebda224cSfranklin5 /*@ 216ebda224cSfranklin5 MatCreateNormalHermitian - Creates a new matrix object that behaves like (A*)'*A. 217ebda224cSfranklin5 218ebda224cSfranklin5 Collective on Mat 219ebda224cSfranklin5 220ebda224cSfranklin5 Input Parameter: 221ebda224cSfranklin5 . A - the (possibly rectangular complex) matrix 222ebda224cSfranklin5 223ebda224cSfranklin5 Output Parameter: 224ebda224cSfranklin5 . N - the matrix that represents (A*)'*A 225ebda224cSfranklin5 226ebda224cSfranklin5 Level: intermediate 227ebda224cSfranklin5 228ebda224cSfranklin5 Notes: The product (A*)'*A is NOT actually formed! Rather the new matrix 229ebda224cSfranklin5 object performs the matrix-vector product by first multiplying by 230ebda224cSfranklin5 A and then (A*)' 231ebda224cSfranklin5 @*/ 232ebda224cSfranklin5 PetscErrorCode MatCreateNormalHermitian(Mat A,Mat *N) 233ebda224cSfranklin5 { 234ebda224cSfranklin5 PetscErrorCode ierr; 235ebda224cSfranklin5 PetscInt m,n; 236ebda224cSfranklin5 Mat_Normal *Na; 237ebda224cSfranklin5 238ebda224cSfranklin5 PetscFunctionBegin; 239ebda224cSfranklin5 ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 240ebda224cSfranklin5 ierr = MatCreate(PetscObjectComm((PetscObject)A),N);CHKERRQ(ierr); 241ebda224cSfranklin5 ierr = MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 242ebda224cSfranklin5 ierr = PetscObjectChangeTypeName((PetscObject)*N,MATNORMALHERMITIAN);CHKERRQ(ierr); 243ebda224cSfranklin5 244ebda224cSfranklin5 ierr = PetscNewLog(*N,&Na);CHKERRQ(ierr); 245ebda224cSfranklin5 (*N)->data = (void*) Na; 246ebda224cSfranklin5 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 247ebda224cSfranklin5 Na->A = A; 248ebda224cSfranklin5 Na->scale = 1.0; 249ebda224cSfranklin5 250ebda224cSfranklin5 ierr = VecCreateMPI(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,&Na->w);CHKERRQ(ierr); 251ebda224cSfranklin5 252ebda224cSfranklin5 (*N)->ops->destroy = MatDestroyHermitian_Normal; 253ebda224cSfranklin5 (*N)->ops->mult = MatMultHermitian_Normal; 254ebda224cSfranklin5 (*N)->ops->multtranspose = MatMultHermitianTranspose_Normal; 255ebda224cSfranklin5 (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_Normal; 256ebda224cSfranklin5 (*N)->ops->multadd = MatMultHermitianAdd_Normal; 257ebda224cSfranklin5 (*N)->ops->getdiagonal = MatGetDiagonalHermitian_Normal; 258ebda224cSfranklin5 (*N)->ops->scale = MatScaleHermitian_Normal; 259ebda224cSfranklin5 (*N)->ops->diagonalscale = MatDiagonalScaleHermitian_Normal; 260ebda224cSfranklin5 (*N)->assembled = PETSC_TRUE; 261ebda224cSfranklin5 (*N)->cmap->N = A->cmap->N; 262ebda224cSfranklin5 (*N)->rmap->N = A->cmap->N; 263ebda224cSfranklin5 (*N)->cmap->n = A->cmap->n; 264ebda224cSfranklin5 (*N)->rmap->n = A->cmap->n; 265ebda224cSfranklin5 PetscFunctionReturn(0); 266ebda224cSfranklin5 } 267ebda224cSfranklin5 268