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