1 #ifndef lint 2 static char vcid[] = "$Id: dense.c,v 1.116 1996/12/08 20:50:35 bsmith Exp bsmith $"; 3 #endif 4 /* 5 Defines the basic matrix operations for sequential dense. 6 */ 7 8 #include "src/mat/impls/dense/seq/dense.h" 9 #include "pinclude/plapack.h" 10 #include "pinclude/pviewer.h" 11 12 int MatAXPY_SeqDense(Scalar *alpha,Mat X,Mat Y) 13 { 14 Mat_SeqDense *x = (Mat_SeqDense*) X->data,*y = (Mat_SeqDense*) Y->data; 15 int N = x->m*x->n, one = 1; 16 BLaxpy_( &N, alpha, x->v, &one, y->v, &one ); 17 PLogFlops(2*N-1); 18 return 0; 19 } 20 21 static int MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info) 22 { 23 Mat_SeqDense *a = (Mat_SeqDense *) A->data; 24 int i,N = a->m*a->n,count = 0; 25 Scalar *v = a->v; 26 for ( i=0; i<N; i++ ) {if (*v != 0.0) count++; v++;} 27 28 info->rows_global = (double)a->m; 29 info->columns_global = (double)a->n; 30 info->rows_local = (double)a->m; 31 info->columns_local = (double)a->n; 32 info->block_size = 1.0; 33 info->nz_allocated = (double)N; 34 info->nz_used = (double)count; 35 info->nz_unneeded = (double)(N-count); 36 info->assemblies = (double)A->num_ass; 37 info->mallocs = 0; 38 info->memory = A->mem; 39 info->fill_ratio_given = 0; 40 info->fill_ratio_needed = 0; 41 info->factor_mallocs = 0; 42 43 return 0; 44 } 45 46 static int MatScale_SeqDense(Scalar *alpha,Mat inA) 47 { 48 Mat_SeqDense *a = (Mat_SeqDense *) inA->data; 49 int one = 1, nz; 50 51 nz = a->m*a->n; 52 BLscal_( &nz, alpha, a->v, &one ); 53 PLogFlops(nz); 54 return 0; 55 } 56 57 /* ---------------------------------------------------------------*/ 58 /* COMMENT: I have chosen to hide column permutation in the pivots, 59 rather than put it in the Mat->col slot.*/ 60 static int MatLUFactor_SeqDense(Mat A,IS row,IS col,double f) 61 { 62 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 63 int info; 64 65 if (!mat->pivots) { 66 mat->pivots = (int *) PetscMalloc((mat->m+1)*sizeof(int));CHKPTRQ(mat->pivots); 67 PLogObjectMemory(A,mat->m*sizeof(int)); 68 } 69 LAgetrf_(&mat->m,&mat->n,mat->v,&mat->m,mat->pivots,&info); 70 if (info<0) SETERRQ(1,"MatLUFactor_SeqDense:Bad argument to LU factorization"); 71 if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"MatLUFactor_SeqDense:Bad LU factorization"); 72 A->factor = FACTOR_LU; 73 PLogFlops((2*mat->n*mat->n*mat->n)/3); 74 return 0; 75 } 76 static int MatConvertSameType_SeqDense(Mat A,Mat *newmat,int cpvalues) 77 { 78 Mat_SeqDense *mat = (Mat_SeqDense *) A->data, *l; 79 int ierr; 80 Mat newi; 81 82 ierr = MatCreateSeqDense(A->comm,mat->m,mat->n,PETSC_NULL,&newi); CHKERRQ(ierr); 83 l = (Mat_SeqDense *) newi->data; 84 if (cpvalues == COPY_VALUES) { 85 PetscMemcpy(l->v,mat->v,mat->m*mat->n*sizeof(Scalar)); 86 } 87 newi->assembled = PETSC_TRUE; 88 *newmat = newi; 89 return 0; 90 } 91 92 static int MatLUFactorSymbolic_SeqDense(Mat A,IS row,IS col,double f,Mat *fact) 93 { 94 return MatConvertSameType_SeqDense(A,fact,PETSC_FALSE); 95 } 96 static int MatLUFactorNumeric_SeqDense(Mat A,Mat *fact) 97 { 98 Mat_SeqDense *mat = (Mat_SeqDense*) A->data, *l = (Mat_SeqDense*) (*fact)->data; 99 /* copy the numerical values */ 100 PetscMemcpy(l->v,mat->v,mat->m*mat->n*sizeof(Scalar)); 101 (*fact)->factor = 0; 102 return MatLUFactor(*fact,0,0,1.0); 103 } 104 static int MatCholeskyFactorSymbolic_SeqDense(Mat A,IS row,double f,Mat *fact) 105 { 106 return MatConvert(A,MATSAME,fact); 107 } 108 static int MatCholeskyFactorNumeric_SeqDense(Mat A,Mat *fact) 109 { 110 return MatCholeskyFactor(*fact,0,1.0); 111 } 112 static int MatCholeskyFactor_SeqDense(Mat A,IS perm,double f) 113 { 114 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 115 int info; 116 117 if (mat->pivots) { 118 PetscFree(mat->pivots); 119 PLogObjectMemory(A,-mat->m*sizeof(int)); 120 mat->pivots = 0; 121 } 122 LApotrf_("L",&mat->n,mat->v,&mat->m,&info); 123 if (info) SETERRQ(PETSC_ERR_MAT_CH_ZRPVT,"MatCholeskyFactor_SeqDense:Bad factorization"); 124 A->factor = FACTOR_CHOLESKY; 125 PLogFlops((mat->n*mat->n*mat->n)/3); 126 return 0; 127 } 128 129 static int MatSolve_SeqDense(Mat A,Vec xx,Vec yy) 130 { 131 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 132 int one = 1, info, ierr; 133 Scalar *x, *y; 134 135 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); ierr = VecGetArray(yy,&y); CHKERRQ(ierr); 136 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 137 if (A->factor == FACTOR_LU) { 138 LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 139 } 140 else if (A->factor == FACTOR_CHOLESKY){ 141 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 142 } 143 else SETERRQ(1,"MatSolve_SeqDense:Matrix must be factored to solve"); 144 if (info) SETERRQ(1,"MatSolve_SeqDense:Bad solve"); 145 PLogFlops(mat->n*mat->n - mat->n); 146 return 0; 147 } 148 static int MatSolveTrans_SeqDense(Mat A,Vec xx,Vec yy) 149 { 150 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 151 int one = 1, info; 152 Scalar *x, *y; 153 154 VecGetArray(xx,&x); VecGetArray(yy,&y); 155 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 156 /* assume if pivots exist then use LU; else Cholesky */ 157 if (mat->pivots) { 158 LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 159 } 160 else { 161 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 162 } 163 if (info) SETERRQ(1,"MatSolveTrans_SeqDense:Bad solve"); 164 PLogFlops(mat->n*mat->n - mat->n); 165 return 0; 166 } 167 static int MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 168 { 169 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 170 int one = 1, info,ierr; 171 Scalar *x, *y, sone = 1.0; 172 Vec tmp = 0; 173 174 VecGetArray(xx,&x); VecGetArray(yy,&y); 175 if (yy == zz) { 176 ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr); 177 PLogObjectParent(A,tmp); 178 ierr = VecCopy(yy,tmp); CHKERRQ(ierr); 179 } 180 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 181 /* assume if pivots exist then use LU; else Cholesky */ 182 if (mat->pivots) { 183 LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 184 } 185 else { 186 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 187 } 188 if (info) SETERRQ(1,"MatSolveAdd_SeqDense:Bad solve"); 189 if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);} 190 else VecAXPY(&sone,zz,yy); 191 PLogFlops(mat->n*mat->n - mat->n); 192 return 0; 193 } 194 195 static int MatSolveTransAdd_SeqDense(Mat A,Vec xx,Vec zz, Vec yy) 196 { 197 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 198 int one = 1, info,ierr; 199 Scalar *x, *y, sone = 1.0; 200 Vec tmp; 201 202 VecGetArray(xx,&x); VecGetArray(yy,&y); 203 if (yy == zz) { 204 ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr); 205 PLogObjectParent(A,tmp); 206 ierr = VecCopy(yy,tmp); CHKERRQ(ierr); 207 } 208 PetscMemcpy(y,x,mat->m*sizeof(Scalar)); 209 /* assume if pivots exist then use LU; else Cholesky */ 210 if (mat->pivots) { 211 LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info ); 212 } 213 else { 214 LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info ); 215 } 216 if (info) SETERRQ(1,"MatSolveTransAdd_SeqDense:Bad solve"); 217 if (tmp) { 218 ierr = VecAXPY(&sone,tmp,yy); CHKERRQ(ierr); 219 ierr = VecDestroy(tmp); CHKERRQ(ierr); 220 } 221 else { 222 ierr = VecAXPY(&sone,zz,yy); CHKERRQ(ierr); 223 } 224 PLogFlops(mat->n*mat->n - mat->n); 225 return 0; 226 } 227 /* ------------------------------------------------------------------*/ 228 static int MatRelax_SeqDense(Mat A,Vec bb,double omega,MatSORType flag, 229 double shift,int its,Vec xx) 230 { 231 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 232 Scalar *x, *b, *v = mat->v, zero = 0.0, xt; 233 int o = 1,ierr, m = mat->m, i; 234 235 if (flag & SOR_ZERO_INITIAL_GUESS) { 236 /* this is a hack fix, should have another version without 237 the second BLdot */ 238 ierr = VecSet(&zero,xx); CHKERRQ(ierr); 239 } 240 VecGetArray(xx,&x); VecGetArray(bb,&b); 241 while (its--) { 242 if (flag & SOR_FORWARD_SWEEP){ 243 for ( i=0; i<m; i++ ) { 244 #if defined(PETSC_COMPLEX) 245 /* cannot use BLAS dot for complex because compiler/linker is 246 not happy about returning a double complex */ 247 int _i; 248 Scalar sum = b[i]; 249 for ( _i=0; _i<m; _i++ ) { 250 sum -= conj(v[i+_i*m])*x[_i]; 251 } 252 xt = sum; 253 #else 254 xt = b[i]-BLdot_(&m,v+i,&m,x,&o); 255 #endif 256 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 257 } 258 } 259 if (flag & SOR_BACKWARD_SWEEP) { 260 for ( i=m-1; i>=0; i-- ) { 261 #if defined(PETSC_COMPLEX) 262 /* cannot use BLAS dot for complex because compiler/linker is 263 not happy about returning a double complex */ 264 int _i; 265 Scalar sum = b[i]; 266 for ( _i=0; _i<m; _i++ ) { 267 sum -= conj(v[i+_i*m])*x[_i]; 268 } 269 xt = sum; 270 #else 271 xt = b[i]-BLdot_(&m,v+i,&m,x,&o); 272 #endif 273 x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift); 274 } 275 } 276 } 277 return 0; 278 } 279 280 /* -----------------------------------------------------------------*/ 281 int MatMultTrans_SeqDense(Mat A,Vec xx,Vec yy) 282 { 283 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 284 Scalar *v = mat->v, *x, *y; 285 int _One=1;Scalar _DOne=1.0, _DZero=0.0; 286 VecGetArray(xx,&x), VecGetArray(yy,&y); 287 LAgemv_("T",&(mat->m),&(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DZero,y,&_One); 288 PLogFlops(2*mat->m*mat->n - mat->n); 289 return 0; 290 } 291 int MatMult_SeqDense(Mat A,Vec xx,Vec yy) 292 { 293 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 294 Scalar *v = mat->v, *x, *y; 295 int _One=1;Scalar _DOne=1.0, _DZero=0.0; 296 VecGetArray(xx,&x); VecGetArray(yy,&y); 297 LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DZero,y,&_One); 298 PLogFlops(2*mat->m*mat->n - mat->m); 299 return 0; 300 } 301 int MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 302 { 303 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 304 Scalar *v = mat->v, *x, *y, *z; 305 int _One=1; Scalar _DOne=1.0; 306 VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z); 307 if (zz != yy) PetscMemcpy(y,z,mat->m*sizeof(Scalar)); 308 LAgemv_( "N", &(mat->m), &(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DOne,y,&_One); 309 PLogFlops(2*mat->m*mat->n); 310 return 0; 311 } 312 int MatMultTransAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy) 313 { 314 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 315 Scalar *v = mat->v, *x, *y, *z; 316 int _One=1; 317 Scalar _DOne=1.0; 318 VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z); 319 if (zz != yy) PetscMemcpy(y,z,mat->n*sizeof(Scalar)); 320 LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DOne,y,&_One); 321 PLogFlops(2*mat->m*mat->n); 322 return 0; 323 } 324 325 /* -----------------------------------------------------------------*/ 326 static int MatGetRow_SeqDense(Mat A,int row,int *ncols,int **cols,Scalar **vals) 327 { 328 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 329 Scalar *v; 330 int i; 331 332 *ncols = mat->n; 333 if (cols) { 334 *cols = (int *) PetscMalloc((mat->n+1)*sizeof(int)); CHKPTRQ(*cols); 335 for ( i=0; i<mat->n; i++ ) (*cols)[i] = i; 336 } 337 if (vals) { 338 *vals = (Scalar *) PetscMalloc((mat->n+1)*sizeof(Scalar)); CHKPTRQ(*vals); 339 v = mat->v + row; 340 for ( i=0; i<mat->n; i++ ) {(*vals)[i] = *v; v += mat->m;} 341 } 342 return 0; 343 } 344 static int MatRestoreRow_SeqDense(Mat A,int row,int *ncols,int **cols,Scalar **vals) 345 { 346 if (cols) { PetscFree(*cols); } 347 if (vals) { PetscFree(*vals); } 348 return 0; 349 } 350 /* ----------------------------------------------------------------*/ 351 static int MatSetValues_SeqDense(Mat A,int m,int *indexm,int n, 352 int *indexn,Scalar *v,InsertMode addv) 353 { 354 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 355 int i,j; 356 357 if (!mat->roworiented) { 358 if (addv == INSERT_VALUES) { 359 for ( j=0; j<n; j++ ) { 360 for ( i=0; i<m; i++ ) { 361 mat->v[indexn[j]*mat->m + indexm[i]] = *v++; 362 } 363 } 364 } 365 else { 366 for ( j=0; j<n; j++ ) { 367 for ( i=0; i<m; i++ ) { 368 mat->v[indexn[j]*mat->m + indexm[i]] += *v++; 369 } 370 } 371 } 372 } 373 else { 374 if (addv == INSERT_VALUES) { 375 for ( i=0; i<m; i++ ) { 376 for ( j=0; j<n; j++ ) { 377 mat->v[indexn[j]*mat->m + indexm[i]] = *v++; 378 } 379 } 380 } 381 else { 382 for ( i=0; i<m; i++ ) { 383 for ( j=0; j<n; j++ ) { 384 mat->v[indexn[j]*mat->m + indexm[i]] += *v++; 385 } 386 } 387 } 388 } 389 return 0; 390 } 391 392 static int MatGetValues_SeqDense(Mat A,int m,int *indexm,int n,int *indexn,Scalar *v) 393 { 394 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 395 int i, j; 396 Scalar *vpt = v; 397 398 /* row-oriented output */ 399 for ( i=0; i<m; i++ ) { 400 for ( j=0; j<n; j++ ) { 401 *vpt++ = mat->v[indexn[j]*mat->m + indexm[i]]; 402 } 403 } 404 return 0; 405 } 406 407 /* -----------------------------------------------------------------*/ 408 409 #include "sys.h" 410 411 int MatLoad_SeqDense(Viewer viewer,MatType type,Mat *A) 412 { 413 Mat_SeqDense *a; 414 Mat B; 415 int *scols, i, j, nz, ierr, fd, header[4], size; 416 int *rowlengths = 0, M, N, *cols; 417 Scalar *vals, *svals, *v; 418 MPI_Comm comm = ((PetscObject)viewer)->comm; 419 420 MPI_Comm_size(comm,&size); 421 if (size > 1) SETERRQ(1,"MatLoad_SeqDense: view must have one processor"); 422 ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr); 423 ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr); 424 if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqDense:Not matrix object"); 425 M = header[1]; N = header[2]; nz = header[3]; 426 427 if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */ 428 ierr = MatCreateSeqDense(comm,M,N,PETSC_NULL,A); CHKERRQ(ierr); 429 B = *A; 430 a = (Mat_SeqDense *) B->data; 431 432 /* read in nonzero values */ 433 ierr = PetscBinaryRead(fd,a->v,M*N,BINARY_SCALAR); CHKERRQ(ierr); 434 435 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 436 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 437 ierr = MatTranspose(B,PETSC_NULL); CHKERRQ(ierr); 438 } else { 439 /* read row lengths */ 440 rowlengths = (int*) PetscMalloc( (M+1)*sizeof(int) ); CHKPTRQ(rowlengths); 441 ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr); 442 443 /* create our matrix */ 444 ierr = MatCreateSeqDense(comm,M,N,PETSC_NULL,A); CHKERRQ(ierr); 445 B = *A; 446 a = (Mat_SeqDense *) B->data; 447 v = a->v; 448 449 /* read column indices and nonzeros */ 450 cols = scols = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(cols); 451 ierr = PetscBinaryRead(fd,cols,nz,BINARY_INT); CHKERRQ(ierr); 452 vals = svals = (Scalar *) PetscMalloc( (nz+1)*sizeof(Scalar) ); CHKPTRQ(vals); 453 ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr); 454 455 /* insert into matrix */ 456 for ( i=0; i<M; i++ ) { 457 for ( j=0; j<rowlengths[i]; j++ ) v[i+M*scols[j]] = svals[j]; 458 svals += rowlengths[i]; scols += rowlengths[i]; 459 } 460 PetscFree(vals); PetscFree(cols); PetscFree(rowlengths); 461 462 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 463 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 464 } 465 return 0; 466 } 467 468 #include "pinclude/pviewer.h" 469 #include "sys.h" 470 471 static int MatView_SeqDense_ASCII(Mat A,Viewer viewer) 472 { 473 Mat_SeqDense *a = (Mat_SeqDense *) A->data; 474 int ierr, i, j, format; 475 FILE *fd; 476 char *outputname; 477 Scalar *v; 478 479 ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 480 ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr); 481 ierr = ViewerGetFormat(viewer,&format); 482 if (format == VIEWER_FORMAT_ASCII_INFO || format == VIEWER_FORMAT_ASCII_INFO_LONG) { 483 return 0; /* do nothing for now */ 484 } 485 else if (format == VIEWER_FORMAT_ASCII_COMMON) { 486 for ( i=0; i<a->m; i++ ) { 487 v = a->v + i; 488 fprintf(fd,"row %d:",i); 489 for ( j=0; j<a->n; j++ ) { 490 #if defined(PETSC_COMPLEX) 491 if (real(*v) != 0.0 && imag(*v) != 0.0) 492 fprintf(fd," %d %g + %g i",j,real(*v),imag(*v)); 493 else if (real(*v)) fprintf(fd," %d %g ",j,real(*v)); 494 v += a->m; 495 #else 496 if (*v) fprintf(fd," %d %g ",j,*v); 497 v += a->m; 498 #endif 499 } 500 fprintf(fd,"\n"); 501 } 502 } 503 else { 504 #if defined(PETSC_COMPLEX) 505 int allreal = 1; 506 /* determine if matrix has all real values */ 507 v = a->v; 508 for ( i=0; i<a->m*a->n; i++ ) { 509 if (imag(v[i])) { allreal = 0; break ;} 510 } 511 #endif 512 for ( i=0; i<a->m; i++ ) { 513 v = a->v + i; 514 for ( j=0; j<a->n; j++ ) { 515 #if defined(PETSC_COMPLEX) 516 if (allreal) { 517 fprintf(fd,"%6.4e ",real(*v)); v += a->m; 518 } else { 519 fprintf(fd,"%6.4e + %6.4e i ",real(*v),imag(*v)); v += a->m; 520 } 521 #else 522 fprintf(fd,"%6.4e ",*v); v += a->m; 523 #endif 524 } 525 fprintf(fd,"\n"); 526 } 527 } 528 fflush(fd); 529 return 0; 530 } 531 532 static int MatView_SeqDense_Binary(Mat A,Viewer viewer) 533 { 534 Mat_SeqDense *a = (Mat_SeqDense *) A->data; 535 int ict, j, n = a->n, m = a->m, i, fd, *col_lens, ierr, nz = m*n; 536 int format; 537 Scalar *v, *anonz,*vals; 538 539 ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr); 540 541 ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr); 542 if (format == VIEWER_FORMAT_BINARY_NATIVE) { 543 /* store the matrix as a dense matrix */ 544 col_lens = (int *) PetscMalloc( 4*sizeof(int) ); CHKPTRQ(col_lens); 545 col_lens[0] = MAT_COOKIE; 546 col_lens[1] = m; 547 col_lens[2] = n; 548 col_lens[3] = MATRIX_BINARY_FORMAT_DENSE; 549 ierr = PetscBinaryWrite(fd,col_lens,4,BINARY_INT,1); CHKERRQ(ierr); 550 PetscFree(col_lens); 551 552 /* write out matrix, by rows */ 553 vals = (Scalar *) PetscMalloc((m*n+1)*sizeof(Scalar)); CHKPTRQ(vals); 554 v = a->v; 555 for ( i=0; i<m; i++ ) { 556 for ( j=0; j<n; j++ ) { 557 vals[i + j*m] = *v++; 558 } 559 } 560 ierr = PetscBinaryWrite(fd,vals,n*m,BINARY_SCALAR,0); CHKERRQ(ierr); 561 PetscFree(vals); 562 } else { 563 col_lens = (int *) PetscMalloc( (4+nz)*sizeof(int) ); CHKPTRQ(col_lens); 564 col_lens[0] = MAT_COOKIE; 565 col_lens[1] = m; 566 col_lens[2] = n; 567 col_lens[3] = nz; 568 569 /* store lengths of each row and write (including header) to file */ 570 for ( i=0; i<m; i++ ) col_lens[4+i] = n; 571 ierr = PetscBinaryWrite(fd,col_lens,4+m,BINARY_INT,1); CHKERRQ(ierr); 572 573 /* Possibly should write in smaller increments, not whole matrix at once? */ 574 /* store column indices (zero start index) */ 575 ict = 0; 576 for ( i=0; i<m; i++ ) { 577 for ( j=0; j<n; j++ ) col_lens[ict++] = j; 578 } 579 ierr = PetscBinaryWrite(fd,col_lens,nz,BINARY_INT,0); CHKERRQ(ierr); 580 PetscFree(col_lens); 581 582 /* store nonzero values */ 583 anonz = (Scalar *) PetscMalloc((nz+1)*sizeof(Scalar)); CHKPTRQ(anonz); 584 ict = 0; 585 for ( i=0; i<m; i++ ) { 586 v = a->v + i; 587 for ( j=0; j<n; j++ ) { 588 anonz[ict++] = *v; v += a->m; 589 } 590 } 591 ierr = PetscBinaryWrite(fd,anonz,nz,BINARY_SCALAR,0); CHKERRQ(ierr); 592 PetscFree(anonz); 593 } 594 return 0; 595 } 596 597 static int MatView_SeqDense(PetscObject obj,Viewer viewer) 598 { 599 Mat A = (Mat) obj; 600 Mat_SeqDense *a = (Mat_SeqDense*) A->data; 601 ViewerType vtype; 602 int ierr; 603 604 ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 605 606 if (vtype == MATLAB_VIEWER) { 607 return ViewerMatlabPutArray_Private(viewer,a->m,a->n,a->v); 608 } 609 else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 610 return MatView_SeqDense_ASCII(A,viewer); 611 } 612 else if (vtype == BINARY_FILE_VIEWER) { 613 return MatView_SeqDense_Binary(A,viewer); 614 } 615 return 0; 616 } 617 618 static int MatDestroy_SeqDense(PetscObject obj) 619 { 620 Mat mat = (Mat) obj; 621 Mat_SeqDense *l = (Mat_SeqDense *) mat->data; 622 int ierr; 623 624 #if defined(PETSC_LOG) 625 PLogObjectState(obj,"Rows %d Cols %d",l->m,l->n); 626 #endif 627 if (l->pivots) PetscFree(l->pivots); 628 if (!l->user_alloc) PetscFree(l->v); 629 PetscFree(l); 630 if (mat->mapping) { 631 ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr); 632 } 633 PLogObjectDestroy(mat); 634 PetscHeaderDestroy(mat); 635 return 0; 636 } 637 638 static int MatTranspose_SeqDense(Mat A,Mat *matout) 639 { 640 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 641 int k, j, m, n; 642 Scalar *v, tmp; 643 644 v = mat->v; m = mat->m; n = mat->n; 645 if (matout == PETSC_NULL) { /* in place transpose */ 646 if (m != n) SETERRQ(PETSC_ERR_SUP,"MatTranspose_SeqDense:Supports square matrix only in-place"); 647 for ( j=0; j<m; j++ ) { 648 for ( k=0; k<j; k++ ) { 649 tmp = v[j + k*n]; 650 v[j + k*n] = v[k + j*n]; 651 v[k + j*n] = tmp; 652 } 653 } 654 } 655 else { /* out-of-place transpose */ 656 int ierr; 657 Mat tmat; 658 Mat_SeqDense *tmatd; 659 Scalar *v2; 660 ierr = MatCreateSeqDense(A->comm,mat->n,mat->m,PETSC_NULL,&tmat); CHKERRQ(ierr); 661 tmatd = (Mat_SeqDense *) tmat->data; 662 v = mat->v; v2 = tmatd->v; 663 for ( j=0; j<n; j++ ) { 664 for ( k=0; k<m; k++ ) v2[j + k*n] = v[k + j*m]; 665 } 666 ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 667 ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 668 *matout = tmat; 669 } 670 return 0; 671 } 672 673 static int MatEqual_SeqDense(Mat A1,Mat A2, PetscTruth *flg) 674 { 675 Mat_SeqDense *mat1 = (Mat_SeqDense *) A1->data; 676 Mat_SeqDense *mat2 = (Mat_SeqDense *) A2->data; 677 int i; 678 Scalar *v1 = mat1->v, *v2 = mat2->v; 679 680 if (A2->type != MATSEQDENSE) SETERRQ(PETSC_ERR_SUP,"MatEqual_SeqDense:Both matrices should be of type MATSEQDENSE"); 681 if (mat1->m != mat2->m) {*flg = PETSC_FALSE; return 0;} 682 if (mat1->n != mat2->n) {*flg = PETSC_FALSE; return 0;} 683 for ( i=0; i<mat1->m*mat1->n; i++ ) { 684 if (*v1 != *v2) {*flg = PETSC_FALSE; return 0;} 685 v1++; v2++; 686 } 687 *flg = PETSC_TRUE; 688 return 0; 689 } 690 691 static int MatGetDiagonal_SeqDense(Mat A,Vec v) 692 { 693 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 694 int i, n, len; 695 Scalar *x, zero = 0.0; 696 697 VecSet(&zero,v); 698 VecGetArray(v,&x); VecGetSize(v,&n); 699 len = PetscMin(mat->m,mat->n); 700 if (n != mat->m) SETERRQ(PETSC_ERR_ARG_SIZ,"MatGetDiagonal_SeqDense:Nonconforming mat and vec"); 701 for ( i=0; i<len; i++ ) { 702 x[i] = mat->v[i*mat->m + i]; 703 } 704 return 0; 705 } 706 707 static int MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr) 708 { 709 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 710 Scalar *l,*r,x,*v; 711 int i,j,m = mat->m, n = mat->n; 712 713 if (ll) { 714 VecGetArray(ll,&l); VecGetSize(ll,&m); 715 if (m != mat->m) SETERRQ(PETSC_ERR_ARG_SIZ,"MatDiagonalScale_SeqDense:Left scaling vec wrong size"); 716 for ( i=0; i<m; i++ ) { 717 x = l[i]; 718 v = mat->v + i; 719 for ( j=0; j<n; j++ ) { (*v) *= x; v+= m;} 720 } 721 PLogFlops(n*m); 722 } 723 if (rr) { 724 VecGetArray(rr,&r); VecGetSize(rr,&n); 725 if (n != mat->n) SETERRQ(PETSC_ERR_ARG_SIZ,"MatDiagonalScale_SeqDense:Right scaling vec wrong size"); 726 for ( i=0; i<n; i++ ) { 727 x = r[i]; 728 v = mat->v + i*m; 729 for ( j=0; j<m; j++ ) { (*v++) *= x;} 730 } 731 PLogFlops(n*m); 732 } 733 return 0; 734 } 735 736 static int MatNorm_SeqDense(Mat A,NormType type,double *norm) 737 { 738 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 739 Scalar *v = mat->v; 740 double sum = 0.0; 741 int i, j; 742 743 if (type == NORM_FROBENIUS) { 744 for (i=0; i<mat->n*mat->m; i++ ) { 745 #if defined(PETSC_COMPLEX) 746 sum += real(conj(*v)*(*v)); v++; 747 #else 748 sum += (*v)*(*v); v++; 749 #endif 750 } 751 *norm = sqrt(sum); 752 PLogFlops(2*mat->n*mat->m); 753 } 754 else if (type == NORM_1) { 755 *norm = 0.0; 756 for ( j=0; j<mat->n; j++ ) { 757 sum = 0.0; 758 for ( i=0; i<mat->m; i++ ) { 759 sum += PetscAbsScalar(*v); v++; 760 } 761 if (sum > *norm) *norm = sum; 762 } 763 PLogFlops(mat->n*mat->m); 764 } 765 else if (type == NORM_INFINITY) { 766 *norm = 0.0; 767 for ( j=0; j<mat->m; j++ ) { 768 v = mat->v + j; 769 sum = 0.0; 770 for ( i=0; i<mat->n; i++ ) { 771 sum += PetscAbsScalar(*v); v += mat->m; 772 } 773 if (sum > *norm) *norm = sum; 774 } 775 PLogFlops(mat->n*mat->m); 776 } 777 else { 778 SETERRQ(PETSC_ERR_SUP,"MatNorm_SeqDense:No two norm"); 779 } 780 return 0; 781 } 782 783 static int MatSetOption_SeqDense(Mat A,MatOption op) 784 { 785 Mat_SeqDense *aij = (Mat_SeqDense *) A->data; 786 787 if (op == MAT_ROW_ORIENTED) aij->roworiented = 1; 788 else if (op == MAT_COLUMN_ORIENTED) aij->roworiented = 0; 789 else if (op == MAT_ROWS_SORTED || 790 op == MAT_ROWS_UNSORTED || 791 op == MAT_COLUMNS_SORTED || 792 op == MAT_COLUMNS_UNSORTED || 793 op == MAT_SYMMETRIC || 794 op == MAT_STRUCTURALLY_SYMMETRIC || 795 op == MAT_NO_NEW_NONZERO_LOCATIONS || 796 op == MAT_YES_NEW_NONZERO_LOCATIONS || 797 op == MAT_NO_NEW_DIAGONALS || 798 op == MAT_YES_NEW_DIAGONALS || 799 op == MAT_IGNORE_OFF_PROCESSOR_ENTRIES) 800 PLogInfo(A,"Info:MatSetOption_SeqDense:Option ignored\n"); 801 else 802 {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqDense:unknown option");} 803 return 0; 804 } 805 806 static int MatZeroEntries_SeqDense(Mat A) 807 { 808 Mat_SeqDense *l = (Mat_SeqDense *) A->data; 809 PetscMemzero(l->v,l->m*l->n*sizeof(Scalar)); 810 return 0; 811 } 812 813 static int MatGetBlockSize_SeqDense(Mat A,int *bs) 814 { 815 *bs = 1; 816 return 0; 817 } 818 819 static int MatZeroRows_SeqDense(Mat A,IS is,Scalar *diag) 820 { 821 Mat_SeqDense *l = (Mat_SeqDense *) A->data; 822 int n = l->n, i, j,ierr,N, *rows; 823 Scalar *slot; 824 825 ierr = ISGetSize(is,&N); CHKERRQ(ierr); 826 ierr = ISGetIndices(is,&rows); CHKERRQ(ierr); 827 for ( i=0; i<N; i++ ) { 828 slot = l->v + rows[i]; 829 for ( j=0; j<n; j++ ) { *slot = 0.0; slot += n;} 830 } 831 if (diag) { 832 for ( i=0; i<N; i++ ) { 833 slot = l->v + (n+1)*rows[i]; 834 *slot = *diag; 835 } 836 } 837 ISRestoreIndices(is,&rows); 838 return 0; 839 } 840 841 static int MatGetSize_SeqDense(Mat A,int *m,int *n) 842 { 843 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 844 *m = mat->m; *n = mat->n; 845 return 0; 846 } 847 848 static int MatGetOwnershipRange_SeqDense(Mat A,int *m,int *n) 849 { 850 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 851 *m = 0; *n = mat->m; 852 return 0; 853 } 854 855 static int MatGetArray_SeqDense(Mat A,Scalar **array) 856 { 857 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 858 *array = mat->v; 859 return 0; 860 } 861 862 static int MatRestoreArray_SeqDense(Mat A,Scalar **array) 863 { 864 return 0; 865 } 866 867 static int MatGetSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall, 868 Mat *submat) 869 { 870 Mat_SeqDense *mat = (Mat_SeqDense *) A->data; 871 int nznew, *smap, i, j, ierr, oldcols = mat->n; 872 int *irow, *icol, nrows, ncols, *cwork; 873 Scalar *vwork, *val; 874 Mat newmat; 875 876 ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr); 877 ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr); 878 ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr); 879 ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr); 880 881 smap = (int *) PetscMalloc(oldcols*sizeof(int)); CHKPTRQ(smap); 882 cwork = (int *) PetscMalloc(ncols*sizeof(int)); CHKPTRQ(cwork); 883 vwork = (Scalar *) PetscMalloc(ncols*sizeof(Scalar)); CHKPTRQ(vwork); 884 PetscMemzero((char*)smap,oldcols*sizeof(int)); 885 for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1; 886 887 /* Create and fill new matrix */ 888 ierr = MatCreateSeqDense(A->comm,nrows,ncols,PETSC_NULL,&newmat); CHKERRQ(ierr); 889 for (i=0; i<nrows; i++) { 890 nznew = 0; 891 val = mat->v + irow[i]; 892 for (j=0; j<oldcols; j++) { 893 if (smap[j]) { 894 cwork[nznew] = smap[j] - 1; 895 vwork[nznew++] = val[j * mat->m]; 896 } 897 } 898 ierr = MatSetValues(newmat,1,&i,nznew,cwork,vwork,INSERT_VALUES); 899 CHKERRQ(ierr); 900 } 901 ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 902 ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 903 904 /* Free work space */ 905 PetscFree(smap); PetscFree(cwork); PetscFree(vwork); 906 ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr); 907 ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr); 908 *submat = newmat; 909 return 0; 910 } 911 912 static int MatGetSubMatrices_SeqDense(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall, 913 Mat **B) 914 { 915 int ierr,i; 916 917 if (scall == MAT_INITIAL_MATRIX) { 918 *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B); 919 } 920 921 for ( i=0; i<n; i++ ) { 922 ierr = MatGetSubMatrix_SeqDense(A,irow[i],icol[i],scall,&(*B)[i]);CHKERRQ(ierr); 923 } 924 return 0; 925 } 926 927 static int MatCopy_SeqDense(Mat A, Mat B) 928 { 929 Mat_SeqDense *a = (Mat_SeqDense *) A->data, *b = (Mat_SeqDense *)B->data; 930 if (B->type != MATSEQDENSE) return MatCopy_Basic(A,B); 931 if (a->m != b->m || a->n != b->n) SETERRQ(PETSC_ERR_ARG_SIZ,"MatCopy_SeqDense:size(B) != size(A)"); 932 PetscMemcpy(b->v,a->v,a->m*a->n*sizeof(Scalar)); 933 return 0; 934 } 935 936 /* -------------------------------------------------------------------*/ 937 static struct _MatOps MatOps = {MatSetValues_SeqDense, 938 MatGetRow_SeqDense, 939 MatRestoreRow_SeqDense, 940 MatMult_SeqDense, 941 MatMultAdd_SeqDense, 942 MatMultTrans_SeqDense, 943 MatMultTransAdd_SeqDense, 944 MatSolve_SeqDense, 945 MatSolveAdd_SeqDense, 946 MatSolveTrans_SeqDense, 947 MatSolveTransAdd_SeqDense, 948 MatLUFactor_SeqDense, 949 MatCholeskyFactor_SeqDense, 950 MatRelax_SeqDense, 951 MatTranspose_SeqDense, 952 MatGetInfo_SeqDense, 953 MatEqual_SeqDense, 954 MatGetDiagonal_SeqDense, 955 MatDiagonalScale_SeqDense, 956 MatNorm_SeqDense, 957 0, 958 0, 959 0, 960 MatSetOption_SeqDense, 961 MatZeroEntries_SeqDense, 962 MatZeroRows_SeqDense, 963 MatLUFactorSymbolic_SeqDense, 964 MatLUFactorNumeric_SeqDense, 965 MatCholeskyFactorSymbolic_SeqDense, 966 MatCholeskyFactorNumeric_SeqDense, 967 MatGetSize_SeqDense, 968 MatGetSize_SeqDense, 969 MatGetOwnershipRange_SeqDense, 970 0, 971 0, 972 MatGetArray_SeqDense, 973 MatRestoreArray_SeqDense, 974 0, 975 MatConvertSameType_SeqDense,0,0,0,0, 976 MatAXPY_SeqDense,MatGetSubMatrices_SeqDense,0, 977 MatGetValues_SeqDense, 978 MatCopy_SeqDense,0,MatScale_SeqDense, 979 0,0,0,MatGetBlockSize_SeqDense}; 980 981 /*@C 982 MatCreateSeqDense - Creates a sequential dense matrix that 983 is stored in column major order (the usual Fortran 77 manner). Many 984 of the matrix operations use the BLAS and LAPACK routines. 985 986 Input Parameters: 987 . comm - MPI communicator, set to MPI_COMM_SELF 988 . m - number of rows 989 . n - number of columns 990 . data - optional location of matrix data. Set data=PETSC_NULL for PETSc 991 to control all matrix memory allocation. 992 993 Output Parameter: 994 . A - the matrix 995 996 Notes: 997 The data input variable is intended primarily for Fortran programmers 998 who wish to allocate their own matrix memory space. Most users should 999 set data=PETSC_NULL. 1000 1001 .keywords: dense, matrix, LAPACK, BLAS 1002 1003 .seealso: MatCreate(), MatSetValues() 1004 @*/ 1005 int MatCreateSeqDense(MPI_Comm comm,int m,int n,Scalar *data,Mat *A) 1006 { 1007 Mat B; 1008 Mat_SeqDense *b; 1009 int ierr,flg,size; 1010 1011 MPI_Comm_size(comm,&size); 1012 if (size > 1) SETERRQ(1,"MatCreateSeqDense:Comm must be of size 1"); 1013 1014 *A = 0; 1015 PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQDENSE,comm); 1016 PLogObjectCreate(B); 1017 b = (Mat_SeqDense *) PetscMalloc(sizeof(Mat_SeqDense)); CHKPTRQ(b); 1018 PetscMemzero(b,sizeof(Mat_SeqDense)); 1019 PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 1020 B->destroy = MatDestroy_SeqDense; 1021 B->view = MatView_SeqDense; 1022 B->factor = 0; 1023 B->mapping = 0; 1024 PLogObjectMemory(B,sizeof(struct _Mat)); 1025 B->data = (void *) b; 1026 1027 b->m = m; B->m = m; B->M = m; 1028 b->n = n; B->n = n; B->N = n; 1029 b->pivots = 0; 1030 b->roworiented = 1; 1031 if (data == PETSC_NULL) { 1032 b->v = (Scalar*) PetscMalloc((m*n+1)*sizeof(Scalar)); CHKPTRQ(b->v); 1033 PetscMemzero(b->v,m*n*sizeof(Scalar)); 1034 b->user_alloc = 0; 1035 PLogObjectMemory(B,n*m*sizeof(Scalar)); 1036 } 1037 else { /* user-allocated storage */ 1038 b->v = data; 1039 b->user_alloc = 1; 1040 } 1041 ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr); 1042 if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr);} 1043 1044 *A = B; 1045 return 0; 1046 } 1047 1048 int MatCreate_SeqDense(Mat A,Mat *newmat) 1049 { 1050 Mat_SeqDense *m = (Mat_SeqDense *) A->data; 1051 return MatCreateSeqDense(A->comm,m->m,m->n,PETSC_NULL,newmat); 1052 } 1053 1054 1055 1056 1057 1058