1 #ifndef lint 2 static char vcid[] = "$Id: dense.c,v 1.60 1995/09/30 19:28:39 bsmith Exp bsmith $"; 3 #endif 4 5 /* 6 Standard Fortran style matrices 7 */ 8 #include "petsc.h" 9 #include "pinclude/plapack.h" 10 #include "matimpl.h" 11 #include "math.h" 12 #include "vec/vecimpl.h" 13 #include "pinclude/pviewer.h" 14 15 typedef struct { 16 Scalar *v; 17 int roworiented; 18 int m,n,pad; 19 int *pivots; /* pivots in LU factorization */ 20 } Mat_SeqDense; 21 22 static int MatGetInfo_SeqDense(Mat matin,MatInfoType flag,int *nz,int *nzalloc,int *mem) 23 { 24 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 25 int i,N = mat->m*mat->n,count = 0; 26 Scalar *v = mat->v; 27 for ( i=0; i<N; i++ ) {if (*v != 0.0) count++; v++;} 28 *nz = count; *nzalloc = N; *mem = (int)matin->mem; 29 return 0; 30 } 31 32 /* ---------------------------------------------------------------*/ 33 /* COMMENT: I have chosen to hide column permutation in the pivots, 34 rather than put it in the Mat->col slot.*/ 35 static int MatLUFactor_SeqDense(Mat matin,IS row,IS col,double f) 36 { 37 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 38 int info; 39 if (!mat->pivots) { 40 mat->pivots = (int *) PETSCMALLOC(mat->m*sizeof(int));CHKPTRQ(mat->pivots); 41 PLogObjectMemory(matin,mat->m*sizeof(int)); 42 } 43 LAgetrf_(&mat->m,&mat->n,mat->v,&mat->m,mat->pivots,&info); 44 if (info) SETERRQ(1,"MatLUFactor_SeqDense:Bad LU factorization"); 45 matin->factor = FACTOR_LU; 46 return 0; 47 } 48 static int MatLUFactorSymbolic_SeqDense(Mat matin,IS row,IS col,double f,Mat *fact) 49 { 50 int ierr; 51 ierr = MatConvert(matin,MATSAME,fact); CHKERRQ(ierr); 52 return 0; 53 } 54 static int MatLUFactorNumeric_SeqDense(Mat matin,Mat *fact) 55 { 56 return MatLUFactor(*fact,0,0,1.0); 57 } 58 static int MatCholeskyFactorSymbolic_SeqDense(Mat matin,IS row,double f,Mat *fact) 59 { 60 int ierr; 61 ierr = MatConvert(matin,MATSAME,fact); CHKERRQ(ierr); 62 return 0; 63 } 64 static int MatCholeskyFactorNumeric_SeqDense(Mat matin,Mat *fact) 65 { 66 return MatCholeskyFactor(*fact,0,1.0); 67 } 68 static int MatCholeskyFactor_SeqDense(Mat matin,IS perm,double f) 69 { 70 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 71 int info; 72 if (mat->pivots) { 73 PETSCFREE(mat->pivots); 74 PLogObjectMemory(matin,-mat->m*sizeof(int)); 75 mat->pivots = 0; 76 } 77 LApotrf_("L",&mat->n,mat->v,&mat->m,&info); 78 if (info) SETERRQ(1,"MatCholeskyFactor_SeqDense:Bad factorization"); 79 matin->factor = FACTOR_CHOLESKY; 80 return 0; 81 } 82 83 static int MatSolve_SeqDense(Mat matin,Vec xx,Vec yy) 84 { 85 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 86 int one = 1, info; 87 Scalar *x, *y; 88 VecGetArray(xx,&x); VecGetArray(yy,&y); 89 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 90 if (matin->factor == FACTOR_LU) { 91 LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 92 } 93 else if (matin->factor == FACTOR_CHOLESKY){ 94 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 95 } 96 else SETERRQ(1,"MatSolve_SeqDense:Matrix must be factored to solve"); 97 if (info) SETERRQ(1,"MatSolve_SeqDense:Bad solve"); 98 return 0; 99 } 100 static int MatSolveTrans_SeqDense(Mat matin,Vec xx,Vec yy) 101 { 102 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 103 int one = 1, info; 104 Scalar *x, *y; 105 VecGetArray(xx,&x); VecGetArray(yy,&y); 106 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 107 /* assume if pivots exist then use LU; else Cholesky */ 108 if (mat->pivots) { 109 LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 110 } 111 else { 112 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 113 } 114 if (info) SETERRQ(1,"MatSolveTrans_SeqDense:Bad solve"); 115 return 0; 116 } 117 static int MatSolveAdd_SeqDense(Mat matin,Vec xx,Vec zz,Vec yy) 118 { 119 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 120 int one = 1, info,ierr; 121 Scalar *x, *y, sone = 1.0; 122 Vec tmp = 0; 123 VecGetArray(xx,&x); VecGetArray(yy,&y); 124 if (yy == zz) { 125 ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr); 126 PLogObjectParent(matin,tmp); 127 ierr = VecCopy(yy,tmp); CHKERRQ(ierr); 128 } 129 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 130 /* assume if pivots exist then use LU; else Cholesky */ 131 if (mat->pivots) { 132 LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 133 } 134 else { 135 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 136 } 137 if (info) SETERRQ(1,"MatSolveAdd_SeqDense:Bad solve"); 138 if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);} 139 else VecAXPY(&sone,zz,yy); 140 return 0; 141 } 142 static int MatSolveTransAdd_SeqDense(Mat matin,Vec xx,Vec zz, Vec yy) 143 { 144 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 145 int one = 1, info,ierr; 146 Scalar *x, *y, sone = 1.0; 147 Vec tmp; 148 VecGetArray(xx,&x); VecGetArray(yy,&y); 149 if (yy == zz) { 150 ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr); 151 PLogObjectParent(matin,tmp); 152 ierr = VecCopy(yy,tmp); CHKERRQ(ierr); 153 } 154 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 155 /* assume if pivots exist then use LU; else Cholesky */ 156 if (mat->pivots) { 157 LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 158 } 159 else { 160 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 161 } 162 if (info) SETERRQ(1,"MatSolveTransAdd_SeqDense:Bad solve"); 163 if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);} 164 else VecAXPY(&sone,zz,yy); 165 return 0; 166 } 167 /* ------------------------------------------------------------------*/ 168 static int MatRelax_SeqDense(Mat matin,Vec bb,double omega,MatSORType flag, 169 double shift,int its,Vec xx) 170 { 171 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 172 Scalar *x, *b, *v = mat->v, zero = 0.0, xt; 173 int o = 1,ierr, m = mat->m, i; 174 175 if (flag & SOR_ZERO_INITIAL_GUESS) { 176 /* this is a hack fix, should have another version without 177 the second BLdot */ 178 ierr = VecSet(&zero,xx); CHKERRQ(ierr); 179 } 180 VecGetArray(xx,&x); VecGetArray(bb,&b); 181 while (its--) { 182 if (flag & SOR_FORWARD_SWEEP){ 183 for ( i=0; i<m; i++ ) { 184 #if defined(PETSC_COMPLEX) 185 /* cannot use BLAS dot for complex because compiler/linker is 186 not happy about returning a double complex */ 187 int _i; 188 Scalar sum = b[i]; 189 for ( _i=0; _i<m; _i++ ) { 190 sum -= conj(v[i+_i*m])*x[_i]; 191 } 192 xt = sum; 193 #else 194 xt = b[i]-BLdot_(&m,v+i,&m,x,&o); 195 #endif 196 x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]); 197 } 198 } 199 if (flag & SOR_BACKWARD_SWEEP) { 200 for ( i=m-1; i>=0; i-- ) { 201 #if defined(PETSC_COMPLEX) 202 /* cannot use BLAS dot for complex because compiler/linker is 203 not happy about returning a double complex */ 204 int _i; 205 Scalar sum = b[i]; 206 for ( _i=0; _i<m; _i++ ) { 207 sum -= conj(v[i+_i*m])*x[_i]; 208 } 209 xt = sum; 210 #else 211 xt = b[i]-BLdot_(&m,v+i,&m,x,&o); 212 #endif 213 x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]); 214 } 215 } 216 } 217 return 0; 218 } 219 220 /* -----------------------------------------------------------------*/ 221 static int MatMultTrans_SeqDense(Mat matin,Vec xx,Vec yy) 222 { 223 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 224 Scalar *v = mat->v, *x, *y; 225 int _One=1;Scalar _DOne=1.0, _DZero=0.0; 226 VecGetArray(xx,&x), VecGetArray(yy,&y); 227 LAgemv_("T",&(mat->m),&(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DZero,y,&_One); 228 return 0; 229 } 230 static int MatMult_SeqDense(Mat matin,Vec xx,Vec yy) 231 { 232 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 233 Scalar *v = mat->v, *x, *y; 234 int _One=1;Scalar _DOne=1.0, _DZero=0.0; 235 VecGetArray(xx,&x); VecGetArray(yy,&y); 236 LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DZero,y,&_One); 237 return 0; 238 } 239 static int MatMultAdd_SeqDense(Mat matin,Vec xx,Vec zz,Vec yy) 240 { 241 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 242 Scalar *v = mat->v, *x, *y, *z; 243 int _One=1; Scalar _DOne=1.0; 244 VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z); 245 if (zz != yy) PetscMemcpy(y,z,mat->m*sizeof(Scalar)); 246 LAgemv_( "N", &(mat->m), &(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DOne,y,&_One); 247 return 0; 248 } 249 static int MatMultTransAdd_SeqDense(Mat matin,Vec xx,Vec zz,Vec yy) 250 { 251 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 252 Scalar *v = mat->v, *x, *y, *z; 253 int _One=1; 254 Scalar _DOne=1.0; 255 VecGetArray(xx,&x); VecGetArray(yy,&y); 256 VecGetArray(zz,&z); 257 if (zz != yy) PetscMemcpy(y,z,mat->m*sizeof(Scalar)); 258 LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DOne,y,&_One); 259 return 0; 260 } 261 262 /* -----------------------------------------------------------------*/ 263 static int MatGetRow_SeqDense(Mat matin,int row,int *ncols,int **cols,Scalar **vals) 264 { 265 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 266 Scalar *v; 267 int i; 268 *ncols = mat->n; 269 if (cols) { 270 *cols = (int *) PETSCMALLOC(mat->n*sizeof(int)); CHKPTRQ(*cols); 271 for ( i=0; i<mat->n; i++ ) *cols[i] = i; 272 } 273 if (vals) { 274 *vals = (Scalar *) PETSCMALLOC(mat->n*sizeof(Scalar)); CHKPTRQ(*vals); 275 v = mat->v + row; 276 for ( i=0; i<mat->n; i++ ) {*vals[i] = *v; v += mat->m;} 277 } 278 return 0; 279 } 280 static int MatRestoreRow_SeqDense(Mat matin,int row,int *ncols,int **cols,Scalar **vals) 281 { 282 if (cols) { PETSCFREE(*cols); } 283 if (vals) { PETSCFREE(*vals); } 284 return 0; 285 } 286 /* ----------------------------------------------------------------*/ 287 static int MatInsert_SeqDense(Mat matin,int m,int *indexm,int n, 288 int *indexn,Scalar *v,InsertMode addv) 289 { 290 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 291 int i,j; 292 293 if (!mat->roworiented) { 294 if (addv == INSERT_VALUES) { 295 for ( j=0; j<n; j++ ) { 296 for ( i=0; i<m; i++ ) { 297 mat->v[indexn[j]*mat->m + indexm[i]] = *v++; 298 } 299 } 300 } 301 else { 302 for ( j=0; j<n; j++ ) { 303 for ( i=0; i<m; i++ ) { 304 mat->v[indexn[j]*mat->m + indexm[i]] += *v++; 305 } 306 } 307 } 308 } 309 else { 310 if (addv == INSERT_VALUES) { 311 for ( i=0; i<m; i++ ) { 312 for ( j=0; j<n; j++ ) { 313 mat->v[indexn[j]*mat->m + indexm[i]] = *v++; 314 } 315 } 316 } 317 else { 318 for ( i=0; i<m; i++ ) { 319 for ( j=0; j<n; j++ ) { 320 mat->v[indexn[j]*mat->m + indexm[i]] += *v++; 321 } 322 } 323 } 324 } 325 return 0; 326 } 327 328 /* -----------------------------------------------------------------*/ 329 static int MatCopyPrivate_SeqDense(Mat matin,Mat *newmat) 330 { 331 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data,*l; 332 int ierr; 333 Mat newi; 334 335 ierr = MatCreateSeqDense(matin->comm,mat->m,mat->n,&newi);CHKERRQ(ierr); 336 l = (Mat_SeqDense *) newi->data; 337 PetscMemcpy(l->v,mat->v,mat->m*mat->n*sizeof(Scalar)); 338 *newmat = newi; 339 return 0; 340 } 341 #include "viewer.h" 342 343 int MatView_SeqDense(PetscObject obj,Viewer ptr) 344 { 345 Mat matin = (Mat) obj; 346 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 347 Scalar *v; 348 int i,j,ierr; 349 PetscObject vobj = (PetscObject) ptr; 350 351 if (ptr == 0) { 352 ptr = STDOUT_VIEWER_SELF; vobj = (PetscObject) ptr; 353 } 354 if (vobj->cookie == VIEWER_COOKIE && vobj->type == MATLAB_VIEWER) { 355 return ViewerMatlabPutArray_Private(ptr,mat->m,mat->n,mat->v); 356 } 357 else { 358 FILE *fd; 359 int format; 360 ierr = ViewerFileGetPointer_Private(ptr,&fd); CHKERRQ(ierr); 361 ierr = ViewerFileGetFormat_Private(ptr,&format); CHKERRQ(ierr); 362 if (format == FILE_FORMAT_INFO) { 363 /* do nothing for now */ 364 } 365 else { 366 for ( i=0; i<mat->m; i++ ) { 367 v = mat->v + i; 368 for ( j=0; j<mat->n; j++ ) { 369 #if defined(PETSC_COMPLEX) 370 fprintf(fd,"%6.4e + %6.4e i ",real(*v),imag(*v)); v += mat->m; 371 #else 372 fprintf(fd,"%6.4e ",*v); v += mat->m; 373 #endif 374 } 375 fprintf(fd,"\n"); 376 } 377 } 378 } 379 return 0; 380 } 381 382 383 static int MatDestroy_SeqDense(PetscObject obj) 384 { 385 Mat mat = (Mat) obj; 386 Mat_SeqDense *l = (Mat_SeqDense *) mat->data; 387 #if defined(PETSC_LOG) 388 PLogObjectState(obj,"Rows %d Cols %d",l->m,l->n); 389 #endif 390 if (l->pivots) PETSCFREE(l->pivots); 391 PETSCFREE(l); 392 PLogObjectDestroy(mat); 393 PETSCHEADERDESTROY(mat); 394 return 0; 395 } 396 397 static int MatTranspose_SeqDense(Mat matin,Mat *matout) 398 { 399 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 400 int k, j, m, n; 401 Scalar *v, tmp; 402 403 v = mat->v; m = mat->m; n = mat->n; 404 if (!matout) { /* in place transpose */ 405 if (m != n) SETERRQ(1,"MatTranspose_SeqDense:Not for rectangular matrix in place"); 406 for ( j=0; j<m; j++ ) { 407 for ( k=0; k<j; k++ ) { 408 tmp = v[j + k*n]; 409 v[j + k*n] = v[k + j*n]; 410 v[k + j*n] = tmp; 411 } 412 } 413 } 414 else { /* out-of-place transpose */ 415 int ierr; 416 Mat tmat; 417 Mat_SeqDense *tmatd; 418 Scalar *v2; 419 ierr = MatCreateSeqDense(matin->comm,mat->n,mat->m,&tmat); CHKERRQ(ierr); 420 tmatd = (Mat_SeqDense *) tmat->data; 421 v = mat->v; v2 = tmatd->v; 422 for ( j=0; j<n; j++ ) { 423 for ( k=0; k<m; k++ ) v2[j + k*n] = v[k + j*m]; 424 } 425 ierr = MatAssemblyBegin(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr); 426 ierr = MatAssemblyEnd(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr); 427 *matout = tmat; 428 } 429 return 0; 430 } 431 432 static int MatEqual_SeqDense(Mat matin1,Mat matin2) 433 { 434 Mat_SeqDense *mat1 = (Mat_SeqDense *) matin1->data; 435 Mat_SeqDense *mat2 = (Mat_SeqDense *) matin2->data; 436 int i; 437 Scalar *v1 = mat1->v, *v2 = mat2->v; 438 if (mat1->m != mat2->m) return 0; 439 if (mat1->n != mat2->n) return 0; 440 for ( i=0; i<mat1->m*mat1->n; i++ ) { 441 if (*v1 != *v2) return 0; 442 v1++; v2++; 443 } 444 return 1; 445 } 446 447 static int MatGetDiagonal_SeqDense(Mat matin,Vec v) 448 { 449 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 450 int i, n; 451 Scalar *x; 452 VecGetArray(v,&x); VecGetSize(v,&n); 453 if (n != mat->m) SETERRQ(1,"MatGetDiagonal_SeqDense:Nonconforming mat and vec"); 454 for ( i=0; i<mat->m; i++ ) { 455 x[i] = mat->v[i*mat->m + i]; 456 } 457 return 0; 458 } 459 460 static int MatScale_SeqDense(Mat matin,Vec ll,Vec rr) 461 { 462 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 463 Scalar *l,*r,x,*v; 464 int i,j,m = mat->m, n = mat->n; 465 if (ll) { 466 VecGetArray(ll,&l); VecGetSize(ll,&m); 467 if (m != mat->m) SETERRQ(1,"MatScale_SeqDense:Left scaling vec wrong size"); 468 for ( i=0; i<m; i++ ) { 469 x = l[i]; 470 v = mat->v + i; 471 for ( j=0; j<n; j++ ) { (*v) *= x; v+= m;} 472 } 473 } 474 if (rr) { 475 VecGetArray(rr,&r); VecGetSize(rr,&n); 476 if (n != mat->n) SETERRQ(1,"MatScale_SeqDense:Right scaling vec wrong size"); 477 for ( i=0; i<n; i++ ) { 478 x = r[i]; 479 v = mat->v + i*m; 480 for ( j=0; j<m; j++ ) { (*v++) *= x;} 481 } 482 } 483 return 0; 484 } 485 486 static int MatNorm_SeqDense(Mat matin,MatNormType type,double *norm) 487 { 488 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 489 Scalar *v = mat->v; 490 double sum = 0.0; 491 int i, j; 492 if (type == NORM_FROBENIUS) { 493 for (i=0; i<mat->n*mat->m; i++ ) { 494 #if defined(PETSC_COMPLEX) 495 sum += real(conj(*v)*(*v)); v++; 496 #else 497 sum += (*v)*(*v); v++; 498 #endif 499 } 500 *norm = sqrt(sum); 501 } 502 else if (type == NORM_1) { 503 *norm = 0.0; 504 for ( j=0; j<mat->n; j++ ) { 505 sum = 0.0; 506 for ( i=0; i<mat->m; i++ ) { 507 #if defined(PETSC_COMPLEX) 508 sum += abs(*v++); 509 #else 510 sum += fabs(*v++); 511 #endif 512 } 513 if (sum > *norm) *norm = sum; 514 } 515 } 516 else if (type == NORM_INFINITY) { 517 *norm = 0.0; 518 for ( j=0; j<mat->m; j++ ) { 519 v = mat->v + j; 520 sum = 0.0; 521 for ( i=0; i<mat->n; i++ ) { 522 #if defined(PETSC_COMPLEX) 523 sum += abs(*v); v += mat->m; 524 #else 525 sum += fabs(*v); v += mat->m; 526 #endif 527 } 528 if (sum > *norm) *norm = sum; 529 } 530 } 531 else { 532 SETERRQ(1,"MatNorm_SeqDense:No two norm"); 533 } 534 return 0; 535 } 536 537 static int MatSetOption_SeqDense(Mat aijin,MatOption op) 538 { 539 Mat_SeqDense *aij = (Mat_SeqDense *) aijin->data; 540 if (op == ROW_ORIENTED) aij->roworiented = 1; 541 else if (op == COLUMN_ORIENTED) aij->roworiented = 0; 542 /* doesn't care about sorted rows or columns */ 543 return 0; 544 } 545 546 static int MatZeroEntries_SeqDense(Mat A) 547 { 548 Mat_SeqDense *l = (Mat_SeqDense *) A->data; 549 PetscZero(l->v,l->m*l->n*sizeof(Scalar)); 550 return 0; 551 } 552 553 static int MatZeroRows_SeqDense(Mat A,IS is,Scalar *diag) 554 { 555 Mat_SeqDense *l = (Mat_SeqDense *) A->data; 556 int n = l->n, i, j,ierr,N, *rows; 557 Scalar *slot; 558 ierr = ISGetLocalSize(is,&N); CHKERRQ(ierr); 559 ierr = ISGetIndices(is,&rows); CHKERRQ(ierr); 560 for ( i=0; i<N; i++ ) { 561 slot = l->v + rows[i]; 562 for ( j=0; j<n; j++ ) { *slot = 0.0; slot += n;} 563 } 564 if (diag) { 565 for ( i=0; i<N; i++ ) { 566 slot = l->v + (n+1)*rows[i]; 567 *slot = *diag; 568 } 569 } 570 ISRestoreIndices(is,&rows); 571 return 0; 572 } 573 574 static int MatGetSize_SeqDense(Mat matin,int *m,int *n) 575 { 576 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 577 *m = mat->m; *n = mat->n; 578 return 0; 579 } 580 581 static int MatGetOwnershipRange_SeqDense(Mat matin,int *m,int *n) 582 { 583 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 584 *m = 0; *n = mat->m; 585 return 0; 586 } 587 588 static int MatGetArray_SeqDense(Mat matin,Scalar **array) 589 { 590 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 591 *array = mat->v; 592 return 0; 593 } 594 595 596 static int MatGetSubMatrixInPlace_SeqDense(Mat matin,IS isrow,IS iscol) 597 { 598 SETERRQ(1,"MatGetSubMatrixInPlace_SeqDense:not done"); 599 } 600 601 static int MatGetSubMatrix_SeqDense(Mat matin,IS isrow,IS iscol,Mat *submat) 602 { 603 Mat_SeqDense *mat = (Mat_SeqDense *) matin->data; 604 int nznew, *smap, i, j, ierr, oldcols = mat->n; 605 int *irow, *icol, nrows, ncols, *cwork; 606 Scalar *vwork, *val; 607 Mat newmat; 608 609 ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr); 610 ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr); 611 ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr); 612 ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr); 613 614 smap = (int *) PETSCMALLOC(oldcols*sizeof(int)); CHKPTRQ(smap); 615 cwork = (int *) PETSCMALLOC(ncols*sizeof(int)); CHKPTRQ(cwork); 616 vwork = (Scalar *) PETSCMALLOC(ncols*sizeof(Scalar)); CHKPTRQ(vwork); 617 PetscZero((char*)smap,oldcols*sizeof(int)); 618 for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1; 619 620 /* Create and fill new matrix */ 621 ierr = MatCreateSeqDense(matin->comm,nrows,ncols,&newmat);CHKERRQ(ierr); 622 for (i=0; i<nrows; i++) { 623 nznew = 0; 624 val = mat->v + irow[i]; 625 for (j=0; j<oldcols; j++) { 626 if (smap[j]) { 627 cwork[nznew] = smap[j] - 1; 628 vwork[nznew++] = val[j * mat->m]; 629 } 630 } 631 ierr = MatSetValues(newmat,1,&i,nznew,cwork,vwork,INSERT_VALUES); 632 CHKERRQ(ierr); 633 } 634 ierr = MatAssemblyBegin(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr); 635 ierr = MatAssemblyEnd(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr); 636 637 /* Free work space */ 638 PETSCFREE(smap); PETSCFREE(cwork); PETSCFREE(vwork); 639 ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr); 640 ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr); 641 *submat = newmat; 642 return 0; 643 } 644 645 /* -------------------------------------------------------------------*/ 646 static struct _MatOps MatOps = {MatInsert_SeqDense, 647 MatGetRow_SeqDense, MatRestoreRow_SeqDense, 648 MatMult_SeqDense, MatMultAdd_SeqDense, 649 MatMultTrans_SeqDense, MatMultTransAdd_SeqDense, 650 MatSolve_SeqDense,MatSolveAdd_SeqDense, 651 MatSolveTrans_SeqDense,MatSolveTransAdd_SeqDense, 652 MatLUFactor_SeqDense,MatCholeskyFactor_SeqDense, 653 MatRelax_SeqDense, 654 MatTranspose_SeqDense, 655 MatGetInfo_SeqDense,MatEqual_SeqDense, 656 MatGetDiagonal_SeqDense,MatScale_SeqDense,MatNorm_SeqDense, 657 0,0, 658 0, MatSetOption_SeqDense,MatZeroEntries_SeqDense,MatZeroRows_SeqDense,0, 659 MatLUFactorSymbolic_SeqDense,MatLUFactorNumeric_SeqDense, 660 MatCholeskyFactorSymbolic_SeqDense,MatCholeskyFactorNumeric_SeqDense, 661 MatGetSize_SeqDense,MatGetSize_SeqDense,MatGetOwnershipRange_SeqDense, 662 0,0,MatGetArray_SeqDense,0,0, 663 MatGetSubMatrix_SeqDense,MatGetSubMatrixInPlace_SeqDense, 664 MatCopyPrivate_SeqDense}; 665 666 /*@C 667 MatCreateSeqDense - Creates a sequential dense matrix that 668 is stored in column major order (the usual Fortran 77 manner). Many 669 of the matrix operations use the BLAS and LAPACK routines. 670 671 Input Parameters: 672 . comm - MPI communicator, set to MPI_COMM_SELF 673 . m - number of rows 674 . n - number of column 675 676 Output Parameter: 677 . newmat - the matrix 678 679 .keywords: dense, matrix, LAPACK, BLAS 680 681 .seealso: MatCreate(), MatSetValues() 682 @*/ 683 int MatCreateSeqDense(MPI_Comm comm,int m,int n,Mat *newmat) 684 { 685 int size = sizeof(Mat_SeqDense) + m*n*sizeof(Scalar); 686 Mat mat; 687 Mat_SeqDense *l; 688 *newmat = 0; 689 PETSCHEADERCREATE(mat,_Mat,MAT_COOKIE,MATSEQDENSE,comm); 690 PLogObjectCreate(mat); 691 l = (Mat_SeqDense *) PETSCMALLOC(size); CHKPTRQ(l); 692 PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps)); 693 mat->destroy = MatDestroy_SeqDense; 694 mat->view = MatView_SeqDense; 695 mat->data = (void *) l; 696 mat->factor = 0; 697 PLogObjectMemory(mat,sizeof(struct _Mat) + size); 698 699 l->m = m; 700 l->n = n; 701 l->v = (Scalar *) (l + 1); 702 l->pivots = 0; 703 l->roworiented = 1; 704 705 PetscZero(l->v,m*n*sizeof(Scalar)); 706 *newmat = mat; 707 return 0; 708 } 709 710 int MatCreate_SeqDense(Mat matin,Mat *newmat) 711 { 712 Mat_SeqDense *m = (Mat_SeqDense *) matin->data; 713 return MatCreateSeqDense(matin->comm,m->m,m->n,newmat); 714 } 715