1 /* 2 Defines the basic matrix operations for sequential dense. 3 */ 4 5 #include "src/mat/impls/dense/seq/dense.h" 6 #include "petscblaslapack.h" 7 8 #undef __FUNCT__ 9 #define __FUNCT__ "MatAXPY_SeqDense" 10 PetscErrorCode MatAXPY_SeqDense(const PetscScalar *alpha,Mat X,Mat Y,MatStructure str) 11 { 12 Mat_SeqDense *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data; 13 PetscInt j; 14 PetscBLASInt N = (PetscBLASInt)X->m*X->n,m=(PetscBLASInt)X->m,ldax = x->lda,lday=y->lda,one = 1; 15 PetscErrorCode ierr; 16 17 PetscFunctionBegin; 18 if (X->m != Y->m || X->n != Y->n) SETERRQ(PETSC_ERR_ARG_SIZ,"size(B) != size(A)"); 19 if (ldax>m || lday>m) { 20 for (j=0; j<X->n; j++) { 21 BLASaxpy_(&m,(PetscScalar*)alpha,x->v+j*ldax,&one,y->v+j*lday,&one); 22 } 23 } else { 24 BLASaxpy_(&N,(PetscScalar*)alpha,x->v,&one,y->v,&one); 25 } 26 ierr = PetscLogFlops(2*N-1);CHKERRQ(ierr); 27 PetscFunctionReturn(0); 28 } 29 30 #undef __FUNCT__ 31 #define __FUNCT__ "MatGetInfo_SeqDense" 32 PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info) 33 { 34 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 35 PetscInt i,N = A->m*A->n,count = 0; 36 PetscScalar *v = a->v; 37 38 PetscFunctionBegin; 39 for (i=0; i<N; i++) {if (*v != 0.0) count++; v++;} 40 41 info->rows_global = (double)A->m; 42 info->columns_global = (double)A->n; 43 info->rows_local = (double)A->m; 44 info->columns_local = (double)A->n; 45 info->block_size = 1.0; 46 info->nz_allocated = (double)N; 47 info->nz_used = (double)count; 48 info->nz_unneeded = (double)(N-count); 49 info->assemblies = (double)A->num_ass; 50 info->mallocs = 0; 51 info->memory = A->mem; 52 info->fill_ratio_given = 0; 53 info->fill_ratio_needed = 0; 54 info->factor_mallocs = 0; 55 56 PetscFunctionReturn(0); 57 } 58 59 #undef __FUNCT__ 60 #define __FUNCT__ "MatScale_SeqDense" 61 PetscErrorCode MatScale_SeqDense(const PetscScalar *alpha,Mat A) 62 { 63 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 64 PetscBLASInt one = 1,lda = a->lda,j,nz; 65 PetscErrorCode ierr; 66 67 PetscFunctionBegin; 68 if (lda>A->m) { 69 nz = (PetscBLASInt)A->m; 70 for (j=0; j<A->n; j++) { 71 BLASscal_(&nz,(PetscScalar*)alpha,a->v+j*lda,&one); 72 } 73 } else { 74 nz = (PetscBLASInt)A->m*A->n; 75 BLASscal_(&nz,(PetscScalar*)alpha,a->v,&one); 76 } 77 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 78 PetscFunctionReturn(0); 79 } 80 81 /* ---------------------------------------------------------------*/ 82 /* COMMENT: I have chosen to hide row permutation in the pivots, 83 rather than put it in the Mat->row slot.*/ 84 #undef __FUNCT__ 85 #define __FUNCT__ "MatLUFactor_SeqDense" 86 PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,MatFactorInfo *minfo) 87 { 88 #if defined(PETSC_MISSING_LAPACK_GETRF) 89 PetscFunctionBegin; 90 SETERRQ(PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable."); 91 #else 92 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 93 PetscErrorCode ierr; 94 PetscBLASInt n = (PetscBLASInt)A->n,m = (PetscBLASInt)A->m,info; 95 96 PetscFunctionBegin; 97 if (!mat->pivots) { 98 ierr = PetscMalloc((A->m+1)*sizeof(PetscBLASInt),&mat->pivots);CHKERRQ(ierr); 99 ierr = PetscLogObjectMemory(A,A->m*sizeof(PetscBLASInt));CHKERRQ(ierr); 100 } 101 A->factor = FACTOR_LU; 102 if (!A->m || !A->n) PetscFunctionReturn(0); 103 LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info); 104 if (info<0) SETERRQ(PETSC_ERR_LIB,"Bad argument to LU factorization"); 105 if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization"); 106 ierr = PetscLogFlops((2*A->n*A->n*A->n)/3);CHKERRQ(ierr); 107 #endif 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "MatDuplicate_SeqDense" 113 PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat) 114 { 115 Mat_SeqDense *mat = (Mat_SeqDense*)A->data,*l; 116 PetscErrorCode ierr; 117 PetscInt lda = (PetscInt)mat->lda,j,m; 118 Mat newi; 119 120 PetscFunctionBegin; 121 ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&newi);CHKERRQ(ierr); 122 ierr = MatSetType(newi,A->type_name);CHKERRQ(ierr); 123 ierr = MatSeqDenseSetPreallocation(newi,PETSC_NULL);CHKERRQ(ierr); 124 if (cpvalues == MAT_COPY_VALUES) { 125 l = (Mat_SeqDense*)newi->data; 126 if (lda>A->m) { 127 m = A->m; 128 for (j=0; j<A->n; j++) { 129 ierr = PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr); 130 } 131 } else { 132 ierr = PetscMemcpy(l->v,mat->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr); 133 } 134 } 135 newi->assembled = PETSC_TRUE; 136 *newmat = newi; 137 PetscFunctionReturn(0); 138 } 139 140 #undef __FUNCT__ 141 #define __FUNCT__ "MatLUFactorSymbolic_SeqDense" 142 PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat A,IS row,IS col,MatFactorInfo *info,Mat *fact) 143 { 144 PetscErrorCode ierr; 145 146 PetscFunctionBegin; 147 ierr = MatDuplicate_SeqDense(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr); 148 PetscFunctionReturn(0); 149 } 150 151 #undef __FUNCT__ 152 #define __FUNCT__ "MatLUFactorNumeric_SeqDense" 153 PetscErrorCode MatLUFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact) 154 { 155 Mat_SeqDense *mat = (Mat_SeqDense*)A->data,*l = (Mat_SeqDense*)(*fact)->data; 156 PetscErrorCode ierr; 157 PetscInt lda1=mat->lda,lda2=l->lda, m=A->m,n=A->n, j; 158 MatFactorInfo info; 159 160 PetscFunctionBegin; 161 /* copy the numerical values */ 162 if (lda1>m || lda2>m ) { 163 for (j=0; j<n; j++) { 164 ierr = PetscMemcpy(l->v+j*lda2,mat->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr); 165 } 166 } else { 167 ierr = PetscMemcpy(l->v,mat->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr); 168 } 169 (*fact)->factor = 0; 170 ierr = MatLUFactor(*fact,0,0,&info);CHKERRQ(ierr); 171 PetscFunctionReturn(0); 172 } 173 174 #undef __FUNCT__ 175 #define __FUNCT__ "MatCholeskyFactorSymbolic_SeqDense" 176 PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat A,IS row,MatFactorInfo *info,Mat *fact) 177 { 178 PetscErrorCode ierr; 179 180 PetscFunctionBegin; 181 ierr = MatConvert(A,MATSAME,MAT_INITIAL_MATRIX,fact);CHKERRQ(ierr); 182 PetscFunctionReturn(0); 183 } 184 185 #undef __FUNCT__ 186 #define __FUNCT__ "MatCholeskyFactor_SeqDense" 187 PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,MatFactorInfo *factinfo) 188 { 189 #if defined(PETSC_MISSING_LAPACK_POTRF) 190 PetscFunctionBegin; 191 SETERRQ(PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable."); 192 #else 193 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 194 PetscErrorCode ierr; 195 PetscBLASInt n = (PetscBLASInt)A->n,info; 196 197 PetscFunctionBegin; 198 if (mat->pivots) { 199 ierr = PetscFree(mat->pivots);CHKERRQ(ierr); 200 ierr = PetscLogObjectMemory(A,-A->m*sizeof(PetscInt));CHKERRQ(ierr); 201 mat->pivots = 0; 202 } 203 if (!A->m || !A->n) PetscFunctionReturn(0); 204 LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info); 205 if (info) SETERRQ1(PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1); 206 A->factor = FACTOR_CHOLESKY; 207 ierr = PetscLogFlops((A->n*A->n*A->n)/3);CHKERRQ(ierr); 208 #endif 209 PetscFunctionReturn(0); 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "MatCholeskyFactorNumeric_SeqDense" 214 PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact) 215 { 216 PetscErrorCode ierr; 217 MatFactorInfo info; 218 219 PetscFunctionBegin; 220 info.fill = 1.0; 221 ierr = MatCholeskyFactor_SeqDense(*fact,0,&info);CHKERRQ(ierr); 222 PetscFunctionReturn(0); 223 } 224 225 #undef __FUNCT__ 226 #define __FUNCT__ "MatSolve_SeqDense" 227 PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy) 228 { 229 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 230 PetscErrorCode ierr; 231 PetscBLASInt m = (PetscBLASInt)A->m, one = 1,info; 232 PetscScalar *x,*y; 233 234 PetscFunctionBegin; 235 if (!A->m || !A->n) PetscFunctionReturn(0); 236 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 237 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 238 ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr); 239 if (A->factor == FACTOR_LU) { 240 #if defined(PETSC_MISSING_LAPACK_GETRS) 241 SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 242 #else 243 LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info); 244 if (info) SETERRQ(PETSC_ERR_LIB,"GETRS - Bad solve"); 245 #endif 246 } else if (A->factor == FACTOR_CHOLESKY){ 247 #if defined(PETSC_MISSING_LAPACK_POTRS) 248 SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 249 #else 250 LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info); 251 if (info) SETERRQ(PETSC_ERR_LIB,"POTRS Bad solve"); 252 #endif 253 } 254 else SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve"); 255 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 256 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 257 ierr = PetscLogFlops(2*A->n*A->n - A->n);CHKERRQ(ierr); 258 PetscFunctionReturn(0); 259 } 260 261 #undef __FUNCT__ 262 #define __FUNCT__ "MatSolveTranspose_SeqDense" 263 PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy) 264 { 265 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 266 PetscErrorCode ierr; 267 PetscBLASInt m = (PetscBLASInt) A->m,one = 1,info; 268 PetscScalar *x,*y; 269 270 PetscFunctionBegin; 271 if (!A->m || !A->n) PetscFunctionReturn(0); 272 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 273 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 274 ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr); 275 /* assume if pivots exist then use LU; else Cholesky */ 276 if (mat->pivots) { 277 #if defined(PETSC_MISSING_LAPACK_GETRS) 278 SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 279 #else 280 LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info); 281 if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve"); 282 #endif 283 } else { 284 #if defined(PETSC_MISSING_LAPACK_POTRS) 285 SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 286 #else 287 LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info); 288 if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve"); 289 #endif 290 } 291 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 292 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 293 ierr = PetscLogFlops(2*A->n*A->n - A->n);CHKERRQ(ierr); 294 PetscFunctionReturn(0); 295 } 296 297 #undef __FUNCT__ 298 #define __FUNCT__ "MatSolveAdd_SeqDense" 299 PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 300 { 301 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 302 PetscErrorCode ierr; 303 PetscBLASInt m = (PetscBLASInt)A->m,one = 1,info; 304 PetscScalar *x,*y,sone = 1.0; 305 Vec tmp = 0; 306 307 PetscFunctionBegin; 308 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 309 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 310 if (!A->m || !A->n) PetscFunctionReturn(0); 311 if (yy == zz) { 312 ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr); 313 ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr); 314 ierr = VecCopy(yy,tmp);CHKERRQ(ierr); 315 } 316 ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr); 317 /* assume if pivots exist then use LU; else Cholesky */ 318 if (mat->pivots) { 319 #if defined(PETSC_MISSING_LAPACK_GETRS) 320 SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 321 #else 322 LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info); 323 if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve"); 324 #endif 325 } else { 326 #if defined(PETSC_MISSING_LAPACK_POTRS) 327 SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 328 #else 329 LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info); 330 if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve"); 331 #endif 332 } 333 if (tmp) {ierr = VecAXPY(&sone,tmp,yy);CHKERRQ(ierr); ierr = VecDestroy(tmp);CHKERRQ(ierr);} 334 else {ierr = VecAXPY(&sone,zz,yy);CHKERRQ(ierr);} 335 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 336 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 337 ierr = PetscLogFlops(2*A->n*A->n);CHKERRQ(ierr); 338 PetscFunctionReturn(0); 339 } 340 341 #undef __FUNCT__ 342 #define __FUNCT__ "MatSolveTransposeAdd_SeqDense" 343 PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 344 { 345 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 346 PetscErrorCode ierr; 347 PetscBLASInt m = (PetscBLASInt)A->m,one = 1,info; 348 PetscScalar *x,*y,sone = 1.0; 349 Vec tmp; 350 351 PetscFunctionBegin; 352 if (!A->m || !A->n) PetscFunctionReturn(0); 353 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 354 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 355 if (yy == zz) { 356 ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr); 357 ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr); 358 ierr = VecCopy(yy,tmp);CHKERRQ(ierr); 359 } 360 ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr); 361 /* assume if pivots exist then use LU; else Cholesky */ 362 if (mat->pivots) { 363 #if defined(PETSC_MISSING_LAPACK_GETRS) 364 SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); 365 #else 366 LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info); 367 if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve"); 368 #endif 369 } else { 370 #if defined(PETSC_MISSING_LAPACK_POTRS) 371 SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable."); 372 #else 373 LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info); 374 if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve"); 375 #endif 376 } 377 if (tmp) { 378 ierr = VecAXPY(&sone,tmp,yy);CHKERRQ(ierr); 379 ierr = VecDestroy(tmp);CHKERRQ(ierr); 380 } else { 381 ierr = VecAXPY(&sone,zz,yy);CHKERRQ(ierr); 382 } 383 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 384 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 385 ierr = PetscLogFlops(2*A->n*A->n);CHKERRQ(ierr); 386 PetscFunctionReturn(0); 387 } 388 /* ------------------------------------------------------------------*/ 389 #undef __FUNCT__ 390 #define __FUNCT__ "MatRelax_SeqDense" 391 PetscErrorCode MatRelax_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx) 392 { 393 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 394 PetscScalar *x,*b,*v = mat->v,zero = 0.0,xt; 395 PetscErrorCode ierr; 396 PetscInt m = A->m,i; 397 #if !defined(PETSC_USE_COMPLEX) 398 PetscBLASInt bm = (PetscBLASInt)m, o = 1; 399 #endif 400 401 PetscFunctionBegin; 402 if (flag & SOR_ZERO_INITIAL_GUESS) { 403 /* this is a hack fix, should have another version without the second BLASdot */ 404 ierr = VecSet(&zero,xx);CHKERRQ(ierr); 405 } 406 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 407 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 408 its = its*lits; 409 if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 410 while (its--) { 411 if (flag & SOR_FORWARD_SWEEP){ 412 for (i=0; i<m; i++) { 413 #if defined(PETSC_USE_COMPLEX) 414 /* cannot use BLAS dot for complex because compiler/linker is 415 not happy about returning a double complex */ 416 PetscInt _i; 417 PetscScalar sum = b[i]; 418 for (_i=0; _i<m; _i++) { 419 sum -= PetscConj(v[i+_i*m])*x[_i]; 420 } 421 xt = sum; 422 #else 423 xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o); 424 #endif 425 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 426 } 427 } 428 if (flag & SOR_BACKWARD_SWEEP) { 429 for (i=m-1; i>=0; i--) { 430 #if defined(PETSC_USE_COMPLEX) 431 /* cannot use BLAS dot for complex because compiler/linker is 432 not happy about returning a double complex */ 433 PetscInt _i; 434 PetscScalar sum = b[i]; 435 for (_i=0; _i<m; _i++) { 436 sum -= PetscConj(v[i+_i*m])*x[_i]; 437 } 438 xt = sum; 439 #else 440 xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o); 441 #endif 442 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 443 } 444 } 445 } 446 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 447 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 448 PetscFunctionReturn(0); 449 } 450 451 /* -----------------------------------------------------------------*/ 452 #undef __FUNCT__ 453 #define __FUNCT__ "MatMultTranspose_SeqDense" 454 PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy) 455 { 456 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 457 PetscScalar *v = mat->v,*x,*y; 458 PetscErrorCode ierr; 459 PetscBLASInt m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n,_One=1; 460 PetscScalar _DOne=1.0,_DZero=0.0; 461 462 PetscFunctionBegin; 463 if (!A->m || !A->n) PetscFunctionReturn(0); 464 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 465 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 466 BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One); 467 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 468 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 469 ierr = PetscLogFlops(2*A->m*A->n - A->n);CHKERRQ(ierr); 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNCT__ 474 #define __FUNCT__ "MatMult_SeqDense" 475 PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy) 476 { 477 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 478 PetscScalar *v = mat->v,*x,*y,_DOne=1.0,_DZero=0.0; 479 PetscErrorCode ierr; 480 PetscBLASInt m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1; 481 482 PetscFunctionBegin; 483 if (!A->m || !A->n) PetscFunctionReturn(0); 484 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 485 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 486 BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One); 487 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 488 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 489 ierr = PetscLogFlops(2*A->m*A->n - A->m);CHKERRQ(ierr); 490 PetscFunctionReturn(0); 491 } 492 493 #undef __FUNCT__ 494 #define __FUNCT__ "MatMultAdd_SeqDense" 495 PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 496 { 497 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 498 PetscScalar *v = mat->v,*x,*y,_DOne=1.0; 499 PetscErrorCode ierr; 500 PetscBLASInt m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1; 501 502 PetscFunctionBegin; 503 if (!A->m || !A->n) PetscFunctionReturn(0); 504 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 505 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 506 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 507 BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One); 508 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 509 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 510 ierr = PetscLogFlops(2*A->m*A->n);CHKERRQ(ierr); 511 PetscFunctionReturn(0); 512 } 513 514 #undef __FUNCT__ 515 #define __FUNCT__ "MatMultTransposeAdd_SeqDense" 516 PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 517 { 518 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 519 PetscScalar *v = mat->v,*x,*y; 520 PetscErrorCode ierr; 521 PetscBLASInt m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1; 522 PetscScalar _DOne=1.0; 523 524 PetscFunctionBegin; 525 if (!A->m || !A->n) PetscFunctionReturn(0); 526 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 527 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 528 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 529 BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One); 530 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 531 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 532 ierr = PetscLogFlops(2*A->m*A->n);CHKERRQ(ierr); 533 PetscFunctionReturn(0); 534 } 535 536 /* -----------------------------------------------------------------*/ 537 #undef __FUNCT__ 538 #define __FUNCT__ "MatGetRow_SeqDense" 539 PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals) 540 { 541 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 542 PetscScalar *v; 543 PetscErrorCode ierr; 544 PetscInt i; 545 546 PetscFunctionBegin; 547 *ncols = A->n; 548 if (cols) { 549 ierr = PetscMalloc((A->n+1)*sizeof(PetscInt),cols);CHKERRQ(ierr); 550 for (i=0; i<A->n; i++) (*cols)[i] = i; 551 } 552 if (vals) { 553 ierr = PetscMalloc((A->n+1)*sizeof(PetscScalar),vals);CHKERRQ(ierr); 554 v = mat->v + row; 555 for (i=0; i<A->n; i++) {(*vals)[i] = *v; v += mat->lda;} 556 } 557 PetscFunctionReturn(0); 558 } 559 560 #undef __FUNCT__ 561 #define __FUNCT__ "MatRestoreRow_SeqDense" 562 PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals) 563 { 564 PetscErrorCode ierr; 565 PetscFunctionBegin; 566 if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);} 567 if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); } 568 PetscFunctionReturn(0); 569 } 570 /* ----------------------------------------------------------------*/ 571 #undef __FUNCT__ 572 #define __FUNCT__ "MatSetValues_SeqDense" 573 PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv) 574 { 575 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 576 PetscInt i,j,idx=0; 577 578 PetscFunctionBegin; 579 if (!mat->roworiented) { 580 if (addv == INSERT_VALUES) { 581 for (j=0; j<n; j++) { 582 if (indexn[j] < 0) {idx += m; continue;} 583 #if defined(PETSC_USE_DEBUG) 584 if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1); 585 #endif 586 for (i=0; i<m; i++) { 587 if (indexm[i] < 0) {idx++; continue;} 588 #if defined(PETSC_USE_DEBUG) 589 if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1); 590 #endif 591 mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++]; 592 } 593 } 594 } else { 595 for (j=0; j<n; j++) { 596 if (indexn[j] < 0) {idx += m; continue;} 597 #if defined(PETSC_USE_DEBUG) 598 if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1); 599 #endif 600 for (i=0; i<m; i++) { 601 if (indexm[i] < 0) {idx++; continue;} 602 #if defined(PETSC_USE_DEBUG) 603 if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1); 604 #endif 605 mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++]; 606 } 607 } 608 } 609 } else { 610 if (addv == INSERT_VALUES) { 611 for (i=0; i<m; i++) { 612 if (indexm[i] < 0) { idx += n; continue;} 613 #if defined(PETSC_USE_DEBUG) 614 if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1); 615 #endif 616 for (j=0; j<n; j++) { 617 if (indexn[j] < 0) { idx++; continue;} 618 #if defined(PETSC_USE_DEBUG) 619 if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1); 620 #endif 621 mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++]; 622 } 623 } 624 } else { 625 for (i=0; i<m; i++) { 626 if (indexm[i] < 0) { idx += n; continue;} 627 #if defined(PETSC_USE_DEBUG) 628 if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1); 629 #endif 630 for (j=0; j<n; j++) { 631 if (indexn[j] < 0) { idx++; continue;} 632 #if defined(PETSC_USE_DEBUG) 633 if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1); 634 #endif 635 mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++]; 636 } 637 } 638 } 639 } 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "MatGetValues_SeqDense" 645 PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[]) 646 { 647 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 648 PetscInt i,j; 649 PetscScalar *vpt = v; 650 651 PetscFunctionBegin; 652 /* row-oriented output */ 653 for (i=0; i<m; i++) { 654 for (j=0; j<n; j++) { 655 *vpt++ = mat->v[indexn[j]*mat->lda + indexm[i]]; 656 } 657 } 658 PetscFunctionReturn(0); 659 } 660 661 /* -----------------------------------------------------------------*/ 662 663 #include "petscsys.h" 664 665 #undef __FUNCT__ 666 #define __FUNCT__ "MatLoad_SeqDense" 667 PetscErrorCode MatLoad_SeqDense(PetscViewer viewer,const MatType type,Mat *A) 668 { 669 Mat_SeqDense *a; 670 Mat B; 671 PetscErrorCode ierr; 672 PetscInt *scols,i,j,nz,header[4]; 673 int fd; 674 PetscMPIInt size; 675 PetscInt *rowlengths = 0,M,N,*cols; 676 PetscScalar *vals,*svals,*v,*w; 677 MPI_Comm comm = ((PetscObject)viewer)->comm; 678 679 PetscFunctionBegin; 680 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 681 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor"); 682 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 683 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 684 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Not matrix object"); 685 M = header[1]; N = header[2]; nz = header[3]; 686 687 if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */ 688 ierr = MatCreate(comm,M,N,M,N,A);CHKERRQ(ierr); 689 ierr = MatSetType(*A,type);CHKERRQ(ierr); 690 ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr); 691 B = *A; 692 a = (Mat_SeqDense*)B->data; 693 v = a->v; 694 /* Allocate some temp space to read in the values and then flip them 695 from row major to column major */ 696 ierr = PetscMalloc((M*N > 0 ? M*N : 1)*sizeof(PetscScalar),&w);CHKERRQ(ierr); 697 /* read in nonzero values */ 698 ierr = PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);CHKERRQ(ierr); 699 /* now flip the values and store them in the matrix*/ 700 for (j=0; j<N; j++) { 701 for (i=0; i<M; i++) { 702 *v++ =w[i*N+j]; 703 } 704 } 705 ierr = PetscFree(w);CHKERRQ(ierr); 706 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 707 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 708 } else { 709 /* read row lengths */ 710 ierr = PetscMalloc((M+1)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 711 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 712 713 /* create our matrix */ 714 ierr = MatCreate(comm,M,N,M,N,A);CHKERRQ(ierr); 715 ierr = MatSetType(*A,type);CHKERRQ(ierr); 716 ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr); 717 B = *A; 718 a = (Mat_SeqDense*)B->data; 719 v = a->v; 720 721 /* read column indices and nonzeros */ 722 ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&scols);CHKERRQ(ierr); 723 cols = scols; 724 ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr); 725 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&svals);CHKERRQ(ierr); 726 vals = svals; 727 ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 728 729 /* insert into matrix */ 730 for (i=0; i<M; i++) { 731 for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j]; 732 svals += rowlengths[i]; scols += rowlengths[i]; 733 } 734 ierr = PetscFree(vals);CHKERRQ(ierr); 735 ierr = PetscFree(cols);CHKERRQ(ierr); 736 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 737 738 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 739 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 740 } 741 PetscFunctionReturn(0); 742 } 743 744 #include "petscsys.h" 745 746 #undef __FUNCT__ 747 #define __FUNCT__ "MatView_SeqDense_ASCII" 748 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer) 749 { 750 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 751 PetscErrorCode ierr; 752 PetscInt i,j; 753 char *name; 754 PetscScalar *v; 755 PetscViewerFormat format; 756 757 PetscFunctionBegin; 758 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 759 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 760 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 761 PetscFunctionReturn(0); /* do nothing for now */ 762 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 763 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 764 for (i=0; i<A->m; i++) { 765 v = a->v + i; 766 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 767 for (j=0; j<A->n; j++) { 768 #if defined(PETSC_USE_COMPLEX) 769 if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) { 770 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr); 771 } else if (PetscRealPart(*v)) { 772 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,PetscRealPart(*v));CHKERRQ(ierr); 773 } 774 #else 775 if (*v) { 776 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,*v);CHKERRQ(ierr); 777 } 778 #endif 779 v += a->lda; 780 } 781 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 782 } 783 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 784 } else { 785 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 786 #if defined(PETSC_USE_COMPLEX) 787 PetscTruth allreal = PETSC_TRUE; 788 /* determine if matrix has all real values */ 789 v = a->v; 790 for (i=0; i<A->m*A->n; i++) { 791 if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break ;} 792 } 793 #endif 794 if (format == PETSC_VIEWER_ASCII_MATLAB) { 795 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 796 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->m,A->n);CHKERRQ(ierr); 797 ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->m,A->n);CHKERRQ(ierr); 798 ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr); 799 } 800 801 for (i=0; i<A->m; i++) { 802 v = a->v + i; 803 for (j=0; j<A->n; j++) { 804 #if defined(PETSC_USE_COMPLEX) 805 if (allreal) { 806 ierr = PetscViewerASCIIPrintf(viewer,"%6.4e ",PetscRealPart(*v));CHKERRQ(ierr); 807 } else { 808 ierr = PetscViewerASCIIPrintf(viewer,"%6.4e + %6.4e i ",PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr); 809 } 810 #else 811 ierr = PetscViewerASCIIPrintf(viewer,"%6.4e ",*v);CHKERRQ(ierr); 812 #endif 813 v += a->lda; 814 } 815 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 816 } 817 if (format == PETSC_VIEWER_ASCII_MATLAB) { 818 ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr); 819 } 820 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 821 } 822 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 823 PetscFunctionReturn(0); 824 } 825 826 #undef __FUNCT__ 827 #define __FUNCT__ "MatView_SeqDense_Binary" 828 static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer) 829 { 830 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 831 PetscErrorCode ierr; 832 int fd; 833 PetscInt ict,j,n = A->n,m = A->m,i,*col_lens,nz = m*n; 834 PetscScalar *v,*anonz,*vals; 835 PetscViewerFormat format; 836 837 PetscFunctionBegin; 838 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 839 840 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 841 if (format == PETSC_VIEWER_BINARY_NATIVE) { 842 /* store the matrix as a dense matrix */ 843 ierr = PetscMalloc(4*sizeof(PetscInt),&col_lens);CHKERRQ(ierr); 844 col_lens[0] = MAT_FILE_COOKIE; 845 col_lens[1] = m; 846 col_lens[2] = n; 847 col_lens[3] = MATRIX_BINARY_FORMAT_DENSE; 848 ierr = PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 849 ierr = PetscFree(col_lens);CHKERRQ(ierr); 850 851 /* write out matrix, by rows */ 852 ierr = PetscMalloc((m*n+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr); 853 v = a->v; 854 for (i=0; i<m; i++) { 855 for (j=0; j<n; j++) { 856 vals[i + j*m] = *v++; 857 } 858 } 859 ierr = PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 860 ierr = PetscFree(vals);CHKERRQ(ierr); 861 } else { 862 ierr = PetscMalloc((4+nz)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr); 863 col_lens[0] = MAT_FILE_COOKIE; 864 col_lens[1] = m; 865 col_lens[2] = n; 866 col_lens[3] = nz; 867 868 /* store lengths of each row and write (including header) to file */ 869 for (i=0; i<m; i++) col_lens[4+i] = n; 870 ierr = PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 871 872 /* Possibly should write in smaller increments, not whole matrix at once? */ 873 /* store column indices (zero start index) */ 874 ict = 0; 875 for (i=0; i<m; i++) { 876 for (j=0; j<n; j++) col_lens[ict++] = j; 877 } 878 ierr = PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 879 ierr = PetscFree(col_lens);CHKERRQ(ierr); 880 881 /* store nonzero values */ 882 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&anonz);CHKERRQ(ierr); 883 ict = 0; 884 for (i=0; i<m; i++) { 885 v = a->v + i; 886 for (j=0; j<n; j++) { 887 anonz[ict++] = *v; v += a->lda; 888 } 889 } 890 ierr = PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 891 ierr = PetscFree(anonz);CHKERRQ(ierr); 892 } 893 PetscFunctionReturn(0); 894 } 895 896 #undef __FUNCT__ 897 #define __FUNCT__ "MatView_SeqDense_Draw_Zoom" 898 PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa) 899 { 900 Mat A = (Mat) Aa; 901 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 902 PetscErrorCode ierr; 903 PetscInt m = A->m,n = A->n,color,i,j; 904 PetscScalar *v = a->v; 905 PetscViewer viewer; 906 PetscDraw popup; 907 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,scale,maxv = 0.0; 908 PetscViewerFormat format; 909 910 PetscFunctionBegin; 911 912 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 913 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 914 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 915 916 /* Loop over matrix elements drawing boxes */ 917 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 918 /* Blue for negative and Red for positive */ 919 color = PETSC_DRAW_BLUE; 920 for(j = 0; j < n; j++) { 921 x_l = j; 922 x_r = x_l + 1.0; 923 for(i = 0; i < m; i++) { 924 y_l = m - i - 1.0; 925 y_r = y_l + 1.0; 926 #if defined(PETSC_USE_COMPLEX) 927 if (PetscRealPart(v[j*m+i]) > 0.) { 928 color = PETSC_DRAW_RED; 929 } else if (PetscRealPart(v[j*m+i]) < 0.) { 930 color = PETSC_DRAW_BLUE; 931 } else { 932 continue; 933 } 934 #else 935 if (v[j*m+i] > 0.) { 936 color = PETSC_DRAW_RED; 937 } else if (v[j*m+i] < 0.) { 938 color = PETSC_DRAW_BLUE; 939 } else { 940 continue; 941 } 942 #endif 943 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 944 } 945 } 946 } else { 947 /* use contour shading to indicate magnitude of values */ 948 /* first determine max of all nonzero values */ 949 for(i = 0; i < m*n; i++) { 950 if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]); 951 } 952 scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv; 953 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 954 if (popup) {ierr = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);} 955 for(j = 0; j < n; j++) { 956 x_l = j; 957 x_r = x_l + 1.0; 958 for(i = 0; i < m; i++) { 959 y_l = m - i - 1.0; 960 y_r = y_l + 1.0; 961 color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(v[j*m+i])); 962 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 963 } 964 } 965 } 966 PetscFunctionReturn(0); 967 } 968 969 #undef __FUNCT__ 970 #define __FUNCT__ "MatView_SeqDense_Draw" 971 PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer) 972 { 973 PetscDraw draw; 974 PetscTruth isnull; 975 PetscReal xr,yr,xl,yl,h,w; 976 PetscErrorCode ierr; 977 978 PetscFunctionBegin; 979 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 980 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 981 if (isnull) PetscFunctionReturn(0); 982 983 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 984 xr = A->n; yr = A->m; h = yr/10.0; w = xr/10.0; 985 xr += w; yr += h; xl = -w; yl = -h; 986 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 987 ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr); 988 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 989 PetscFunctionReturn(0); 990 } 991 992 #undef __FUNCT__ 993 #define __FUNCT__ "MatView_SeqDense" 994 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer) 995 { 996 Mat_SeqDense *a = (Mat_SeqDense*)A->data; 997 PetscErrorCode ierr; 998 PetscTruth issocket,iascii,isbinary,isdraw; 999 1000 PetscFunctionBegin; 1001 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr); 1002 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 1003 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr); 1004 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr); 1005 1006 if (issocket) { 1007 if (a->lda>A->m) SETERRQ(PETSC_ERR_SUP,"Case can not handle LDA"); 1008 ierr = PetscViewerSocketPutScalar(viewer,A->m,A->n,a->v);CHKERRQ(ierr); 1009 } else if (iascii) { 1010 ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr); 1011 } else if (isbinary) { 1012 ierr = MatView_SeqDense_Binary(A,viewer);CHKERRQ(ierr); 1013 } else if (isdraw) { 1014 ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr); 1015 } else { 1016 SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by dense matrix",((PetscObject)viewer)->type_name); 1017 } 1018 PetscFunctionReturn(0); 1019 } 1020 1021 #undef __FUNCT__ 1022 #define __FUNCT__ "MatDestroy_SeqDense" 1023 PetscErrorCode MatDestroy_SeqDense(Mat mat) 1024 { 1025 Mat_SeqDense *l = (Mat_SeqDense*)mat->data; 1026 PetscErrorCode ierr; 1027 1028 PetscFunctionBegin; 1029 #if defined(PETSC_USE_LOG) 1030 PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->m,mat->n); 1031 #endif 1032 if (l->pivots) {ierr = PetscFree(l->pivots);CHKERRQ(ierr);} 1033 if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);} 1034 ierr = PetscFree(l);CHKERRQ(ierr); 1035 ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatSeqDenseSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr); 1036 PetscFunctionReturn(0); 1037 } 1038 1039 #undef __FUNCT__ 1040 #define __FUNCT__ "MatTranspose_SeqDense" 1041 PetscErrorCode MatTranspose_SeqDense(Mat A,Mat *matout) 1042 { 1043 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1044 PetscErrorCode ierr; 1045 PetscInt k,j,m,n,M; 1046 PetscScalar *v,tmp; 1047 1048 PetscFunctionBegin; 1049 v = mat->v; m = A->m; M = mat->lda; n = A->n; 1050 if (!matout) { /* in place transpose */ 1051 if (m != n) { 1052 SETERRQ(PETSC_ERR_SUP,"Can not transpose non-square matrix in place"); 1053 } else { 1054 for (j=0; j<m; j++) { 1055 for (k=0; k<j; k++) { 1056 tmp = v[j + k*M]; 1057 v[j + k*M] = v[k + j*M]; 1058 v[k + j*M] = tmp; 1059 } 1060 } 1061 } 1062 } else { /* out-of-place transpose */ 1063 Mat tmat; 1064 Mat_SeqDense *tmatd; 1065 PetscScalar *v2; 1066 1067 ierr = MatCreate(A->comm,A->n,A->m,A->n,A->m,&tmat);CHKERRQ(ierr); 1068 ierr = MatSetType(tmat,A->type_name);CHKERRQ(ierr); 1069 ierr = MatSeqDenseSetPreallocation(tmat,PETSC_NULL);CHKERRQ(ierr); 1070 tmatd = (Mat_SeqDense*)tmat->data; 1071 v = mat->v; v2 = tmatd->v; 1072 for (j=0; j<n; j++) { 1073 for (k=0; k<m; k++) v2[j + k*n] = v[k + j*M]; 1074 } 1075 ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1076 ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1077 *matout = tmat; 1078 } 1079 PetscFunctionReturn(0); 1080 } 1081 1082 #undef __FUNCT__ 1083 #define __FUNCT__ "MatEqual_SeqDense" 1084 PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscTruth *flg) 1085 { 1086 Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data; 1087 Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data; 1088 PetscInt i,j; 1089 PetscScalar *v1 = mat1->v,*v2 = mat2->v; 1090 1091 PetscFunctionBegin; 1092 if (A1->m != A2->m) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1093 if (A1->n != A2->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1094 for (i=0; i<A1->m; i++) { 1095 v1 = mat1->v+i; v2 = mat2->v+i; 1096 for (j=0; j<A1->n; j++) { 1097 if (*v1 != *v2) {*flg = PETSC_FALSE; PetscFunctionReturn(0);} 1098 v1 += mat1->lda; v2 += mat2->lda; 1099 } 1100 } 1101 *flg = PETSC_TRUE; 1102 PetscFunctionReturn(0); 1103 } 1104 1105 #undef __FUNCT__ 1106 #define __FUNCT__ "MatGetDiagonal_SeqDense" 1107 PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v) 1108 { 1109 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1110 PetscErrorCode ierr; 1111 PetscInt i,n,len; 1112 PetscScalar *x,zero = 0.0; 1113 1114 PetscFunctionBegin; 1115 ierr = VecSet(&zero,v);CHKERRQ(ierr); 1116 ierr = VecGetSize(v,&n);CHKERRQ(ierr); 1117 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1118 len = PetscMin(A->m,A->n); 1119 if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec"); 1120 for (i=0; i<len; i++) { 1121 x[i] = mat->v[i*mat->lda + i]; 1122 } 1123 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1124 PetscFunctionReturn(0); 1125 } 1126 1127 #undef __FUNCT__ 1128 #define __FUNCT__ "MatDiagonalScale_SeqDense" 1129 PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr) 1130 { 1131 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1132 PetscScalar *l,*r,x,*v; 1133 PetscErrorCode ierr; 1134 PetscInt i,j,m = A->m,n = A->n; 1135 1136 PetscFunctionBegin; 1137 if (ll) { 1138 ierr = VecGetSize(ll,&m);CHKERRQ(ierr); 1139 ierr = VecGetArray(ll,&l);CHKERRQ(ierr); 1140 if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size"); 1141 for (i=0; i<m; i++) { 1142 x = l[i]; 1143 v = mat->v + i; 1144 for (j=0; j<n; j++) { (*v) *= x; v+= m;} 1145 } 1146 ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr); 1147 ierr = PetscLogFlops(n*m);CHKERRQ(ierr); 1148 } 1149 if (rr) { 1150 ierr = VecGetSize(rr,&n);CHKERRQ(ierr); 1151 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 1152 if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size"); 1153 for (i=0; i<n; i++) { 1154 x = r[i]; 1155 v = mat->v + i*m; 1156 for (j=0; j<m; j++) { (*v++) *= x;} 1157 } 1158 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 1159 ierr = PetscLogFlops(n*m);CHKERRQ(ierr); 1160 } 1161 PetscFunctionReturn(0); 1162 } 1163 1164 #undef __FUNCT__ 1165 #define __FUNCT__ "MatNorm_SeqDense" 1166 PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm) 1167 { 1168 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1169 PetscScalar *v = mat->v; 1170 PetscReal sum = 0.0; 1171 PetscInt lda=mat->lda,m=A->m,i,j; 1172 PetscErrorCode ierr; 1173 1174 PetscFunctionBegin; 1175 if (type == NORM_FROBENIUS) { 1176 if (lda>m) { 1177 for (j=0; j<A->n; j++) { 1178 v = mat->v+j*lda; 1179 for (i=0; i<m; i++) { 1180 #if defined(PETSC_USE_COMPLEX) 1181 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1182 #else 1183 sum += (*v)*(*v); v++; 1184 #endif 1185 } 1186 } 1187 } else { 1188 for (i=0; i<A->n*A->m; i++) { 1189 #if defined(PETSC_USE_COMPLEX) 1190 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1191 #else 1192 sum += (*v)*(*v); v++; 1193 #endif 1194 } 1195 } 1196 *nrm = sqrt(sum); 1197 ierr = PetscLogFlops(2*A->n*A->m);CHKERRQ(ierr); 1198 } else if (type == NORM_1) { 1199 *nrm = 0.0; 1200 for (j=0; j<A->n; j++) { 1201 v = mat->v + j*mat->lda; 1202 sum = 0.0; 1203 for (i=0; i<A->m; i++) { 1204 sum += PetscAbsScalar(*v); v++; 1205 } 1206 if (sum > *nrm) *nrm = sum; 1207 } 1208 ierr = PetscLogFlops(A->n*A->m);CHKERRQ(ierr); 1209 } else if (type == NORM_INFINITY) { 1210 *nrm = 0.0; 1211 for (j=0; j<A->m; j++) { 1212 v = mat->v + j; 1213 sum = 0.0; 1214 for (i=0; i<A->n; i++) { 1215 sum += PetscAbsScalar(*v); v += mat->lda; 1216 } 1217 if (sum > *nrm) *nrm = sum; 1218 } 1219 ierr = PetscLogFlops(A->n*A->m);CHKERRQ(ierr); 1220 } else { 1221 SETERRQ(PETSC_ERR_SUP,"No two norm"); 1222 } 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "MatSetOption_SeqDense" 1228 PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op) 1229 { 1230 Mat_SeqDense *aij = (Mat_SeqDense*)A->data; 1231 1232 PetscFunctionBegin; 1233 switch (op) { 1234 case MAT_ROW_ORIENTED: 1235 aij->roworiented = PETSC_TRUE; 1236 break; 1237 case MAT_COLUMN_ORIENTED: 1238 aij->roworiented = PETSC_FALSE; 1239 break; 1240 case MAT_ROWS_SORTED: 1241 case MAT_ROWS_UNSORTED: 1242 case MAT_COLUMNS_SORTED: 1243 case MAT_COLUMNS_UNSORTED: 1244 case MAT_NO_NEW_NONZERO_LOCATIONS: 1245 case MAT_YES_NEW_NONZERO_LOCATIONS: 1246 case MAT_NEW_NONZERO_LOCATION_ERR: 1247 case MAT_NO_NEW_DIAGONALS: 1248 case MAT_YES_NEW_DIAGONALS: 1249 case MAT_IGNORE_OFF_PROC_ENTRIES: 1250 case MAT_USE_HASH_TABLE: 1251 PetscLogInfo(A,"MatSetOption_SeqDense:Option ignored\n"); 1252 break; 1253 case MAT_SYMMETRIC: 1254 case MAT_STRUCTURALLY_SYMMETRIC: 1255 case MAT_NOT_SYMMETRIC: 1256 case MAT_NOT_STRUCTURALLY_SYMMETRIC: 1257 case MAT_HERMITIAN: 1258 case MAT_NOT_HERMITIAN: 1259 case MAT_SYMMETRY_ETERNAL: 1260 case MAT_NOT_SYMMETRY_ETERNAL: 1261 break; 1262 default: 1263 SETERRQ(PETSC_ERR_SUP,"unknown option"); 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "MatZeroEntries_SeqDense" 1270 PetscErrorCode MatZeroEntries_SeqDense(Mat A) 1271 { 1272 Mat_SeqDense *l = (Mat_SeqDense*)A->data; 1273 PetscErrorCode ierr; 1274 PetscInt lda=l->lda,m=A->m,j; 1275 1276 PetscFunctionBegin; 1277 if (lda>m) { 1278 for (j=0; j<A->n; j++) { 1279 ierr = PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr); 1280 } 1281 } else { 1282 ierr = PetscMemzero(l->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr); 1283 } 1284 PetscFunctionReturn(0); 1285 } 1286 1287 #undef __FUNCT__ 1288 #define __FUNCT__ "MatZeroRows_SeqDense" 1289 PetscErrorCode MatZeroRows_SeqDense(Mat A,IS is,const PetscScalar *diag) 1290 { 1291 Mat_SeqDense *l = (Mat_SeqDense*)A->data; 1292 PetscErrorCode ierr; 1293 PetscInt n = A->n,i,j,N,*rows; 1294 PetscScalar *slot; 1295 1296 PetscFunctionBegin; 1297 ierr = ISGetLocalSize(is,&N);CHKERRQ(ierr); 1298 ierr = ISGetIndices(is,&rows);CHKERRQ(ierr); 1299 for (i=0; i<N; i++) { 1300 slot = l->v + rows[i]; 1301 for (j=0; j<n; j++) { *slot = 0.0; slot += n;} 1302 } 1303 if (diag) { 1304 for (i=0; i<N; i++) { 1305 slot = l->v + (n+1)*rows[i]; 1306 *slot = *diag; 1307 } 1308 } 1309 ISRestoreIndices(is,&rows); 1310 PetscFunctionReturn(0); 1311 } 1312 1313 #undef __FUNCT__ 1314 #define __FUNCT__ "MatGetArray_SeqDense" 1315 PetscErrorCode MatGetArray_SeqDense(Mat A,PetscScalar *array[]) 1316 { 1317 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1318 1319 PetscFunctionBegin; 1320 *array = mat->v; 1321 PetscFunctionReturn(0); 1322 } 1323 1324 #undef __FUNCT__ 1325 #define __FUNCT__ "MatRestoreArray_SeqDense" 1326 PetscErrorCode MatRestoreArray_SeqDense(Mat A,PetscScalar *array[]) 1327 { 1328 PetscFunctionBegin; 1329 *array = 0; /* user cannot accidently use the array later */ 1330 PetscFunctionReturn(0); 1331 } 1332 1333 #undef __FUNCT__ 1334 #define __FUNCT__ "MatGetSubMatrix_SeqDense" 1335 static PetscErrorCode MatGetSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B) 1336 { 1337 Mat_SeqDense *mat = (Mat_SeqDense*)A->data; 1338 PetscErrorCode ierr; 1339 PetscInt i,j,m = A->m,*irow,*icol,nrows,ncols; 1340 PetscScalar *av,*bv,*v = mat->v; 1341 Mat newmat; 1342 1343 PetscFunctionBegin; 1344 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 1345 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 1346 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 1347 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 1348 1349 /* Check submatrixcall */ 1350 if (scall == MAT_REUSE_MATRIX) { 1351 PetscInt n_cols,n_rows; 1352 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 1353 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 1354 newmat = *B; 1355 } else { 1356 /* Create and fill new matrix */ 1357 ierr = MatCreate(A->comm,nrows,ncols,nrows,ncols,&newmat);CHKERRQ(ierr); 1358 ierr = MatSetType(newmat,A->type_name);CHKERRQ(ierr); 1359 ierr = MatSeqDenseSetPreallocation(newmat,PETSC_NULL);CHKERRQ(ierr); 1360 } 1361 1362 /* Now extract the data pointers and do the copy,column at a time */ 1363 bv = ((Mat_SeqDense*)newmat->data)->v; 1364 1365 for (i=0; i<ncols; i++) { 1366 av = v + m*icol[i]; 1367 for (j=0; j<nrows; j++) { 1368 *bv++ = av[irow[j]]; 1369 } 1370 } 1371 1372 /* Assemble the matrices so that the correct flags are set */ 1373 ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1374 ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1375 1376 /* Free work space */ 1377 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 1378 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 1379 *B = newmat; 1380 PetscFunctionReturn(0); 1381 } 1382 1383 #undef __FUNCT__ 1384 #define __FUNCT__ "MatGetSubMatrices_SeqDense" 1385 PetscErrorCode MatGetSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 1386 { 1387 PetscErrorCode ierr; 1388 PetscInt i; 1389 1390 PetscFunctionBegin; 1391 if (scall == MAT_INITIAL_MATRIX) { 1392 ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr); 1393 } 1394 1395 for (i=0; i<n; i++) { 1396 ierr = MatGetSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 1397 } 1398 PetscFunctionReturn(0); 1399 } 1400 1401 #undef __FUNCT__ 1402 #define __FUNCT__ "MatCopy_SeqDense" 1403 PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str) 1404 { 1405 Mat_SeqDense *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense *)B->data; 1406 PetscErrorCode ierr; 1407 PetscInt lda1=a->lda,lda2=b->lda, m=A->m,n=A->n, j; 1408 1409 PetscFunctionBegin; 1410 /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 1411 if (A->ops->copy != B->ops->copy) { 1412 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 1413 PetscFunctionReturn(0); 1414 } 1415 if (m != B->m || n != B->n) SETERRQ(PETSC_ERR_ARG_SIZ,"size(B) != size(A)"); 1416 if (lda1>m || lda2>m) { 1417 for (j=0; j<n; j++) { 1418 ierr = PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr); 1419 } 1420 } else { 1421 ierr = PetscMemcpy(b->v,a->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr); 1422 } 1423 PetscFunctionReturn(0); 1424 } 1425 1426 #undef __FUNCT__ 1427 #define __FUNCT__ "MatSetUpPreallocation_SeqDense" 1428 PetscErrorCode MatSetUpPreallocation_SeqDense(Mat A) 1429 { 1430 PetscErrorCode ierr; 1431 1432 PetscFunctionBegin; 1433 ierr = MatSeqDenseSetPreallocation(A,0);CHKERRQ(ierr); 1434 PetscFunctionReturn(0); 1435 } 1436 1437 /* -------------------------------------------------------------------*/ 1438 static struct _MatOps MatOps_Values = {MatSetValues_SeqDense, 1439 MatGetRow_SeqDense, 1440 MatRestoreRow_SeqDense, 1441 MatMult_SeqDense, 1442 /* 4*/ MatMultAdd_SeqDense, 1443 MatMultTranspose_SeqDense, 1444 MatMultTransposeAdd_SeqDense, 1445 MatSolve_SeqDense, 1446 MatSolveAdd_SeqDense, 1447 MatSolveTranspose_SeqDense, 1448 /*10*/ MatSolveTransposeAdd_SeqDense, 1449 MatLUFactor_SeqDense, 1450 MatCholeskyFactor_SeqDense, 1451 MatRelax_SeqDense, 1452 MatTranspose_SeqDense, 1453 /*15*/ MatGetInfo_SeqDense, 1454 MatEqual_SeqDense, 1455 MatGetDiagonal_SeqDense, 1456 MatDiagonalScale_SeqDense, 1457 MatNorm_SeqDense, 1458 /*20*/ 0, 1459 0, 1460 0, 1461 MatSetOption_SeqDense, 1462 MatZeroEntries_SeqDense, 1463 /*25*/ MatZeroRows_SeqDense, 1464 MatLUFactorSymbolic_SeqDense, 1465 MatLUFactorNumeric_SeqDense, 1466 MatCholeskyFactorSymbolic_SeqDense, 1467 MatCholeskyFactorNumeric_SeqDense, 1468 /*30*/ MatSetUpPreallocation_SeqDense, 1469 0, 1470 0, 1471 MatGetArray_SeqDense, 1472 MatRestoreArray_SeqDense, 1473 /*35*/ MatDuplicate_SeqDense, 1474 0, 1475 0, 1476 0, 1477 0, 1478 /*40*/ MatAXPY_SeqDense, 1479 MatGetSubMatrices_SeqDense, 1480 0, 1481 MatGetValues_SeqDense, 1482 MatCopy_SeqDense, 1483 /*45*/ 0, 1484 MatScale_SeqDense, 1485 0, 1486 0, 1487 0, 1488 /*50*/ 0, 1489 0, 1490 0, 1491 0, 1492 0, 1493 /*55*/ 0, 1494 0, 1495 0, 1496 0, 1497 0, 1498 /*60*/ 0, 1499 MatDestroy_SeqDense, 1500 MatView_SeqDense, 1501 MatGetPetscMaps_Petsc, 1502 0, 1503 /*65*/ 0, 1504 0, 1505 0, 1506 0, 1507 0, 1508 /*70*/ 0, 1509 0, 1510 0, 1511 0, 1512 0, 1513 /*75*/ 0, 1514 0, 1515 0, 1516 0, 1517 0, 1518 /*80*/ 0, 1519 0, 1520 0, 1521 0, 1522 /*84*/ MatLoad_SeqDense, 1523 0, 1524 0, 1525 0, 1526 0, 1527 0, 1528 /*90*/ 0, 1529 0, 1530 0, 1531 0, 1532 0, 1533 /*95*/ 0, 1534 0, 1535 0, 1536 0}; 1537 1538 #undef __FUNCT__ 1539 #define __FUNCT__ "MatCreateSeqDense" 1540 /*@C 1541 MatCreateSeqDense - Creates a sequential dense matrix that 1542 is stored in column major order (the usual Fortran 77 manner). Many 1543 of the matrix operations use the BLAS and LAPACK routines. 1544 1545 Collective on MPI_Comm 1546 1547 Input Parameters: 1548 + comm - MPI communicator, set to PETSC_COMM_SELF 1549 . m - number of rows 1550 . n - number of columns 1551 - data - optional location of matrix data. Set data=PETSC_NULL for PETSc 1552 to control all matrix memory allocation. 1553 1554 Output Parameter: 1555 . A - the matrix 1556 1557 Notes: 1558 The data input variable is intended primarily for Fortran programmers 1559 who wish to allocate their own matrix memory space. Most users should 1560 set data=PETSC_NULL. 1561 1562 Level: intermediate 1563 1564 .keywords: dense, matrix, LAPACK, BLAS 1565 1566 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues() 1567 @*/ 1568 PetscErrorCode MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A) 1569 { 1570 PetscErrorCode ierr; 1571 1572 PetscFunctionBegin; 1573 ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr); 1574 ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr); 1575 ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr); 1576 PetscFunctionReturn(0); 1577 } 1578 1579 #undef __FUNCT__ 1580 #define __FUNCT__ "MatSeqDensePreallocation" 1581 /*@C 1582 MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements 1583 1584 Collective on MPI_Comm 1585 1586 Input Parameters: 1587 + A - the matrix 1588 - data - the array (or PETSC_NULL) 1589 1590 Notes: 1591 The data input variable is intended primarily for Fortran programmers 1592 who wish to allocate their own matrix memory space. Most users should 1593 set data=PETSC_NULL. 1594 1595 Level: intermediate 1596 1597 .keywords: dense, matrix, LAPACK, BLAS 1598 1599 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues() 1600 @*/ 1601 PetscErrorCode MatSeqDenseSetPreallocation(Mat B,PetscScalar data[]) 1602 { 1603 PetscErrorCode ierr,(*f)(Mat,PetscScalar[]); 1604 1605 PetscFunctionBegin; 1606 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 1607 if (f) { 1608 ierr = (*f)(B,data);CHKERRQ(ierr); 1609 } 1610 PetscFunctionReturn(0); 1611 } 1612 1613 EXTERN_C_BEGIN 1614 #undef __FUNCT__ 1615 #define __FUNCT__ "MatSeqDensePreallocation_SeqDense" 1616 PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data) 1617 { 1618 Mat_SeqDense *b; 1619 PetscErrorCode ierr; 1620 1621 PetscFunctionBegin; 1622 B->preallocated = PETSC_TRUE; 1623 b = (Mat_SeqDense*)B->data; 1624 if (!data) { 1625 ierr = PetscMalloc((B->m*B->n+1)*sizeof(PetscScalar),&b->v);CHKERRQ(ierr); 1626 ierr = PetscMemzero(b->v,B->m*B->n*sizeof(PetscScalar));CHKERRQ(ierr); 1627 b->user_alloc = PETSC_FALSE; 1628 ierr = PetscLogObjectMemory(B,B->n*B->m*sizeof(PetscScalar));CHKERRQ(ierr); 1629 } else { /* user-allocated storage */ 1630 b->v = data; 1631 b->user_alloc = PETSC_TRUE; 1632 } 1633 PetscFunctionReturn(0); 1634 } 1635 EXTERN_C_END 1636 1637 #undef __FUNCT__ 1638 #define __FUNCT__ "MatSeqDenseSetLDA" 1639 /*@C 1640 MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array 1641 1642 Input parameter: 1643 + A - the matrix 1644 - lda - the leading dimension 1645 1646 Notes: 1647 This routine is to be used in conjunction with MatSeqDenseSetPreallocation; 1648 it asserts that the preallocation has a leading dimension (the LDA parameter 1649 of Blas and Lapack fame) larger than M, the first dimension of the matrix. 1650 1651 Level: intermediate 1652 1653 .keywords: dense, matrix, LAPACK, BLAS 1654 1655 .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation() 1656 @*/ 1657 PetscErrorCode MatSeqDenseSetLDA(Mat B,PetscInt lda) 1658 { 1659 Mat_SeqDense *b = (Mat_SeqDense*)B->data; 1660 PetscFunctionBegin; 1661 if (lda < B->m) SETERRQ2(PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->m); 1662 b->lda = lda; 1663 PetscFunctionReturn(0); 1664 } 1665 1666 /*MC 1667 MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices. 1668 1669 Options Database Keys: 1670 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions() 1671 1672 Level: beginner 1673 1674 .seealso: MatCreateSeqDense 1675 M*/ 1676 1677 EXTERN_C_BEGIN 1678 #undef __FUNCT__ 1679 #define __FUNCT__ "MatCreate_SeqDense" 1680 PetscErrorCode MatCreate_SeqDense(Mat B) 1681 { 1682 Mat_SeqDense *b; 1683 PetscErrorCode ierr; 1684 PetscMPIInt size; 1685 1686 PetscFunctionBegin; 1687 ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr); 1688 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1"); 1689 1690 B->m = B->M = PetscMax(B->m,B->M); 1691 B->n = B->N = PetscMax(B->n,B->N); 1692 1693 ierr = PetscNew(Mat_SeqDense,&b);CHKERRQ(ierr); 1694 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1695 B->factor = 0; 1696 B->mapping = 0; 1697 ierr = PetscLogObjectMemory(B,sizeof(struct _p_Mat));CHKERRQ(ierr); 1698 B->data = (void*)b; 1699 1700 ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr); 1701 ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr); 1702 1703 b->pivots = 0; 1704 b->roworiented = PETSC_TRUE; 1705 b->v = 0; 1706 b->lda = B->m; 1707 1708 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqDenseSetPreallocation_C", 1709 "MatSeqDenseSetPreallocation_SeqDense", 1710 MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr); 1711 PetscFunctionReturn(0); 1712 } 1713 EXTERN_C_END 1714