1 2 /* 3 Defines the basic matrix operations for sequential dense. 4 */ 5 6 #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/ 7 #include <petscblaslapack.h> 8 9 #include <../src/mat/impls/aij/seq/aij.h> 10 11 static PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian) 12 { 13 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 14 PetscInt j, k, n = A->rmap->n; 15 16 PetscFunctionBegin; 17 if (A->rmap->n != A->cmap->n) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot symmetrize a rectangular matrix"); 18 if (!hermitian) { 19 for (k=0;k<n;k++) { 20 for (j=k;j<n;j++) { 21 mat->v[j*mat->lda + k] = mat->v[k*mat->lda + j]; 22 } 23 } 24 } else { 25 for (k=0;k<n;k++) { 26 for (j=k;j<n;j++) { 27 mat->v[j*mat->lda + k] = PetscConj(mat->v[k*mat->lda + j]); 28 } 29 } 30 } 31 PetscFunctionReturn(0); 32 } 33 34 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A) 35 { 36 #if defined(PETSC_MISSING_LAPACK_POTRF) 37 PetscFunctionBegin; 38 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable."); 39 #else 40 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 41 PetscErrorCode ierr; 42 PetscBLASInt info,n; 43 44 PetscFunctionBegin; 45 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 46 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 47 if (A->factortype == MAT_FACTOR_LU) { 48 if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present"); 49 if (!mat->fwork) { 50 mat->lfwork = n; 51 ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr); 52 ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr); 53 } 54 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 55 PetscStackCallBLAS("LAPACKgetri",LAPACKgetri_(&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info)); 56 ierr = PetscFPTrapPop();CHKERRQ(ierr); 57 ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr); /* TODO CHECK FLOPS */ 58 } else if (A->factortype == MAT_FACTOR_CHOLESKY) { 59 if (A->spd) { 60 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 61 PetscStackCallBLAS("LAPACKpotri",LAPACKpotri_("L",&n,mat->v,&mat->lda,&info)); 62 ierr = PetscFPTrapPop();CHKERRQ(ierr); 63 ierr = MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);CHKERRQ(ierr); 64 #if defined(PETSC_USE_COMPLEX) 65 } else if (A->hermitian) { 66 if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present"); 67 if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present"); 68 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 69 PetscStackCallBLAS("LAPACKhetri",LAPACKhetri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info)); 70 ierr = PetscFPTrapPop();CHKERRQ(ierr); 71 ierr = MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);CHKERRQ(ierr); 72 #endif 73 } else { /* symmetric case */ 74 if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present"); 75 if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present"); 76 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 77 PetscStackCallBLAS("LAPACKsytri",LAPACKsytri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info)); 78 ierr = PetscFPTrapPop();CHKERRQ(ierr); 79 ierr = MatSeqDenseSymmetrize_Private(A,PETSC_FALSE);CHKERRQ(ierr); 80 } 81 if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad Inversion: zero pivot in row %D",(PetscInt)info-1); 82 ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr); /* TODO CHECK FLOPS */ 83 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve"); 84 #endif 85 86 A->ops->solve = NULL; 87 A->ops->matsolve = NULL; 88 A->ops->solvetranspose = NULL; 89 A->ops->matsolvetranspose = NULL; 90 A->ops->solveadd = NULL; 91 A->ops->solvetransposeadd = NULL; 92 A->factortype = MAT_FACTOR_NONE; 93 ierr = PetscFree(A->solvertype);CHKERRQ(ierr); 94 PetscFunctionReturn(0); 95 } 96 97 PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 98 { 99 PetscErrorCode ierr; 100 Mat_SeqDense *l = (Mat_SeqDense*)A->data; 101 PetscInt m = l->lda, n = A->cmap->n,r = A->rmap->n, i,j; 102 PetscScalar *slot,*bb; 103 const PetscScalar *xx; 104 105 PetscFunctionBegin; 106 #if defined(PETSC_USE_DEBUG) 107 for (i=0; i<N; i++) { 108 if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed"); 109 if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n); 110 if (rows[i] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Col %D requested to be zeroed greater than or equal number of cols %D",rows[i],A->cmap->n); 111 } 112 #endif 113 114 /* fix right hand side if needed */ 115 if (x && b) { 116 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 117 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 118 for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]]; 119 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 120 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 121 } 122 123 for (i=0; i<N; i++) { 124 slot = l->v + rows[i]*m; 125 ierr = PetscMemzero(slot,r*sizeof(PetscScalar));CHKERRQ(ierr); 126 } 127 for (i=0; i<N; i++) { 128 slot = l->v + rows[i]; 129 for (j=0; j<n; j++) { *slot = 0.0; slot += m;} 130 } 131 if (diag != 0.0) { 132 if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices"); 133 for (i=0; i<N; i++) { 134 slot = l->v + (m+1)*rows[i]; 135 *slot = diag; 136 } 137 } 138 PetscFunctionReturn(0); 139 } 140 141 PetscErrorCode MatPtAPNumeric_SeqDense_SeqDense(Mat A,Mat P,Mat C) 142 { 143 Mat_SeqDense *c = (Mat_SeqDense*)(C->data); 144 PetscErrorCode ierr; 145 146 PetscFunctionBegin; 147 ierr = MatMatMultNumeric_SeqDense_SeqDense(A,P,c->ptapwork);CHKERRQ(ierr); 148 ierr = MatTransposeMatMultNumeric_SeqDense_SeqDense(P,c->ptapwork,C);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 PetscErrorCode MatPtAPSymbolic_SeqDense_SeqDense(Mat A,Mat P,PetscReal fill,Mat *C) 153 { 154 Mat_SeqDense *c; 155 PetscErrorCode ierr; 156 157 PetscFunctionBegin; 158 ierr = MatCreateSeqDense(PetscObjectComm((PetscObject)A),P->cmap->N,P->cmap->N,NULL,C);CHKERRQ(ierr); 159 c = (Mat_SeqDense*)((*C)->data); 160 ierr = MatCreateSeqDense(PetscObjectComm((PetscObject)A),A->rmap->N,P->cmap->N,NULL,&c->ptapwork);CHKERRQ(ierr); 161 PetscFunctionReturn(0); 162 } 163 164 PETSC_INTERN PetscErrorCode MatPtAP_SeqDense_SeqDense(Mat A,Mat P,MatReuse reuse,PetscReal fill,Mat *C) 165 { 166 PetscErrorCode ierr; 167 168 PetscFunctionBegin; 169 if (reuse == MAT_INITIAL_MATRIX) { 170 ierr = MatPtAPSymbolic_SeqDense_SeqDense(A,P,fill,C);CHKERRQ(ierr); 171 } 172 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 173 ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 174 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 175 PetscFunctionReturn(0); 176 } 177 178 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 179 { 180 Mat B = NULL; 181 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 182 Mat_SeqDense *b; 183 PetscErrorCode ierr; 184 PetscInt *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->N,i; 185 MatScalar *av=a->a; 186 PetscBool isseqdense; 187 188 PetscFunctionBegin; 189 if (reuse == MAT_REUSE_MATRIX) { 190 ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); 191 if (!isseqdense) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type); 192 } 193 if (reuse != MAT_REUSE_MATRIX) { 194 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 195 ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr); 196 ierr = MatSetType(B,MATSEQDENSE);CHKERRQ(ierr); 197 ierr = MatSeqDenseSetPreallocation(B,NULL);CHKERRQ(ierr); 198 b = (Mat_SeqDense*)(B->data); 199 } else { 200 b = (Mat_SeqDense*)((*newmat)->data); 201 ierr = PetscMemzero(b->v,m*n*sizeof(PetscScalar));CHKERRQ(ierr); 202 } 203 for (i=0; i<m; i++) { 204 PetscInt j; 205 for (j=0;j<ai[1]-ai[0];j++) { 206 b->v[*aj*m+i] = *av; 207 aj++; 208 av++; 209 } 210 ai++; 211 } 212 213 if (reuse == MAT_INPLACE_MATRIX) { 214 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 215 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 216 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 217 } else { 218 if (B) *newmat = B; 219 ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 220 ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 221 } 222 PetscFunctionReturn(0); 223 } 224 225 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 226 { 227 Mat B; 228 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 229 PetscErrorCode ierr; 230 PetscInt i, j; 231 PetscInt *rows, *nnz; 232 MatScalar *aa = a->v, *vals; 233 234 PetscFunctionBegin; 235 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 236 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 237 ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 238 ierr = PetscCalloc3(A->rmap->n,&rows,A->rmap->n,&nnz,A->rmap->n,&vals);CHKERRQ(ierr); 239 for (j=0; j<A->cmap->n; j++) { 240 for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) ++nnz[i]; 241 aa += a->lda; 242 } 243 ierr = MatSeqAIJSetPreallocation(B,PETSC_DETERMINE,nnz);CHKERRQ(ierr); 244 aa = a->v; 245 for (j=0; j<A->cmap->n; j++) { 246 PetscInt numRows = 0; 247 for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) {rows[numRows] = i; vals[numRows++] = aa[i];} 248 ierr = MatSetValues(B,numRows,rows,1,&j,vals,INSERT_VALUES);CHKERRQ(ierr); 249 aa += a->lda; 250 } 251 ierr = PetscFree3(rows,nnz,vals);CHKERRQ(ierr); 252 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 253 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 254 255 if (reuse == MAT_INPLACE_MATRIX) { 256 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 257 } else { 258 *newmat = B; 259 } 260 PetscFunctionReturn(0); 261 } 262 263 static PetscErrorCode MatAXPY_SeqDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str) 264 { 265 Mat_SeqDense *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data; 266 PetscScalar oalpha = alpha; 267 PetscInt j; 268 PetscBLASInt N,m,ldax,lday,one = 1; 269 PetscErrorCode ierr; 270 271 PetscFunctionBegin; 272 ierr = PetscBLASIntCast(X->rmap->n*X->cmap->n,&N);CHKERRQ(ierr); 273 ierr = PetscBLASIntCast(X->rmap->n,&m);CHKERRQ(ierr); 274 ierr = PetscBLASIntCast(x->lda,&ldax);CHKERRQ(ierr); 275 ierr = PetscBLASIntCast(y->lda,&lday);CHKERRQ(ierr); 276 if (ldax>m || lday>m) { 277 for (j=0; j<X->cmap->n; j++) { 278 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&m,&oalpha,x->v+j*ldax,&one,y->v+j*lday,&one)); 279 } 280 } else { 281 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&N,&oalpha,x->v,&one,y->v,&one)); 282 } 283 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 284 ierr = PetscLogFlops(PetscMax(2*N-1,0));CHKERRQ(ierr); 285 PetscFunctionReturn(0); 286 } 287 288 static PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info) 289 { 290 PetscInt N = A->rmap->n*A->cmap->n; 291 292 PetscFunctionBegin; 293 info->block_size = 1.0; 294 info->nz_allocated = (double)N; 295 info->nz_used = (double)N; 296 info->nz_unneeded = (double)0; 297 info->assemblies = (double)A->num_ass; 298 info->mallocs = 0; 299 info->memory = ((PetscObject)A)->mem; 300 info->fill_ratio_given = 0; 301 info->fill_ratio_needed = 0; 302 info->factor_mallocs = 0; 303 PetscFunctionReturn(0); 304 } 305 306 static PetscErrorCode MatScale_SeqDense(Mat A,PetscScalar alpha) 307 { 308 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 309 PetscScalar oalpha = alpha; 310 PetscErrorCode ierr; 311 PetscBLASInt one = 1,j,nz,lda; 312 313 PetscFunctionBegin; 314 ierr = PetscBLASIntCast(a->lda,&lda);CHKERRQ(ierr); 315 if (lda>A->rmap->n) { 316 ierr = PetscBLASIntCast(A->rmap->n,&nz);CHKERRQ(ierr); 317 for (j=0; j<A->cmap->n; j++) { 318 PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v+j*lda,&one)); 319 } 320 } else { 321 ierr = PetscBLASIntCast(A->rmap->n*A->cmap->n,&nz);CHKERRQ(ierr); 322 PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v,&one)); 323 } 324 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 325 PetscFunctionReturn(0); 326 } 327 328 static PetscErrorCode MatIsHermitian_SeqDense(Mat A,PetscReal rtol,PetscBool *fl) 329 { 330 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 331 PetscInt i,j,m = A->rmap->n,N; 332 PetscScalar *v = a->v; 333 334 PetscFunctionBegin; 335 *fl = PETSC_FALSE; 336 if (A->rmap->n != A->cmap->n) PetscFunctionReturn(0); 337 N = a->lda; 338 339 for (i=0; i<m; i++) { 340 for (j=i+1; j<m; j++) { 341 if (PetscAbsScalar(v[i+j*N] - PetscConj(v[j+i*N])) > rtol) PetscFunctionReturn(0); 342 } 343 } 344 *fl = PETSC_TRUE; 345 PetscFunctionReturn(0); 346 } 347 348 static PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi,Mat A,MatDuplicateOption cpvalues) 349 { 350 Mat_SeqDense *mat = (Mat_SeqDense*)A->data,*l; 351 PetscErrorCode ierr; 352 PetscInt lda = (PetscInt)mat->lda,j,m; 353 354 PetscFunctionBegin; 355 ierr = PetscLayoutReference(A->rmap,&newi->rmap);CHKERRQ(ierr); 356 ierr = PetscLayoutReference(A->cmap,&newi->cmap);CHKERRQ(ierr); 357 ierr = MatSeqDenseSetPreallocation(newi,NULL);CHKERRQ(ierr); 358 if (cpvalues == MAT_COPY_VALUES) { 359 l = (Mat_SeqDense*)newi->data; 360 if (lda>A->rmap->n) { 361 m = A->rmap->n; 362 for (j=0; j<A->cmap->n; j++) { 363 ierr = PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr); 364 } 365 } else { 366 ierr = PetscMemcpy(l->v,mat->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 367 } 368 } 369 newi->assembled = PETSC_TRUE; 370 PetscFunctionReturn(0); 371 } 372 373 static PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat) 374 { 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 ierr = MatCreate(PetscObjectComm((PetscObject)A),newmat);CHKERRQ(ierr); 379 ierr = MatSetSizes(*newmat,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 380 ierr = MatSetType(*newmat,((PetscObject)A)->type_name);CHKERRQ(ierr); 381 ierr = MatDuplicateNoCreate_SeqDense(*newmat,A,cpvalues);CHKERRQ(ierr); 382 PetscFunctionReturn(0); 383 } 384 385 386 static PetscErrorCode MatLUFactor_SeqDense(Mat,IS,IS,const MatFactorInfo*); 387 388 static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy) 389 { 390 MatFactorInfo info; 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr); 395 ierr = MatLUFactor_SeqDense(fact,0,0,&info);CHKERRQ(ierr); 396 PetscFunctionReturn(0); 397 } 398 399 static PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy) 400 { 401 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 402 PetscErrorCode ierr; 403 const PetscScalar *x; 404 PetscScalar *y; 405 PetscBLASInt one = 1,info,m; 406 407 PetscFunctionBegin; 408 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 409 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 410 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 411 ierr = PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 412 if (A->factortype == MAT_FACTOR_LU) { 413 #if defined(PETSC_MISSING_LAPACK_GETRS) 414 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 415 #else 416 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 417 PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 418 ierr = PetscFPTrapPop();CHKERRQ(ierr); 419 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve"); 420 #endif 421 } else if (A->factortype == MAT_FACTOR_CHOLESKY) { 422 #if defined(PETSC_MISSING_LAPACK_POTRS) 423 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 424 #else 425 if (A->spd) { 426 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 427 PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info)); 428 ierr = PetscFPTrapPop();CHKERRQ(ierr); 429 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve"); 430 #if defined(PETSC_USE_COMPLEX) 431 } else if (A->hermitian) { 432 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 433 PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 434 ierr = PetscFPTrapPop();CHKERRQ(ierr); 435 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve"); 436 #endif 437 } else { /* symmetric case */ 438 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 439 PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 440 ierr = PetscFPTrapPop();CHKERRQ(ierr); 441 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve"); 442 } 443 #endif 444 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve"); 445 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 446 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 447 ierr = PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr); 448 PetscFunctionReturn(0); 449 } 450 451 static PetscErrorCode MatMatSolve_SeqDense(Mat A,Mat B,Mat X) 452 { 453 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 454 PetscErrorCode ierr; 455 PetscScalar *b,*x; 456 PetscInt n; 457 PetscBLASInt nrhs,info,m; 458 PetscBool flg; 459 460 PetscFunctionBegin; 461 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 462 ierr = PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); 463 if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix"); 464 ierr = PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); 465 if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix"); 466 467 ierr = MatGetSize(B,NULL,&n);CHKERRQ(ierr); 468 ierr = PetscBLASIntCast(n,&nrhs);CHKERRQ(ierr); 469 ierr = MatDenseGetArray(B,&b);CHKERRQ(ierr); 470 ierr = MatDenseGetArray(X,&x);CHKERRQ(ierr); 471 472 ierr = PetscMemcpy(x,b,m*nrhs*sizeof(PetscScalar));CHKERRQ(ierr); 473 474 if (A->factortype == MAT_FACTOR_LU) { 475 #if defined(PETSC_MISSING_LAPACK_GETRS) 476 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 477 #else 478 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 479 PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info)); 480 ierr = PetscFPTrapPop();CHKERRQ(ierr); 481 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve"); 482 #endif 483 } else if (A->factortype == MAT_FACTOR_CHOLESKY) { 484 #if defined(PETSC_MISSING_LAPACK_POTRS) 485 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 486 #else 487 if (A->spd) { 488 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 489 PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&nrhs,mat->v,&mat->lda,x,&m,&info)); 490 ierr = PetscFPTrapPop();CHKERRQ(ierr); 491 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve"); 492 #if defined(PETSC_USE_COMPLEX) 493 } else if (A->hermitian) { 494 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 495 PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info)); 496 ierr = PetscFPTrapPop();CHKERRQ(ierr); 497 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve"); 498 #endif 499 } else { /* symmetric case */ 500 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 501 PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info)); 502 ierr = PetscFPTrapPop();CHKERRQ(ierr); 503 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve"); 504 } 505 #endif 506 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve"); 507 508 ierr = MatDenseRestoreArray(B,&b);CHKERRQ(ierr); 509 ierr = MatDenseRestoreArray(X,&x);CHKERRQ(ierr); 510 ierr = PetscLogFlops(nrhs*(2.0*m*m - m));CHKERRQ(ierr); 511 PetscFunctionReturn(0); 512 } 513 514 static PetscErrorCode MatConjugate_SeqDense(Mat); 515 516 static PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy) 517 { 518 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 519 PetscErrorCode ierr; 520 const PetscScalar *x; 521 PetscScalar *y; 522 PetscBLASInt one = 1,info,m; 523 524 PetscFunctionBegin; 525 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 526 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 527 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 528 ierr = PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 529 if (A->factortype == MAT_FACTOR_LU) { 530 #if defined(PETSC_MISSING_LAPACK_GETRS) 531 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 532 #else 533 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 534 PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 535 ierr = PetscFPTrapPop();CHKERRQ(ierr); 536 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS - Bad solve"); 537 #endif 538 } else if (A->factortype == MAT_FACTOR_CHOLESKY) { 539 #if defined(PETSC_MISSING_LAPACK_POTRS) 540 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 541 #else 542 if (A->spd) { 543 #if defined(PETSC_USE_COMPLEX) 544 ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr); 545 #endif 546 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 547 PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info)); 548 ierr = PetscFPTrapPop();CHKERRQ(ierr); 549 #if defined(PETSC_USE_COMPLEX) 550 ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr); 551 #endif 552 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve"); 553 #if defined(PETSC_USE_COMPLEX) 554 } else if (A->hermitian) { 555 ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr); 556 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 557 PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 558 ierr = PetscFPTrapPop();CHKERRQ(ierr); 559 ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr); 560 #endif 561 } else { /* symmetric case */ 562 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 563 PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info)); 564 ierr = PetscFPTrapPop();CHKERRQ(ierr); 565 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve"); 566 } 567 #endif 568 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve"); 569 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 570 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 571 ierr = PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr); 572 PetscFunctionReturn(0); 573 } 574 575 static PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 576 { 577 PetscErrorCode ierr; 578 const PetscScalar *x; 579 PetscScalar *y,sone = 1.0; 580 Vec tmp = 0; 581 582 PetscFunctionBegin; 583 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 584 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 585 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 586 if (yy == zz) { 587 ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr); 588 ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);CHKERRQ(ierr); 589 ierr = VecCopy(yy,tmp);CHKERRQ(ierr); 590 } 591 ierr = MatSolve_SeqDense(A,xx,yy);CHKERRQ(ierr); 592 if (tmp) { 593 ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr); 594 ierr = VecDestroy(&tmp);CHKERRQ(ierr); 595 } else { 596 ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr); 597 } 598 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 599 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 600 ierr = PetscLogFlops(A->cmap->n);CHKERRQ(ierr); 601 PetscFunctionReturn(0); 602 } 603 604 static PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 605 { 606 PetscErrorCode ierr; 607 const PetscScalar *x; 608 PetscScalar *y,sone = 1.0; 609 Vec tmp = NULL; 610 611 PetscFunctionBegin; 612 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 613 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 614 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 615 if (yy == zz) { 616 ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr); 617 ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);CHKERRQ(ierr); 618 ierr = VecCopy(yy,tmp);CHKERRQ(ierr); 619 } 620 ierr = MatSolveTranspose_SeqDense(A,xx,yy);CHKERRQ(ierr); 621 if (tmp) { 622 ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr); 623 ierr = VecDestroy(&tmp);CHKERRQ(ierr); 624 } else { 625 ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr); 626 } 627 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 628 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 629 ierr = PetscLogFlops(A->cmap->n);CHKERRQ(ierr); 630 PetscFunctionReturn(0); 631 } 632 633 /* ---------------------------------------------------------------*/ 634 /* COMMENT: I have chosen to hide row permutation in the pivots, 635 rather than put it in the Mat->row slot.*/ 636 static PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,const MatFactorInfo *minfo) 637 { 638 #if defined(PETSC_MISSING_LAPACK_GETRF) 639 PetscFunctionBegin; 640 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable."); 641 #else 642 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 643 PetscErrorCode ierr; 644 PetscBLASInt n,m,info; 645 646 PetscFunctionBegin; 647 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 648 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 649 if (!mat->pivots) { 650 ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr); 651 ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr); 652 } 653 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 654 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 655 PetscStackCallBLAS("LAPACKgetrf",LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info)); 656 ierr = PetscFPTrapPop();CHKERRQ(ierr); 657 658 if (info<0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to LU factorization"); 659 if (info>0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization"); 660 661 A->ops->solve = MatSolve_SeqDense; 662 A->ops->matsolve = MatMatSolve_SeqDense; 663 A->ops->solvetranspose = MatSolveTranspose_SeqDense; 664 A->ops->solveadd = MatSolveAdd_SeqDense; 665 A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense; 666 A->factortype = MAT_FACTOR_LU; 667 668 ierr = PetscFree(A->solvertype);CHKERRQ(ierr); 669 ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr); 670 671 ierr = PetscLogFlops((2.0*A->cmap->n*A->cmap->n*A->cmap->n)/3);CHKERRQ(ierr); 672 #endif 673 PetscFunctionReturn(0); 674 } 675 676 /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */ 677 static PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,const MatFactorInfo *factinfo) 678 { 679 #if defined(PETSC_MISSING_LAPACK_POTRF) 680 PetscFunctionBegin; 681 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable."); 682 #else 683 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 684 PetscErrorCode ierr; 685 PetscBLASInt info,n; 686 687 PetscFunctionBegin; 688 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 689 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 690 if (A->spd) { 691 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 692 PetscStackCallBLAS("LAPACKpotrf",LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info)); 693 ierr = PetscFPTrapPop();CHKERRQ(ierr); 694 #if defined(PETSC_USE_COMPLEX) 695 } else if (A->hermitian) { 696 if (!mat->pivots) { 697 ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr); 698 ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr); 699 } 700 if (!mat->fwork) { 701 PetscScalar dummy; 702 703 mat->lfwork = -1; 704 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 705 PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info)); 706 ierr = PetscFPTrapPop();CHKERRQ(ierr); 707 mat->lfwork = (PetscInt)PetscRealPart(dummy); 708 ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr); 709 ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr); 710 } 711 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 712 PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info)); 713 ierr = PetscFPTrapPop();CHKERRQ(ierr); 714 #endif 715 } else { /* symmetric case */ 716 if (!mat->pivots) { 717 ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr); 718 ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr); 719 } 720 if (!mat->fwork) { 721 PetscScalar dummy; 722 723 mat->lfwork = -1; 724 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 725 PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info)); 726 ierr = PetscFPTrapPop();CHKERRQ(ierr); 727 mat->lfwork = (PetscInt)PetscRealPart(dummy); 728 ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr); 729 ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr); 730 } 731 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 732 PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info)); 733 ierr = PetscFPTrapPop();CHKERRQ(ierr); 734 } 735 if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1); 736 737 A->ops->solve = MatSolve_SeqDense; 738 A->ops->matsolve = MatMatSolve_SeqDense; 739 A->ops->solvetranspose = MatSolveTranspose_SeqDense; 740 A->ops->solveadd = MatSolveAdd_SeqDense; 741 A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense; 742 A->factortype = MAT_FACTOR_CHOLESKY; 743 744 ierr = PetscFree(A->solvertype);CHKERRQ(ierr); 745 ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr); 746 747 ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr); 748 #endif 749 PetscFunctionReturn(0); 750 } 751 752 753 PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy) 754 { 755 PetscErrorCode ierr; 756 MatFactorInfo info; 757 758 PetscFunctionBegin; 759 info.fill = 1.0; 760 761 ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr); 762 ierr = MatCholeskyFactor_SeqDense(fact,0,&info);CHKERRQ(ierr); 763 PetscFunctionReturn(0); 764 } 765 766 static PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,const MatFactorInfo *info) 767 { 768 PetscFunctionBegin; 769 fact->assembled = PETSC_TRUE; 770 fact->preallocated = PETSC_TRUE; 771 fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense; 772 fact->ops->solve = MatSolve_SeqDense; 773 fact->ops->matsolve = MatMatSolve_SeqDense; 774 fact->ops->solvetranspose = MatSolveTranspose_SeqDense; 775 fact->ops->solveadd = MatSolveAdd_SeqDense; 776 fact->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense; 777 PetscFunctionReturn(0); 778 } 779 780 static PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,IS col,const MatFactorInfo *info) 781 { 782 PetscFunctionBegin; 783 fact->preallocated = PETSC_TRUE; 784 fact->assembled = PETSC_TRUE; 785 fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense; 786 fact->ops->solve = MatSolve_SeqDense; 787 fact->ops->matsolve = MatMatSolve_SeqDense; 788 fact->ops->solvetranspose = MatSolveTranspose_SeqDense; 789 fact->ops->solveadd = MatSolveAdd_SeqDense; 790 fact->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense; 791 PetscFunctionReturn(0); 792 } 793 794 PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A,MatFactorType ftype,Mat *fact) 795 { 796 PetscErrorCode ierr; 797 798 PetscFunctionBegin; 799 ierr = MatCreate(PetscObjectComm((PetscObject)A),fact);CHKERRQ(ierr); 800 ierr = MatSetSizes(*fact,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 801 ierr = MatSetType(*fact,((PetscObject)A)->type_name);CHKERRQ(ierr); 802 if (ftype == MAT_FACTOR_LU) { 803 (*fact)->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqDense; 804 } else { 805 (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense; 806 } 807 (*fact)->factortype = ftype; 808 809 ierr = PetscFree((*fact)->solvertype);CHKERRQ(ierr); 810 ierr = PetscStrallocpy(MATSOLVERPETSC,&(*fact)->solvertype);CHKERRQ(ierr); 811 PetscFunctionReturn(0); 812 } 813 814 /* ------------------------------------------------------------------*/ 815 static PetscErrorCode MatSOR_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx) 816 { 817 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 818 PetscScalar *x,*v = mat->v,zero = 0.0,xt; 819 const PetscScalar *b; 820 PetscErrorCode ierr; 821 PetscInt m = A->rmap->n,i; 822 PetscBLASInt o = 1,bm; 823 824 PetscFunctionBegin; 825 if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */ 826 ierr = PetscBLASIntCast(m,&bm);CHKERRQ(ierr); 827 if (flag & SOR_ZERO_INITIAL_GUESS) { 828 /* this is a hack fix, should have another version without the second BLASdotu */ 829 ierr = VecSet(xx,zero);CHKERRQ(ierr); 830 } 831 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 832 ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr); 833 its = its*lits; 834 if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 835 while (its--) { 836 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 837 for (i=0; i<m; i++) { 838 PetscStackCallBLAS("BLASdotu",xt = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o)); 839 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 840 } 841 } 842 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 843 for (i=m-1; i>=0; i--) { 844 PetscStackCallBLAS("BLASdotu",xt = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o)); 845 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 846 } 847 } 848 } 849 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 850 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 851 PetscFunctionReturn(0); 852 } 853 854 /* -----------------------------------------------------------------*/ 855 PETSC_INTERN PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy) 856 { 857 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 858 const PetscScalar *v = mat->v,*x; 859 PetscScalar *y; 860 PetscErrorCode ierr; 861 PetscBLASInt m, n,_One=1; 862 PetscScalar _DOne=1.0,_DZero=0.0; 863 864 PetscFunctionBegin; 865 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 866 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 867 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 868 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 869 if (!A->rmap->n || !A->cmap->n) { 870 PetscBLASInt i; 871 for (i=0; i<n; i++) y[i] = 0.0; 872 } else { 873 PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One)); 874 ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr); 875 } 876 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 877 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 878 PetscFunctionReturn(0); 879 } 880 881 PETSC_INTERN PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy) 882 { 883 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 884 PetscScalar *y,_DOne=1.0,_DZero=0.0; 885 PetscErrorCode ierr; 886 PetscBLASInt m, n, _One=1; 887 const PetscScalar *v = mat->v,*x; 888 889 PetscFunctionBegin; 890 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 891 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 892 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 893 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 894 if (!A->rmap->n || !A->cmap->n) { 895 PetscBLASInt i; 896 for (i=0; i<m; i++) y[i] = 0.0; 897 } else { 898 PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One)); 899 ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->rmap->n);CHKERRQ(ierr); 900 } 901 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 902 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 903 PetscFunctionReturn(0); 904 } 905 906 PETSC_INTERN PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 907 { 908 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 909 const PetscScalar *v = mat->v,*x; 910 PetscScalar *y,_DOne=1.0; 911 PetscErrorCode ierr; 912 PetscBLASInt m, n, _One=1; 913 914 PetscFunctionBegin; 915 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 916 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 917 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 918 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 919 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 920 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 921 PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One)); 922 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 923 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 924 ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr); 925 PetscFunctionReturn(0); 926 } 927 928 static PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 929 { 930 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 931 const PetscScalar *v = mat->v,*x; 932 PetscScalar *y; 933 PetscErrorCode ierr; 934 PetscBLASInt m, n, _One=1; 935 PetscScalar _DOne=1.0; 936 937 PetscFunctionBegin; 938 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 939 ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr); 940 if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0); 941 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 942 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 943 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 944 PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One)); 945 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 946 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 947 ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr); 948 PetscFunctionReturn(0); 949 } 950 951 /* -----------------------------------------------------------------*/ 952 static PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals) 953 { 954 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 955 PetscScalar *v; 956 PetscErrorCode ierr; 957 PetscInt i; 958 959 PetscFunctionBegin; 960 *ncols = A->cmap->n; 961 if (cols) { 962 ierr = PetscMalloc1(A->cmap->n+1,cols);CHKERRQ(ierr); 963 for (i=0; i<A->cmap->n; i++) (*cols)[i] = i; 964 } 965 if (vals) { 966 ierr = PetscMalloc1(A->cmap->n+1,vals);CHKERRQ(ierr); 967 v = mat->v + row; 968 for (i=0; i<A->cmap->n; i++) {(*vals)[i] = *v; v += mat->lda;} 969 } 970 PetscFunctionReturn(0); 971 } 972 973 static PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals) 974 { 975 PetscErrorCode ierr; 976 977 PetscFunctionBegin; 978 if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);} 979 if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); } 980 PetscFunctionReturn(0); 981 } 982 /* ----------------------------------------------------------------*/ 983 static PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv) 984 { 985 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 986 PetscInt i,j,idx=0; 987 988 PetscFunctionBegin; 989 if (!mat->roworiented) { 990 if (addv == INSERT_VALUES) { 991 for (j=0; j<n; j++) { 992 if (indexn[j] < 0) {idx += m; continue;} 993 #if defined(PETSC_USE_DEBUG) 994 if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1); 995 #endif 996 for (i=0; i<m; i++) { 997 if (indexm[i] < 0) {idx++; continue;} 998 #if defined(PETSC_USE_DEBUG) 999 if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1); 1000 #endif 1001 mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++]; 1002 } 1003 } 1004 } else { 1005 for (j=0; j<n; j++) { 1006 if (indexn[j] < 0) {idx += m; continue;} 1007 #if defined(PETSC_USE_DEBUG) 1008 if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1); 1009 #endif 1010 for (i=0; i<m; i++) { 1011 if (indexm[i] < 0) {idx++; continue;} 1012 #if defined(PETSC_USE_DEBUG) 1013 if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1); 1014 #endif 1015 mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++]; 1016 } 1017 } 1018 } 1019 } else { 1020 if (addv == INSERT_VALUES) { 1021 for (i=0; i<m; i++) { 1022 if (indexm[i] < 0) { idx += n; continue;} 1023 #if defined(PETSC_USE_DEBUG) 1024 if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1); 1025 #endif 1026 for (j=0; j<n; j++) { 1027 if (indexn[j] < 0) { idx++; continue;} 1028 #if defined(PETSC_USE_DEBUG) 1029 if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1); 1030 #endif 1031 mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++]; 1032 } 1033 } 1034 } else { 1035 for (i=0; i<m; i++) { 1036 if (indexm[i] < 0) { idx += n; continue;} 1037 #if defined(PETSC_USE_DEBUG) 1038 if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1); 1039 #endif 1040 for (j=0; j<n; j++) { 1041 if (indexn[j] < 0) { idx++; continue;} 1042 #if defined(PETSC_USE_DEBUG) 1043 if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1); 1044 #endif 1045 mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++]; 1046 } 1047 } 1048 } 1049 } 1050 PetscFunctionReturn(0); 1051 } 1052 1053 static PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[]) 1054 { 1055 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1056 PetscInt i,j; 1057 1058 PetscFunctionBegin; 1059 /* row-oriented output */ 1060 for (i=0; i<m; i++) { 1061 if (indexm[i] < 0) {v += n;continue;} 1062 if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested larger than number rows %D",indexm[i],A->rmap->n); 1063 for (j=0; j<n; j++) { 1064 if (indexn[j] < 0) {v++; continue;} 1065 if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column %D requested larger than number columns %D",indexn[j],A->cmap->n); 1066 *v++ = mat->v[indexn[j]*mat->lda + indexm[i]]; 1067 } 1068 } 1069 PetscFunctionReturn(0); 1070 } 1071 1072 /* -----------------------------------------------------------------*/ 1073 1074 static PetscErrorCode MatLoad_SeqDense(Mat newmat,PetscViewer viewer) 1075 { 1076 Mat_SeqDense *a; 1077 PetscErrorCode ierr; 1078 PetscInt *scols,i,j,nz,header[4]; 1079 int fd; 1080 PetscMPIInt size; 1081 PetscInt *rowlengths = 0,M,N,*cols,grows,gcols; 1082 PetscScalar *vals,*svals,*v,*w; 1083 MPI_Comm comm; 1084 1085 PetscFunctionBegin; 1086 /* force binary viewer to load .info file if it has not yet done so */ 1087 ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 1088 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 1089 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1090 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"view must have one processor"); 1091 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1092 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 1093 if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not matrix object"); 1094 M = header[1]; N = header[2]; nz = header[3]; 1095 1096 /* set global size if not set already*/ 1097 if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) { 1098 ierr = MatSetSizes(newmat,M,N,M,N);CHKERRQ(ierr); 1099 } else { 1100 /* if sizes and type are already set, check if the vector global sizes are correct */ 1101 ierr = MatGetSize(newmat,&grows,&gcols);CHKERRQ(ierr); 1102 if (M != grows || N != gcols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,grows,gcols); 1103 } 1104 a = (Mat_SeqDense*)newmat->data; 1105 if (!a->user_alloc) { 1106 ierr = MatSeqDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr); 1107 } 1108 1109 if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */ 1110 a = (Mat_SeqDense*)newmat->data; 1111 v = a->v; 1112 /* Allocate some temp space to read in the values and then flip them 1113 from row major to column major */ 1114 ierr = PetscMalloc1(M*N > 0 ? M*N : 1,&w);CHKERRQ(ierr); 1115 /* read in nonzero values */ 1116 ierr = PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);CHKERRQ(ierr); 1117 /* now flip the values and store them in the matrix*/ 1118 for (j=0; j<N; j++) { 1119 for (i=0; i<M; i++) { 1120 *v++ =w[i*N+j]; 1121 } 1122 } 1123 ierr = PetscFree(w);CHKERRQ(ierr); 1124 } else { 1125 /* read row lengths */ 1126 ierr = PetscMalloc1(M+1,&rowlengths);CHKERRQ(ierr); 1127 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 1128 1129 a = (Mat_SeqDense*)newmat->data; 1130 v = a->v; 1131 1132 /* read column indices and nonzeros */ 1133 ierr = PetscMalloc1(nz+1,&scols);CHKERRQ(ierr); 1134 cols = scols; 1135 ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr); 1136 ierr = PetscMalloc1(nz+1,&svals);CHKERRQ(ierr); 1137 vals = svals; 1138 ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 1139 1140 /* insert into matrix */ 1141 for (i=0; i<M; i++) { 1142 for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j]; 1143 svals += rowlengths[i]; scols += rowlengths[i]; 1144 } 1145 ierr = PetscFree(vals);CHKERRQ(ierr); 1146 ierr = PetscFree(cols);CHKERRQ(ierr); 1147 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 1148 } 1149 ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1150 ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1151 PetscFunctionReturn(0); 1152 } 1153 1154 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer) 1155 { 1156 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1157 PetscErrorCode ierr; 1158 PetscInt i,j; 1159 const char *name; 1160 PetscScalar *v; 1161 PetscViewerFormat format; 1162 #if defined(PETSC_USE_COMPLEX) 1163 PetscBool allreal = PETSC_TRUE; 1164 #endif 1165 1166 PetscFunctionBegin; 1167 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1168 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1169 PetscFunctionReturn(0); /* do nothing for now */ 1170 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 1171 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 1172 for (i=0; i<A->rmap->n; i++) { 1173 v = a->v + i; 1174 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 1175 for (j=0; j<A->cmap->n; j++) { 1176 #if defined(PETSC_USE_COMPLEX) 1177 if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) { 1178 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr); 1179 } else if (PetscRealPart(*v)) { 1180 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)PetscRealPart(*v));CHKERRQ(ierr); 1181 } 1182 #else 1183 if (*v) { 1184 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)*v);CHKERRQ(ierr); 1185 } 1186 #endif 1187 v += a->lda; 1188 } 1189 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 1190 } 1191 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 1192 } else { 1193 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 1194 #if defined(PETSC_USE_COMPLEX) 1195 /* determine if matrix has all real values */ 1196 v = a->v; 1197 for (i=0; i<A->rmap->n*A->cmap->n; i++) { 1198 if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break;} 1199 } 1200 #endif 1201 if (format == PETSC_VIEWER_ASCII_MATLAB) { 1202 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 1203 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap->n,A->cmap->n);CHKERRQ(ierr); 1204 ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 1205 ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr); 1206 } 1207 1208 for (i=0; i<A->rmap->n; i++) { 1209 v = a->v + i; 1210 for (j=0; j<A->cmap->n; j++) { 1211 #if defined(PETSC_USE_COMPLEX) 1212 if (allreal) { 1213 ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v));CHKERRQ(ierr); 1214 } else { 1215 ierr = PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr); 1216 } 1217 #else 1218 ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v);CHKERRQ(ierr); 1219 #endif 1220 v += a->lda; 1221 } 1222 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 1223 } 1224 if (format == PETSC_VIEWER_ASCII_MATLAB) { 1225 ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr); 1226 } 1227 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 1228 } 1229 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1230 PetscFunctionReturn(0); 1231 } 1232 1233 static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer) 1234 { 1235 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1236 PetscErrorCode ierr; 1237 int fd; 1238 PetscInt ict,j,n = A->cmap->n,m = A->rmap->n,i,*col_lens,nz = m*n; 1239 PetscScalar *v,*anonz,*vals; 1240 PetscViewerFormat format; 1241 1242 PetscFunctionBegin; 1243 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1244 1245 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1246 if (format == PETSC_VIEWER_NATIVE) { 1247 /* store the matrix as a dense matrix */ 1248 ierr = PetscMalloc1(4,&col_lens);CHKERRQ(ierr); 1249 1250 col_lens[0] = MAT_FILE_CLASSID; 1251 col_lens[1] = m; 1252 col_lens[2] = n; 1253 col_lens[3] = MATRIX_BINARY_FORMAT_DENSE; 1254 1255 ierr = PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 1256 ierr = PetscFree(col_lens);CHKERRQ(ierr); 1257 1258 /* write out matrix, by rows */ 1259 ierr = PetscMalloc1(m*n+1,&vals);CHKERRQ(ierr); 1260 v = a->v; 1261 for (j=0; j<n; j++) { 1262 for (i=0; i<m; i++) { 1263 vals[j + i*n] = *v++; 1264 } 1265 } 1266 ierr = PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 1267 ierr = PetscFree(vals);CHKERRQ(ierr); 1268 } else { 1269 ierr = PetscMalloc1(4+nz,&col_lens);CHKERRQ(ierr); 1270 1271 col_lens[0] = MAT_FILE_CLASSID; 1272 col_lens[1] = m; 1273 col_lens[2] = n; 1274 col_lens[3] = nz; 1275 1276 /* store lengths of each row and write (including header) to file */ 1277 for (i=0; i<m; i++) col_lens[4+i] = n; 1278 ierr = PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 1279 1280 /* Possibly should write in smaller increments, not whole matrix at once? */ 1281 /* store column indices (zero start index) */ 1282 ict = 0; 1283 for (i=0; i<m; i++) { 1284 for (j=0; j<n; j++) col_lens[ict++] = j; 1285 } 1286 ierr = PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 1287 ierr = PetscFree(col_lens);CHKERRQ(ierr); 1288 1289 /* store nonzero values */ 1290 ierr = PetscMalloc1(nz+1,&anonz);CHKERRQ(ierr); 1291 ict = 0; 1292 for (i=0; i<m; i++) { 1293 v = a->v + i; 1294 for (j=0; j<n; j++) { 1295 anonz[ict++] = *v; v += a->lda; 1296 } 1297 } 1298 ierr = PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 1299 ierr = PetscFree(anonz);CHKERRQ(ierr); 1300 } 1301 PetscFunctionReturn(0); 1302 } 1303 1304 #include <petscdraw.h> 1305 static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa) 1306 { 1307 Mat A = (Mat) Aa; 1308 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1309 PetscErrorCode ierr; 1310 PetscInt m = A->rmap->n,n = A->cmap->n,i,j; 1311 int color = PETSC_DRAW_WHITE; 1312 PetscScalar *v = a->v; 1313 PetscViewer viewer; 1314 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r; 1315 PetscViewerFormat format; 1316 1317 PetscFunctionBegin; 1318 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 1319 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1320 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 1321 1322 /* Loop over matrix elements drawing boxes */ 1323 1324 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 1325 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 1326 /* Blue for negative and Red for positive */ 1327 for (j = 0; j < n; j++) { 1328 x_l = j; x_r = x_l + 1.0; 1329 for (i = 0; i < m; i++) { 1330 y_l = m - i - 1.0; 1331 y_r = y_l + 1.0; 1332 if (PetscRealPart(v[j*m+i]) > 0.) { 1333 color = PETSC_DRAW_RED; 1334 } else if (PetscRealPart(v[j*m+i]) < 0.) { 1335 color = PETSC_DRAW_BLUE; 1336 } else { 1337 continue; 1338 } 1339 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 1340 } 1341 } 1342 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 1343 } else { 1344 /* use contour shading to indicate magnitude of values */ 1345 /* first determine max of all nonzero values */ 1346 PetscReal minv = 0.0, maxv = 0.0; 1347 PetscDraw popup; 1348 1349 for (i=0; i < m*n; i++) { 1350 if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]); 1351 } 1352 if (minv >= maxv) maxv = minv + PETSC_SMALL; 1353 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 1354 ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr); 1355 1356 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 1357 for (j=0; j<n; j++) { 1358 x_l = j; 1359 x_r = x_l + 1.0; 1360 for (i=0; i<m; i++) { 1361 y_l = m - i - 1.0; 1362 y_r = y_l + 1.0; 1363 color = PetscDrawRealToColor(PetscAbsScalar(v[j*m+i]),minv,maxv); 1364 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 1365 } 1366 } 1367 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 1368 } 1369 PetscFunctionReturn(0); 1370 } 1371 1372 static PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer) 1373 { 1374 PetscDraw draw; 1375 PetscBool isnull; 1376 PetscReal xr,yr,xl,yl,h,w; 1377 PetscErrorCode ierr; 1378 1379 PetscFunctionBegin; 1380 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 1381 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 1382 if (isnull) PetscFunctionReturn(0); 1383 1384 xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0; 1385 xr += w; yr += h; xl = -w; yl = -h; 1386 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 1387 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 1388 ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr); 1389 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr); 1390 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1391 PetscFunctionReturn(0); 1392 } 1393 1394 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer) 1395 { 1396 PetscErrorCode ierr; 1397 PetscBool iascii,isbinary,isdraw; 1398 1399 PetscFunctionBegin; 1400 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1401 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1402 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1403 1404 if (iascii) { 1405 ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr); 1406 } else if (isbinary) { 1407 ierr = MatView_SeqDense_Binary(A,viewer);CHKERRQ(ierr); 1408 } else if (isdraw) { 1409 ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr); 1410 } 1411 PetscFunctionReturn(0); 1412 } 1413 1414 static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A,const PetscScalar array[]) 1415 { 1416 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1417 1418 PetscFunctionBegin; 1419 a->unplacedarray = a->v; 1420 a->unplaced_user_alloc = a->user_alloc; 1421 a->v = (PetscScalar*) array; 1422 PetscFunctionReturn(0); 1423 } 1424 1425 static PetscErrorCode MatDenseResetArray_SeqDense(Mat A) 1426 { 1427 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1428 1429 PetscFunctionBegin; 1430 a->v = a->unplacedarray; 1431 a->user_alloc = a->unplaced_user_alloc; 1432 a->unplacedarray = NULL; 1433 PetscFunctionReturn(0); 1434 } 1435 1436 static PetscErrorCode MatDestroy_SeqDense(Mat mat) 1437 { 1438 Mat_SeqDense *l = (Mat_SeqDense*)mat->data; 1439 PetscErrorCode ierr; 1440 1441 PetscFunctionBegin; 1442 #if defined(PETSC_USE_LOG) 1443 PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap->n,mat->cmap->n); 1444 #endif 1445 ierr = PetscFree(l->pivots);CHKERRQ(ierr); 1446 ierr = PetscFree(l->fwork);CHKERRQ(ierr); 1447 ierr = MatDestroy(&l->ptapwork);CHKERRQ(ierr); 1448 if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);} 1449 ierr = PetscFree(mat->data);CHKERRQ(ierr); 1450 1451 ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr); 1452 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);CHKERRQ(ierr); 1453 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);CHKERRQ(ierr); 1454 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);CHKERRQ(ierr); 1455 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);CHKERRQ(ierr); 1456 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqaij_C",NULL);CHKERRQ(ierr); 1457 #if defined(PETSC_HAVE_ELEMENTAL) 1458 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_elemental_C",NULL);CHKERRQ(ierr); 1459 #endif 1460 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSeqDenseSetPreallocation_C",NULL);CHKERRQ(ierr); 1461 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1462 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1463 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1464 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatPtAP_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1465 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1466 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1467 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1468 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",NULL);CHKERRQ(ierr); 1469 ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",NULL);CHKERRQ(ierr); 1470 PetscFunctionReturn(0); 1471 } 1472 1473 static PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout) 1474 { 1475 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1476 PetscErrorCode ierr; 1477 PetscInt k,j,m,n,M; 1478 PetscScalar *v,tmp; 1479 1480 PetscFunctionBegin; 1481 v = mat->v; m = A->rmap->n; M = mat->lda; n = A->cmap->n; 1482 if (reuse == MAT_INPLACE_MATRIX && m == n) { /* in place transpose */ 1483 for (j=0; j<m; j++) { 1484 for (k=0; k<j; k++) { 1485 tmp = v[j + k*M]; 1486 v[j + k*M] = v[k + j*M]; 1487 v[k + j*M] = tmp; 1488 } 1489 } 1490 } else { /* out-of-place transpose */ 1491 Mat tmat; 1492 Mat_SeqDense *tmatd; 1493 PetscScalar *v2; 1494 PetscInt M2; 1495 1496 if (reuse != MAT_REUSE_MATRIX) { 1497 ierr = MatCreate(PetscObjectComm((PetscObject)A),&tmat);CHKERRQ(ierr); 1498 ierr = MatSetSizes(tmat,A->cmap->n,A->rmap->n,A->cmap->n,A->rmap->n);CHKERRQ(ierr); 1499 ierr = MatSetType(tmat,((PetscObject)A)->type_name);CHKERRQ(ierr); 1500 ierr = MatSeqDenseSetPreallocation(tmat,NULL);CHKERRQ(ierr); 1501 } else { 1502 tmat = *matout; 1503 } 1504 tmatd = (Mat_SeqDense*)tmat->data; 1505 v = mat->v; v2 = tmatd->v; M2 = tmatd->lda; 1506 for (j=0; j<n; j++) { 1507 for (k=0; k<m; k++) v2[j + k*M2] = v[k + j*M]; 1508 } 1509 ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1510 ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1511 if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) *matout = tmat; 1512 else { 1513 ierr = MatHeaderMerge(A,&tmat);CHKERRQ(ierr); 1514 } 1515 } 1516 PetscFunctionReturn(0); 1517 } 1518 1519 static PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscBool *flg) 1520 { 1521 Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data; 1522 Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data; 1523 PetscInt i,j; 1524 PetscScalar *v1,*v2; 1525 1526 PetscFunctionBegin; 1527 if (A1->rmap->n != A2->rmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1528 if (A1->cmap->n != A2->cmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1529 for (i=0; i<A1->rmap->n; i++) { 1530 v1 = mat1->v+i; v2 = mat2->v+i; 1531 for (j=0; j<A1->cmap->n; j++) { 1532 if (*v1 != *v2) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1533 v1 += mat1->lda; v2 += mat2->lda; 1534 } 1535 } 1536 *flg = PETSC_TRUE; 1537 PetscFunctionReturn(0); 1538 } 1539 1540 static PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v) 1541 { 1542 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1543 PetscErrorCode ierr; 1544 PetscInt i,n,len; 1545 PetscScalar *x,zero = 0.0; 1546 1547 PetscFunctionBegin; 1548 ierr = VecSet(v,zero);CHKERRQ(ierr); 1549 ierr = VecGetSize(v,&n);CHKERRQ(ierr); 1550 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1551 len = PetscMin(A->rmap->n,A->cmap->n); 1552 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec"); 1553 for (i=0; i<len; i++) { 1554 x[i] = mat->v[i*mat->lda + i]; 1555 } 1556 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1557 PetscFunctionReturn(0); 1558 } 1559 1560 static PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr) 1561 { 1562 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1563 const PetscScalar *l,*r; 1564 PetscScalar x,*v; 1565 PetscErrorCode ierr; 1566 PetscInt i,j,m = A->rmap->n,n = A->cmap->n; 1567 1568 PetscFunctionBegin; 1569 if (ll) { 1570 ierr = VecGetSize(ll,&m);CHKERRQ(ierr); 1571 ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr); 1572 if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size"); 1573 for (i=0; i<m; i++) { 1574 x = l[i]; 1575 v = mat->v + i; 1576 for (j=0; j<n; j++) { (*v) *= x; v+= mat->lda;} 1577 } 1578 ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr); 1579 ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr); 1580 } 1581 if (rr) { 1582 ierr = VecGetSize(rr,&n);CHKERRQ(ierr); 1583 ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr); 1584 if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size"); 1585 for (i=0; i<n; i++) { 1586 x = r[i]; 1587 v = mat->v + i*mat->lda; 1588 for (j=0; j<m; j++) (*v++) *= x; 1589 } 1590 ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr); 1591 ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr); 1592 } 1593 PetscFunctionReturn(0); 1594 } 1595 1596 static PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm) 1597 { 1598 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1599 PetscScalar *v = mat->v; 1600 PetscReal sum = 0.0; 1601 PetscInt lda =mat->lda,m=A->rmap->n,i,j; 1602 PetscErrorCode ierr; 1603 1604 PetscFunctionBegin; 1605 if (type == NORM_FROBENIUS) { 1606 if (lda>m) { 1607 for (j=0; j<A->cmap->n; j++) { 1608 v = mat->v+j*lda; 1609 for (i=0; i<m; i++) { 1610 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1611 } 1612 } 1613 } else { 1614 #if defined(PETSC_USE_REAL___FP16) 1615 PetscBLASInt one = 1,cnt = A->cmap->n*A->rmap->n; 1616 *nrm = BLASnrm2_(&cnt,v,&one); 1617 } 1618 #else 1619 for (i=0; i<A->cmap->n*A->rmap->n; i++) { 1620 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1621 } 1622 } 1623 *nrm = PetscSqrtReal(sum); 1624 #endif 1625 ierr = PetscLogFlops(2.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr); 1626 } else if (type == NORM_1) { 1627 *nrm = 0.0; 1628 for (j=0; j<A->cmap->n; j++) { 1629 v = mat->v + j*mat->lda; 1630 sum = 0.0; 1631 for (i=0; i<A->rmap->n; i++) { 1632 sum += PetscAbsScalar(*v); v++; 1633 } 1634 if (sum > *nrm) *nrm = sum; 1635 } 1636 ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr); 1637 } else if (type == NORM_INFINITY) { 1638 *nrm = 0.0; 1639 for (j=0; j<A->rmap->n; j++) { 1640 v = mat->v + j; 1641 sum = 0.0; 1642 for (i=0; i<A->cmap->n; i++) { 1643 sum += PetscAbsScalar(*v); v += mat->lda; 1644 } 1645 if (sum > *nrm) *nrm = sum; 1646 } 1647 ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr); 1648 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No two norm"); 1649 PetscFunctionReturn(0); 1650 } 1651 1652 static PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscBool flg) 1653 { 1654 Mat_SeqDense *aij = (Mat_SeqDense*)A->data; 1655 PetscErrorCode ierr; 1656 1657 PetscFunctionBegin; 1658 switch (op) { 1659 case MAT_ROW_ORIENTED: 1660 aij->roworiented = flg; 1661 break; 1662 case MAT_NEW_NONZERO_LOCATIONS: 1663 case MAT_NEW_NONZERO_LOCATION_ERR: 1664 case MAT_NEW_NONZERO_ALLOCATION_ERR: 1665 case MAT_NEW_DIAGONALS: 1666 case MAT_KEEP_NONZERO_PATTERN: 1667 case MAT_IGNORE_OFF_PROC_ENTRIES: 1668 case MAT_USE_HASH_TABLE: 1669 case MAT_IGNORE_ZERO_ENTRIES: 1670 case MAT_IGNORE_LOWER_TRIANGULAR: 1671 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 1672 break; 1673 case MAT_SPD: 1674 case MAT_SYMMETRIC: 1675 case MAT_STRUCTURALLY_SYMMETRIC: 1676 case MAT_HERMITIAN: 1677 case MAT_SYMMETRY_ETERNAL: 1678 /* These options are handled directly by MatSetOption() */ 1679 break; 1680 default: 1681 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]); 1682 } 1683 PetscFunctionReturn(0); 1684 } 1685 1686 static PetscErrorCode MatZeroEntries_SeqDense(Mat A) 1687 { 1688 Mat_SeqDense *l = (Mat_SeqDense*)A->data; 1689 PetscErrorCode ierr; 1690 PetscInt lda=l->lda,m=A->rmap->n,j; 1691 1692 PetscFunctionBegin; 1693 if (lda>m) { 1694 for (j=0; j<A->cmap->n; j++) { 1695 ierr = PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr); 1696 } 1697 } else { 1698 ierr = PetscMemzero(l->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 1699 } 1700 PetscFunctionReturn(0); 1701 } 1702 1703 static PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1704 { 1705 PetscErrorCode ierr; 1706 Mat_SeqDense *l = (Mat_SeqDense*)A->data; 1707 PetscInt m = l->lda, n = A->cmap->n, i,j; 1708 PetscScalar *slot,*bb; 1709 const PetscScalar *xx; 1710 1711 PetscFunctionBegin; 1712 #if defined(PETSC_USE_DEBUG) 1713 for (i=0; i<N; i++) { 1714 if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed"); 1715 if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n); 1716 } 1717 #endif 1718 1719 /* fix right hand side if needed */ 1720 if (x && b) { 1721 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1722 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1723 for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]]; 1724 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 1725 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1726 } 1727 1728 for (i=0; i<N; i++) { 1729 slot = l->v + rows[i]; 1730 for (j=0; j<n; j++) { *slot = 0.0; slot += m;} 1731 } 1732 if (diag != 0.0) { 1733 if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices"); 1734 for (i=0; i<N; i++) { 1735 slot = l->v + (m+1)*rows[i]; 1736 *slot = diag; 1737 } 1738 } 1739 PetscFunctionReturn(0); 1740 } 1741 1742 static PetscErrorCode MatDenseGetArray_SeqDense(Mat A,PetscScalar *array[]) 1743 { 1744 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1745 1746 PetscFunctionBegin; 1747 if (mat->lda != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get array for Dense matrices with LDA different from number of rows"); 1748 *array = mat->v; 1749 PetscFunctionReturn(0); 1750 } 1751 1752 static PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A,PetscScalar *array[]) 1753 { 1754 PetscFunctionBegin; 1755 PetscFunctionReturn(0); 1756 } 1757 1758 /*@C 1759 MatDenseGetArray - gives access to the array where the data for a SeqDense matrix is stored 1760 1761 Logically Collective on Mat 1762 1763 Input Parameter: 1764 . mat - a MATSEQDENSE or MATMPIDENSE matrix 1765 1766 Output Parameter: 1767 . array - pointer to the data 1768 1769 Level: intermediate 1770 1771 .seealso: MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead() 1772 @*/ 1773 PetscErrorCode MatDenseGetArray(Mat A,PetscScalar **array) 1774 { 1775 PetscErrorCode ierr; 1776 1777 PetscFunctionBegin; 1778 ierr = PetscUseMethod(A,"MatDenseGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 1779 PetscFunctionReturn(0); 1780 } 1781 1782 /*@C 1783 MatDenseRestoreArray - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray() 1784 1785 Logically Collective on Mat 1786 1787 Input Parameters: 1788 . mat - a MATSEQDENSE or MATMPIDENSE matrix 1789 . array - pointer to the data 1790 1791 Level: intermediate 1792 1793 .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead() 1794 @*/ 1795 PetscErrorCode MatDenseRestoreArray(Mat A,PetscScalar **array) 1796 { 1797 PetscErrorCode ierr; 1798 1799 PetscFunctionBegin; 1800 ierr = PetscUseMethod(A,"MatDenseRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 1801 if (array) *array = NULL; 1802 ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 1803 PetscFunctionReturn(0); 1804 } 1805 1806 /*@C 1807 MatDenseGetArrayRead - gives access to the array where the data for a SeqDense matrix is stored 1808 1809 Not Collective 1810 1811 Input Parameter: 1812 . mat - a MATSEQDENSE or MATMPIDENSE matrix 1813 1814 Output Parameter: 1815 . array - pointer to the data 1816 1817 Level: intermediate 1818 1819 .seealso: MatDenseRestoreArray(), MatDenseGetArray(), MatDenseRestoreArrayRead() 1820 @*/ 1821 PetscErrorCode MatDenseGetArrayRead(Mat A,const PetscScalar **array) 1822 { 1823 PetscErrorCode ierr; 1824 1825 PetscFunctionBegin; 1826 ierr = PetscUseMethod(A,"MatDenseGetArrayRead_C",(Mat,const PetscScalar**),(A,array));CHKERRQ(ierr); 1827 PetscFunctionReturn(0); 1828 } 1829 1830 /*@C 1831 MatDenseRestoreArrayRead - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray() 1832 1833 Not Collective 1834 1835 Input Parameters: 1836 . mat - a MATSEQDENSE or MATMPIDENSE matrix 1837 . array - pointer to the data 1838 1839 Level: intermediate 1840 1841 .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArray() 1842 @*/ 1843 PetscErrorCode MatDenseRestoreArrayRead(Mat A,const PetscScalar **array) 1844 { 1845 PetscErrorCode ierr; 1846 1847 PetscFunctionBegin; 1848 ierr = PetscUseMethod(A,"MatDenseRestoreArrayRead_C",(Mat,const PetscScalar**),(A,array));CHKERRQ(ierr); 1849 if (array) *array = NULL; 1850 PetscFunctionReturn(0); 1851 } 1852 1853 static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B) 1854 { 1855 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1856 PetscErrorCode ierr; 1857 PetscInt i,j,nrows,ncols; 1858 const PetscInt *irow,*icol; 1859 PetscScalar *av,*bv,*v = mat->v; 1860 Mat newmat; 1861 1862 PetscFunctionBegin; 1863 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 1864 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 1865 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 1866 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 1867 1868 /* Check submatrixcall */ 1869 if (scall == MAT_REUSE_MATRIX) { 1870 PetscInt n_cols,n_rows; 1871 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 1872 if (n_rows != nrows || n_cols != ncols) { 1873 /* resize the result matrix to match number of requested rows/columns */ 1874 ierr = MatSetSizes(*B,nrows,ncols,nrows,ncols);CHKERRQ(ierr); 1875 } 1876 newmat = *B; 1877 } else { 1878 /* Create and fill new matrix */ 1879 ierr = MatCreate(PetscObjectComm((PetscObject)A),&newmat);CHKERRQ(ierr); 1880 ierr = MatSetSizes(newmat,nrows,ncols,nrows,ncols);CHKERRQ(ierr); 1881 ierr = MatSetType(newmat,((PetscObject)A)->type_name);CHKERRQ(ierr); 1882 ierr = MatSeqDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr); 1883 } 1884 1885 /* Now extract the data pointers and do the copy,column at a time */ 1886 bv = ((Mat_SeqDense*)newmat->data)->v; 1887 1888 for (i=0; i<ncols; i++) { 1889 av = v + mat->lda*icol[i]; 1890 for (j=0; j<nrows; j++) *bv++ = av[irow[j]]; 1891 } 1892 1893 /* Assemble the matrices so that the correct flags are set */ 1894 ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1895 ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1896 1897 /* Free work space */ 1898 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 1899 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 1900 *B = newmat; 1901 PetscFunctionReturn(0); 1902 } 1903 1904 static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 1905 { 1906 PetscErrorCode ierr; 1907 PetscInt i; 1908 1909 PetscFunctionBegin; 1910 if (scall == MAT_INITIAL_MATRIX) { 1911 ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr); 1912 } 1913 1914 for (i=0; i<n; i++) { 1915 ierr = MatCreateSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 1916 } 1917 PetscFunctionReturn(0); 1918 } 1919 1920 static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode) 1921 { 1922 PetscFunctionBegin; 1923 PetscFunctionReturn(0); 1924 } 1925 1926 static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode) 1927 { 1928 PetscFunctionBegin; 1929 PetscFunctionReturn(0); 1930 } 1931 1932 static PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str) 1933 { 1934 Mat_SeqDense *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense*)B->data; 1935 PetscErrorCode ierr; 1936 PetscInt lda1=a->lda,lda2=b->lda, m=A->rmap->n,n=A->cmap->n, j; 1937 1938 PetscFunctionBegin; 1939 /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 1940 if (A->ops->copy != B->ops->copy) { 1941 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 1942 PetscFunctionReturn(0); 1943 } 1944 if (m != B->rmap->n || n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"size(B) != size(A)"); 1945 if (lda1>m || lda2>m) { 1946 for (j=0; j<n; j++) { 1947 ierr = PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr); 1948 } 1949 } else { 1950 ierr = PetscMemcpy(b->v,a->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 1951 } 1952 ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 1953 PetscFunctionReturn(0); 1954 } 1955 1956 static PetscErrorCode MatSetUp_SeqDense(Mat A) 1957 { 1958 PetscErrorCode ierr; 1959 1960 PetscFunctionBegin; 1961 ierr = MatSeqDenseSetPreallocation(A,0);CHKERRQ(ierr); 1962 PetscFunctionReturn(0); 1963 } 1964 1965 static PetscErrorCode MatConjugate_SeqDense(Mat A) 1966 { 1967 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1968 PetscInt i,nz = A->rmap->n*A->cmap->n; 1969 PetscScalar *aa = a->v; 1970 1971 PetscFunctionBegin; 1972 for (i=0; i<nz; i++) aa[i] = PetscConj(aa[i]); 1973 PetscFunctionReturn(0); 1974 } 1975 1976 static PetscErrorCode MatRealPart_SeqDense(Mat A) 1977 { 1978 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1979 PetscInt i,nz = A->rmap->n*A->cmap->n; 1980 PetscScalar *aa = a->v; 1981 1982 PetscFunctionBegin; 1983 for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 1984 PetscFunctionReturn(0); 1985 } 1986 1987 static PetscErrorCode MatImaginaryPart_SeqDense(Mat A) 1988 { 1989 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 1990 PetscInt i,nz = A->rmap->n*A->cmap->n; 1991 PetscScalar *aa = a->v; 1992 1993 PetscFunctionBegin; 1994 for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 1995 PetscFunctionReturn(0); 1996 } 1997 1998 /* ----------------------------------------------------------------*/ 1999 PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 2000 { 2001 PetscErrorCode ierr; 2002 2003 PetscFunctionBegin; 2004 if (scall == MAT_INITIAL_MATRIX) { 2005 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2006 ierr = MatMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr); 2007 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2008 } 2009 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 2010 ierr = MatMatMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr); 2011 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 2012 PetscFunctionReturn(0); 2013 } 2014 2015 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C) 2016 { 2017 PetscErrorCode ierr; 2018 PetscInt m=A->rmap->n,n=B->cmap->n; 2019 Mat Cmat; 2020 2021 PetscFunctionBegin; 2022 if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n); 2023 ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr); 2024 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 2025 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 2026 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 2027 2028 *C = Cmat; 2029 PetscFunctionReturn(0); 2030 } 2031 2032 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C) 2033 { 2034 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2035 Mat_SeqDense *b = (Mat_SeqDense*)B->data; 2036 Mat_SeqDense *c = (Mat_SeqDense*)C->data; 2037 PetscBLASInt m,n,k; 2038 PetscScalar _DOne=1.0,_DZero=0.0; 2039 PetscErrorCode ierr; 2040 PetscBool flg; 2041 2042 PetscFunctionBegin; 2043 ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQDENSE,&flg);CHKERRQ(ierr); 2044 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Second matrix must be dense"); 2045 2046 /* Handle case where where user provided the final C matrix rather than calling MatMatMult() with MAT_INITIAL_MATRIX*/ 2047 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr); 2048 if (flg) { 2049 C->ops->matmultnumeric = MatMatMultNumeric_SeqAIJ_SeqDense; 2050 ierr = (*C->ops->matmultnumeric)(A,B,C);CHKERRQ(ierr); 2051 PetscFunctionReturn(0); 2052 } 2053 2054 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&flg);CHKERRQ(ierr); 2055 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"First matrix must be dense"); 2056 ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr); 2057 ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr); 2058 ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr); 2059 PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda)); 2060 PetscFunctionReturn(0); 2061 } 2062 2063 PetscErrorCode MatMatTransposeMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 2064 { 2065 PetscErrorCode ierr; 2066 2067 PetscFunctionBegin; 2068 if (scall == MAT_INITIAL_MATRIX) { 2069 ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2070 ierr = MatMatTransposeMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr); 2071 ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2072 } 2073 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 2074 ierr = MatMatTransposeMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr); 2075 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 2076 PetscFunctionReturn(0); 2077 } 2078 2079 PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C) 2080 { 2081 PetscErrorCode ierr; 2082 PetscInt m=A->rmap->n,n=B->rmap->n; 2083 Mat Cmat; 2084 2085 PetscFunctionBegin; 2086 if (A->cmap->n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->cmap->n %d\n",A->cmap->n,B->cmap->n); 2087 ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr); 2088 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 2089 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 2090 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 2091 2092 Cmat->assembled = PETSC_TRUE; 2093 2094 *C = Cmat; 2095 PetscFunctionReturn(0); 2096 } 2097 2098 PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C) 2099 { 2100 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2101 Mat_SeqDense *b = (Mat_SeqDense*)B->data; 2102 Mat_SeqDense *c = (Mat_SeqDense*)C->data; 2103 PetscBLASInt m,n,k; 2104 PetscScalar _DOne=1.0,_DZero=0.0; 2105 PetscErrorCode ierr; 2106 2107 PetscFunctionBegin; 2108 ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); 2109 ierr = PetscBLASIntCast(B->rmap->n,&n);CHKERRQ(ierr); 2110 ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr); 2111 PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda)); 2112 PetscFunctionReturn(0); 2113 } 2114 2115 PetscErrorCode MatTransposeMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 2116 { 2117 PetscErrorCode ierr; 2118 2119 PetscFunctionBegin; 2120 if (scall == MAT_INITIAL_MATRIX) { 2121 ierr = PetscLogEventBegin(MAT_TransposeMatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2122 ierr = MatTransposeMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr); 2123 ierr = PetscLogEventEnd(MAT_TransposeMatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 2124 } 2125 ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 2126 ierr = MatTransposeMatMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr); 2127 ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 2128 PetscFunctionReturn(0); 2129 } 2130 2131 PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C) 2132 { 2133 PetscErrorCode ierr; 2134 PetscInt m=A->cmap->n,n=B->cmap->n; 2135 Mat Cmat; 2136 2137 PetscFunctionBegin; 2138 if (A->rmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->rmap->n %d != B->rmap->n %d\n",A->rmap->n,B->rmap->n); 2139 ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr); 2140 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 2141 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 2142 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 2143 2144 Cmat->assembled = PETSC_TRUE; 2145 2146 *C = Cmat; 2147 PetscFunctionReturn(0); 2148 } 2149 2150 PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C) 2151 { 2152 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2153 Mat_SeqDense *b = (Mat_SeqDense*)B->data; 2154 Mat_SeqDense *c = (Mat_SeqDense*)C->data; 2155 PetscBLASInt m,n,k; 2156 PetscScalar _DOne=1.0,_DZero=0.0; 2157 PetscErrorCode ierr; 2158 2159 PetscFunctionBegin; 2160 ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr); 2161 ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr); 2162 ierr = PetscBLASIntCast(A->rmap->n,&k);CHKERRQ(ierr); 2163 PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda)); 2164 PetscFunctionReturn(0); 2165 } 2166 2167 static PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[]) 2168 { 2169 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2170 PetscErrorCode ierr; 2171 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p; 2172 PetscScalar *x; 2173 MatScalar *aa = a->v; 2174 2175 PetscFunctionBegin; 2176 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2177 2178 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2179 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2180 ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr); 2181 if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2182 for (i=0; i<m; i++) { 2183 x[i] = aa[i]; if (idx) idx[i] = 0; 2184 for (j=1; j<n; j++) { 2185 if (PetscRealPart(x[i]) < PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;} 2186 } 2187 } 2188 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2189 PetscFunctionReturn(0); 2190 } 2191 2192 static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[]) 2193 { 2194 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2195 PetscErrorCode ierr; 2196 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p; 2197 PetscScalar *x; 2198 PetscReal atmp; 2199 MatScalar *aa = a->v; 2200 2201 PetscFunctionBegin; 2202 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2203 2204 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2205 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2206 ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr); 2207 if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2208 for (i=0; i<m; i++) { 2209 x[i] = PetscAbsScalar(aa[i]); 2210 for (j=1; j<n; j++) { 2211 atmp = PetscAbsScalar(aa[i+m*j]); 2212 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;} 2213 } 2214 } 2215 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2216 PetscFunctionReturn(0); 2217 } 2218 2219 static PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[]) 2220 { 2221 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2222 PetscErrorCode ierr; 2223 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p; 2224 PetscScalar *x; 2225 MatScalar *aa = a->v; 2226 2227 PetscFunctionBegin; 2228 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2229 2230 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2231 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2232 ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr); 2233 if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2234 for (i=0; i<m; i++) { 2235 x[i] = aa[i]; if (idx) idx[i] = 0; 2236 for (j=1; j<n; j++) { 2237 if (PetscRealPart(x[i]) > PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;} 2238 } 2239 } 2240 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2241 PetscFunctionReturn(0); 2242 } 2243 2244 static PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col) 2245 { 2246 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2247 PetscErrorCode ierr; 2248 PetscScalar *x; 2249 2250 PetscFunctionBegin; 2251 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2252 2253 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2254 ierr = PetscMemcpy(x,a->v+col*a->lda,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr); 2255 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2256 PetscFunctionReturn(0); 2257 } 2258 2259 PetscErrorCode MatGetColumnNorms_SeqDense(Mat A,NormType type,PetscReal *norms) 2260 { 2261 PetscErrorCode ierr; 2262 PetscInt i,j,m,n; 2263 PetscScalar *a; 2264 2265 PetscFunctionBegin; 2266 ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); 2267 ierr = PetscMemzero(norms,n*sizeof(PetscReal));CHKERRQ(ierr); 2268 ierr = MatDenseGetArray(A,&a);CHKERRQ(ierr); 2269 if (type == NORM_2) { 2270 for (i=0; i<n; i++) { 2271 for (j=0; j<m; j++) { 2272 norms[i] += PetscAbsScalar(a[j]*a[j]); 2273 } 2274 a += m; 2275 } 2276 } else if (type == NORM_1) { 2277 for (i=0; i<n; i++) { 2278 for (j=0; j<m; j++) { 2279 norms[i] += PetscAbsScalar(a[j]); 2280 } 2281 a += m; 2282 } 2283 } else if (type == NORM_INFINITY) { 2284 for (i=0; i<n; i++) { 2285 for (j=0; j<m; j++) { 2286 norms[i] = PetscMax(PetscAbsScalar(a[j]),norms[i]); 2287 } 2288 a += m; 2289 } 2290 } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType"); 2291 ierr = MatDenseRestoreArray(A,&a);CHKERRQ(ierr); 2292 if (type == NORM_2) { 2293 for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 2294 } 2295 PetscFunctionReturn(0); 2296 } 2297 2298 static PetscErrorCode MatSetRandom_SeqDense(Mat x,PetscRandom rctx) 2299 { 2300 PetscErrorCode ierr; 2301 PetscScalar *a; 2302 PetscInt m,n,i; 2303 2304 PetscFunctionBegin; 2305 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 2306 ierr = MatDenseGetArray(x,&a);CHKERRQ(ierr); 2307 for (i=0; i<m*n; i++) { 2308 ierr = PetscRandomGetValue(rctx,a+i);CHKERRQ(ierr); 2309 } 2310 ierr = MatDenseRestoreArray(x,&a);CHKERRQ(ierr); 2311 PetscFunctionReturn(0); 2312 } 2313 2314 static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A,PetscBool *missing,PetscInt *d) 2315 { 2316 PetscFunctionBegin; 2317 *missing = PETSC_FALSE; 2318 PetscFunctionReturn(0); 2319 } 2320 2321 static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A,PetscInt col,PetscScalar **vals) 2322 { 2323 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 2324 2325 PetscFunctionBegin; 2326 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2327 *vals = a->v+col*a->lda; 2328 PetscFunctionReturn(0); 2329 } 2330 2331 static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A,PetscScalar **vals) 2332 { 2333 PetscFunctionBegin; 2334 *vals = 0; /* user cannot accidently use the array later */ 2335 PetscFunctionReturn(0); 2336 } 2337 2338 /* -------------------------------------------------------------------*/ 2339 static struct _MatOps MatOps_Values = { MatSetValues_SeqDense, 2340 MatGetRow_SeqDense, 2341 MatRestoreRow_SeqDense, 2342 MatMult_SeqDense, 2343 /* 4*/ MatMultAdd_SeqDense, 2344 MatMultTranspose_SeqDense, 2345 MatMultTransposeAdd_SeqDense, 2346 0, 2347 0, 2348 0, 2349 /* 10*/ 0, 2350 MatLUFactor_SeqDense, 2351 MatCholeskyFactor_SeqDense, 2352 MatSOR_SeqDense, 2353 MatTranspose_SeqDense, 2354 /* 15*/ MatGetInfo_SeqDense, 2355 MatEqual_SeqDense, 2356 MatGetDiagonal_SeqDense, 2357 MatDiagonalScale_SeqDense, 2358 MatNorm_SeqDense, 2359 /* 20*/ MatAssemblyBegin_SeqDense, 2360 MatAssemblyEnd_SeqDense, 2361 MatSetOption_SeqDense, 2362 MatZeroEntries_SeqDense, 2363 /* 24*/ MatZeroRows_SeqDense, 2364 0, 2365 0, 2366 0, 2367 0, 2368 /* 29*/ MatSetUp_SeqDense, 2369 0, 2370 0, 2371 0, 2372 0, 2373 /* 34*/ MatDuplicate_SeqDense, 2374 0, 2375 0, 2376 0, 2377 0, 2378 /* 39*/ MatAXPY_SeqDense, 2379 MatCreateSubMatrices_SeqDense, 2380 0, 2381 MatGetValues_SeqDense, 2382 MatCopy_SeqDense, 2383 /* 44*/ MatGetRowMax_SeqDense, 2384 MatScale_SeqDense, 2385 MatShift_Basic, 2386 0, 2387 MatZeroRowsColumns_SeqDense, 2388 /* 49*/ MatSetRandom_SeqDense, 2389 0, 2390 0, 2391 0, 2392 0, 2393 /* 54*/ 0, 2394 0, 2395 0, 2396 0, 2397 0, 2398 /* 59*/ 0, 2399 MatDestroy_SeqDense, 2400 MatView_SeqDense, 2401 0, 2402 0, 2403 /* 64*/ 0, 2404 0, 2405 0, 2406 0, 2407 0, 2408 /* 69*/ MatGetRowMaxAbs_SeqDense, 2409 0, 2410 0, 2411 0, 2412 0, 2413 /* 74*/ 0, 2414 0, 2415 0, 2416 0, 2417 0, 2418 /* 79*/ 0, 2419 0, 2420 0, 2421 0, 2422 /* 83*/ MatLoad_SeqDense, 2423 0, 2424 MatIsHermitian_SeqDense, 2425 0, 2426 0, 2427 0, 2428 /* 89*/ MatMatMult_SeqDense_SeqDense, 2429 MatMatMultSymbolic_SeqDense_SeqDense, 2430 MatMatMultNumeric_SeqDense_SeqDense, 2431 MatPtAP_SeqDense_SeqDense, 2432 MatPtAPSymbolic_SeqDense_SeqDense, 2433 /* 94*/ MatPtAPNumeric_SeqDense_SeqDense, 2434 MatMatTransposeMult_SeqDense_SeqDense, 2435 MatMatTransposeMultSymbolic_SeqDense_SeqDense, 2436 MatMatTransposeMultNumeric_SeqDense_SeqDense, 2437 0, 2438 /* 99*/ 0, 2439 0, 2440 0, 2441 MatConjugate_SeqDense, 2442 0, 2443 /*104*/ 0, 2444 MatRealPart_SeqDense, 2445 MatImaginaryPart_SeqDense, 2446 0, 2447 0, 2448 /*109*/ 0, 2449 0, 2450 MatGetRowMin_SeqDense, 2451 MatGetColumnVector_SeqDense, 2452 MatMissingDiagonal_SeqDense, 2453 /*114*/ 0, 2454 0, 2455 0, 2456 0, 2457 0, 2458 /*119*/ 0, 2459 0, 2460 0, 2461 0, 2462 0, 2463 /*124*/ 0, 2464 MatGetColumnNorms_SeqDense, 2465 0, 2466 0, 2467 0, 2468 /*129*/ 0, 2469 MatTransposeMatMult_SeqDense_SeqDense, 2470 MatTransposeMatMultSymbolic_SeqDense_SeqDense, 2471 MatTransposeMatMultNumeric_SeqDense_SeqDense, 2472 0, 2473 /*134*/ 0, 2474 0, 2475 0, 2476 0, 2477 0, 2478 /*139*/ 0, 2479 0, 2480 0, 2481 0, 2482 0, 2483 /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqDense 2484 }; 2485 2486 /*@C 2487 MatCreateSeqDense - Creates a sequential dense matrix that 2488 is stored in column major order (the usual Fortran 77 manner). Many 2489 of the matrix operations use the BLAS and LAPACK routines. 2490 2491 Collective on MPI_Comm 2492 2493 Input Parameters: 2494 + comm - MPI communicator, set to PETSC_COMM_SELF 2495 . m - number of rows 2496 . n - number of columns 2497 - data - optional location of matrix data in column major order. Set data=NULL for PETSc 2498 to control all matrix memory allocation. 2499 2500 Output Parameter: 2501 . A - the matrix 2502 2503 Notes: 2504 The data input variable is intended primarily for Fortran programmers 2505 who wish to allocate their own matrix memory space. Most users should 2506 set data=NULL. 2507 2508 Level: intermediate 2509 2510 .keywords: dense, matrix, LAPACK, BLAS 2511 2512 .seealso: MatCreate(), MatCreateDense(), MatSetValues() 2513 @*/ 2514 PetscErrorCode MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A) 2515 { 2516 PetscErrorCode ierr; 2517 2518 PetscFunctionBegin; 2519 ierr = MatCreate(comm,A);CHKERRQ(ierr); 2520 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 2521 ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr); 2522 ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr); 2523 PetscFunctionReturn(0); 2524 } 2525 2526 /*@C 2527 MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements 2528 2529 Collective on MPI_Comm 2530 2531 Input Parameters: 2532 + B - the matrix 2533 - data - the array (or NULL) 2534 2535 Notes: 2536 The data input variable is intended primarily for Fortran programmers 2537 who wish to allocate their own matrix memory space. Most users should 2538 need not call this routine. 2539 2540 Level: intermediate 2541 2542 .keywords: dense, matrix, LAPACK, BLAS 2543 2544 .seealso: MatCreate(), MatCreateDense(), MatSetValues(), MatSeqDenseSetLDA() 2545 2546 @*/ 2547 PetscErrorCode MatSeqDenseSetPreallocation(Mat B,PetscScalar data[]) 2548 { 2549 PetscErrorCode ierr; 2550 2551 PetscFunctionBegin; 2552 ierr = PetscTryMethod(B,"MatSeqDenseSetPreallocation_C",(Mat,PetscScalar[]),(B,data));CHKERRQ(ierr); 2553 PetscFunctionReturn(0); 2554 } 2555 2556 PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data) 2557 { 2558 Mat_SeqDense *b; 2559 PetscErrorCode ierr; 2560 2561 PetscFunctionBegin; 2562 B->preallocated = PETSC_TRUE; 2563 2564 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 2565 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 2566 2567 b = (Mat_SeqDense*)B->data; 2568 b->Mmax = B->rmap->n; 2569 b->Nmax = B->cmap->n; 2570 if (b->lda <= 0 || b->changelda) b->lda = B->rmap->n; 2571 2572 ierr = PetscIntMultError(b->lda,b->Nmax,NULL);CHKERRQ(ierr); 2573 if (!data) { /* petsc-allocated storage */ 2574 if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); } 2575 ierr = PetscCalloc1((size_t)b->lda*b->Nmax,&b->v);CHKERRQ(ierr); 2576 ierr = PetscLogObjectMemory((PetscObject)B,b->lda*b->Nmax*sizeof(PetscScalar));CHKERRQ(ierr); 2577 2578 b->user_alloc = PETSC_FALSE; 2579 } else { /* user-allocated storage */ 2580 if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); } 2581 b->v = data; 2582 b->user_alloc = PETSC_TRUE; 2583 } 2584 B->assembled = PETSC_TRUE; 2585 PetscFunctionReturn(0); 2586 } 2587 2588 #if defined(PETSC_HAVE_ELEMENTAL) 2589 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 2590 { 2591 Mat mat_elemental; 2592 PetscErrorCode ierr; 2593 PetscScalar *array,*v_colwise; 2594 PetscInt M=A->rmap->N,N=A->cmap->N,i,j,k,*rows,*cols; 2595 2596 PetscFunctionBegin; 2597 ierr = PetscMalloc3(M*N,&v_colwise,M,&rows,N,&cols);CHKERRQ(ierr); 2598 ierr = MatDenseGetArray(A,&array);CHKERRQ(ierr); 2599 /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */ 2600 k = 0; 2601 for (j=0; j<N; j++) { 2602 cols[j] = j; 2603 for (i=0; i<M; i++) { 2604 v_colwise[j*M+i] = array[k++]; 2605 } 2606 } 2607 for (i=0; i<M; i++) { 2608 rows[i] = i; 2609 } 2610 ierr = MatDenseRestoreArray(A,&array);CHKERRQ(ierr); 2611 2612 ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr); 2613 ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 2614 ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr); 2615 ierr = MatSetUp(mat_elemental);CHKERRQ(ierr); 2616 2617 /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 2618 ierr = MatSetValues(mat_elemental,M,rows,N,cols,v_colwise,ADD_VALUES);CHKERRQ(ierr); 2619 ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2620 ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2621 ierr = PetscFree3(v_colwise,rows,cols);CHKERRQ(ierr); 2622 2623 if (reuse == MAT_INPLACE_MATRIX) { 2624 ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr); 2625 } else { 2626 *newmat = mat_elemental; 2627 } 2628 PetscFunctionReturn(0); 2629 } 2630 #endif 2631 2632 /*@C 2633 MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array 2634 2635 Input parameter: 2636 + A - the matrix 2637 - lda - the leading dimension 2638 2639 Notes: 2640 This routine is to be used in conjunction with MatSeqDenseSetPreallocation(); 2641 it asserts that the preallocation has a leading dimension (the LDA parameter 2642 of Blas and Lapack fame) larger than M, the first dimension of the matrix. 2643 2644 Level: intermediate 2645 2646 .keywords: dense, matrix, LAPACK, BLAS 2647 2648 .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation(), MatSetMaximumSize() 2649 2650 @*/ 2651 PetscErrorCode MatSeqDenseSetLDA(Mat B,PetscInt lda) 2652 { 2653 Mat_SeqDense *b = (Mat_SeqDense*)B->data; 2654 2655 PetscFunctionBegin; 2656 if (lda < B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->rmap->n); 2657 b->lda = lda; 2658 b->changelda = PETSC_FALSE; 2659 b->Mmax = PetscMax(b->Mmax,lda); 2660 PetscFunctionReturn(0); 2661 } 2662 2663 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 2664 { 2665 PetscErrorCode ierr; 2666 PetscMPIInt size; 2667 2668 PetscFunctionBegin; 2669 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 2670 if (size == 1) { 2671 if (scall == MAT_INITIAL_MATRIX) { 2672 ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr); 2673 } else { 2674 ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2675 } 2676 } else { 2677 ierr = MatCreateMPIMatConcatenateSeqMat_MPIDense(comm,inmat,n,scall,outmat);CHKERRQ(ierr); 2678 } 2679 PetscFunctionReturn(0); 2680 } 2681 2682 /*MC 2683 MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices. 2684 2685 Options Database Keys: 2686 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions() 2687 2688 Level: beginner 2689 2690 .seealso: MatCreateSeqDense() 2691 2692 M*/ 2693 2694 PETSC_EXTERN PetscErrorCode MatCreate_SeqDense(Mat B) 2695 { 2696 Mat_SeqDense *b; 2697 PetscErrorCode ierr; 2698 PetscMPIInt size; 2699 2700 PetscFunctionBegin; 2701 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 2702 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Comm must be of size 1"); 2703 2704 ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 2705 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 2706 B->data = (void*)b; 2707 2708 b->roworiented = PETSC_TRUE; 2709 2710 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArray_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr); 2711 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArray_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr); 2712 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDensePlaceArray_C",MatDensePlaceArray_SeqDense);CHKERRQ(ierr); 2713 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseResetArray_C",MatDenseResetArray_SeqDense);CHKERRQ(ierr); 2714 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArrayRead_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr); 2715 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArrayRead_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr); 2716 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqaij_C",MatConvert_SeqDense_SeqAIJ);CHKERRQ(ierr); 2717 #if defined(PETSC_HAVE_ELEMENTAL) 2718 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_elemental_C",MatConvert_SeqDense_Elemental);CHKERRQ(ierr); 2719 #endif 2720 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr); 2721 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaij_seqdense_C",MatMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2722 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaij_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2723 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaij_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2724 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_seqdense_C",MatPtAP_SeqDense_SeqDense);CHKERRQ(ierr); 2725 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijperm_seqdense_C",MatMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2726 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijperm_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2727 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijperm_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2728 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijperm_seqdense_C",MatPtAP_SeqDense_SeqDense);CHKERRQ(ierr); 2729 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijmkl_seqdense_C",MatMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2730 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijmkl_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2731 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijmkl_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2732 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijmkl_seqdense_C",MatPtAP_SeqDense_SeqDense);CHKERRQ(ierr); 2733 2734 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaij_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2735 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2736 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaij_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2737 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijperm_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2738 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijperm_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2739 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijperm_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2740 2741 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijmkl_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr); 2742 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijmkl_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr); 2743 ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijmkl_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr); 2744 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumn_C",MatDenseGetColumn_SeqDense);CHKERRQ(ierr); 2745 ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumn_C",MatDenseRestoreColumn_SeqDense);CHKERRQ(ierr); 2746 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);CHKERRQ(ierr); 2747 PetscFunctionReturn(0); 2748 } 2749 2750 /*@C 2751 MatDenseGetColumn - gives access to a column of a dense matrix. This is only the local part of the column. You MUST call MatDenseRestoreColumn() to avoid memory bleeding. 2752 2753 Not Collective 2754 2755 Input Parameter: 2756 + mat - a MATSEQDENSE or MATMPIDENSE matrix 2757 - col - column index 2758 2759 Output Parameter: 2760 . vals - pointer to the data 2761 2762 Level: intermediate 2763 2764 .seealso: MatDenseRestoreColumn() 2765 @*/ 2766 PetscErrorCode MatDenseGetColumn(Mat A,PetscInt col,PetscScalar **vals) 2767 { 2768 PetscErrorCode ierr; 2769 2770 PetscFunctionBegin; 2771 ierr = PetscUseMethod(A,"MatDenseGetColumn_C",(Mat,PetscInt,PetscScalar**),(A,col,vals));CHKERRQ(ierr); 2772 PetscFunctionReturn(0); 2773 } 2774 2775 /*@C 2776 MatDenseRestoreColumn - returns access to a column of a dense matrix which is returned by MatDenseGetColumn(). 2777 2778 Not Collective 2779 2780 Input Parameter: 2781 . mat - a MATSEQDENSE or MATMPIDENSE matrix 2782 2783 Output Parameter: 2784 . vals - pointer to the data 2785 2786 Level: intermediate 2787 2788 .seealso: MatDenseGetColumn() 2789 @*/ 2790 PetscErrorCode MatDenseRestoreColumn(Mat A,PetscScalar **vals) 2791 { 2792 PetscErrorCode ierr; 2793 2794 PetscFunctionBegin; 2795 ierr = PetscUseMethod(A,"MatDenseRestoreColumn_C",(Mat,PetscScalar**),(A,vals));CHKERRQ(ierr); 2796 PetscFunctionReturn(0); 2797 } 2798