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