1 #define PETSCMAT_DLL 2 3 /* 4 Defines the basic matrix operations for the SBAIJ (compressed row) 5 matrix storage format. 6 */ 7 #include "../src/mat/impls/baij/seq/baij.h" /*I "petscmat.h" I*/ 8 #include "../src/inline/spops.h" 9 #include "../src/mat/impls/sbaij/seq/sbaij.h" 10 11 extern PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat,PetscTruth); 12 #define CHUNKSIZE 10 13 14 /* 15 Checks for missing diagonals 16 */ 17 #undef __FUNCT__ 18 #define __FUNCT__ "MatMissingDiagonal_SeqSBAIJ" 19 PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A,PetscTruth *missing,PetscInt *dd) 20 { 21 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 22 PetscErrorCode ierr; 23 PetscInt *diag,*jj = a->j,i; 24 25 PetscFunctionBegin; 26 ierr = MatMarkDiagonal_SeqSBAIJ(A);CHKERRQ(ierr); 27 diag = a->diag; 28 *missing = PETSC_FALSE; 29 for (i=0; i<a->mbs; i++) { 30 if (jj[diag[i]] != i) { 31 *missing = PETSC_TRUE; 32 if (dd) *dd = i; 33 break; 34 } 35 } 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "MatMarkDiagonal_SeqSBAIJ" 41 PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A) 42 { 43 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 44 PetscErrorCode ierr; 45 PetscInt i; 46 47 PetscFunctionBegin; 48 if (!a->diag) { 49 ierr = PetscMalloc(a->mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr); 50 } 51 for (i=0; i<a->mbs; i++) a->diag[i] = a->i[i]; 52 PetscFunctionReturn(0); 53 } 54 55 #undef __FUNCT__ 56 #define __FUNCT__ "MatGetRowIJ_SeqSBAIJ" 57 static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 58 { 59 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 60 PetscInt i,j,n = a->mbs,nz = a->i[n],bs = A->rmap->bs; 61 PetscErrorCode ierr; 62 63 PetscFunctionBegin; 64 *nn = n; 65 if (!ia) PetscFunctionReturn(0); 66 if (!blockcompressed) { 67 /* malloc & create the natural set of indices */ 68 ierr = PetscMalloc2((n+1)*bs,PetscInt,ia,nz*bs,PetscInt,ja);CHKERRQ(ierr); 69 for (i=0; i<n+1; i++) { 70 for (j=0; j<bs; j++) { 71 *ia[i*bs+j] = a->i[i]*bs+j+oshift; 72 } 73 } 74 for (i=0; i<nz; i++) { 75 for (j=0; j<bs; j++) { 76 *ja[i*bs+j] = a->j[i]*bs+j+oshift; 77 } 78 } 79 } else { /* blockcompressed */ 80 if (oshift == 1) { 81 /* temporarily add 1 to i and j indices */ 82 for (i=0; i<nz; i++) a->j[i]++; 83 for (i=0; i<n+1; i++) a->i[i]++; 84 } 85 *ia = a->i; *ja = a->j; 86 } 87 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "MatRestoreRowIJ_SeqSBAIJ" 93 static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 94 { 95 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 96 PetscInt i,n = a->mbs,nz = a->i[n]; 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 if (!ia) PetscFunctionReturn(0); 101 102 if (!blockcompressed) { 103 ierr = PetscFree2(*ia,*ja);CHKERRQ(ierr); 104 } else if (oshift == 1) { /* blockcompressed */ 105 for (i=0; i<nz; i++) a->j[i]--; 106 for (i=0; i<n+1; i++) a->i[i]--; 107 } 108 109 PetscFunctionReturn(0); 110 } 111 112 #undef __FUNCT__ 113 #define __FUNCT__ "MatDestroy_SeqSBAIJ" 114 PetscErrorCode MatDestroy_SeqSBAIJ(Mat A) 115 { 116 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 117 PetscErrorCode ierr; 118 119 PetscFunctionBegin; 120 #if defined(PETSC_USE_LOG) 121 PetscLogObjectState((PetscObject)A,"Rows=%D, NZ=%D",A->rmap->N,a->nz); 122 #endif 123 ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr); 124 if (a->row) {ierr = ISDestroy(a->row);CHKERRQ(ierr);} 125 if (a->col){ierr = ISDestroy(a->col);CHKERRQ(ierr);} 126 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} 127 ierr = PetscFree(a->diag);CHKERRQ(ierr); 128 ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr); 129 ierr = PetscFree(a->solve_work);CHKERRQ(ierr); 130 ierr = PetscFree(a->relax_work);CHKERRQ(ierr); 131 ierr = PetscFree(a->solves_work);CHKERRQ(ierr); 132 ierr = PetscFree(a->mult_work);CHKERRQ(ierr); 133 ierr = PetscFree(a->saved_values);CHKERRQ(ierr); 134 ierr = PetscFree(a->xtoy);CHKERRQ(ierr); 135 136 ierr = PetscFree(a->inew);CHKERRQ(ierr); 137 ierr = PetscFree(a);CHKERRQ(ierr); 138 139 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 140 ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr); 141 ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr); 142 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr); 143 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqaij_C","",PETSC_NULL);CHKERRQ(ierr); 144 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr); 145 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "MatSetOption_SeqSBAIJ" 151 PetscErrorCode MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscTruth flg) 152 { 153 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 switch (op) { 158 case MAT_ROW_ORIENTED: 159 a->roworiented = flg; 160 break; 161 case MAT_KEEP_ZEROED_ROWS: 162 a->keepzeroedrows = flg; 163 break; 164 case MAT_NEW_NONZERO_LOCATIONS: 165 a->nonew = (flg ? 0 : 1); 166 break; 167 case MAT_NEW_NONZERO_LOCATION_ERR: 168 a->nonew = (flg ? -1 : 0); 169 break; 170 case MAT_NEW_NONZERO_ALLOCATION_ERR: 171 a->nonew = (flg ? -2 : 0); 172 break; 173 case MAT_UNUSED_NONZERO_LOCATION_ERR: 174 a->nounused = (flg ? -1 : 0); 175 break; 176 case MAT_NEW_DIAGONALS: 177 case MAT_IGNORE_OFF_PROC_ENTRIES: 178 case MAT_USE_HASH_TABLE: 179 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 180 break; 181 case MAT_HERMITIAN: 182 if (flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric"); 183 case MAT_SYMMETRIC: 184 case MAT_STRUCTURALLY_SYMMETRIC: 185 case MAT_SYMMETRY_ETERNAL: 186 if (!flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric"); 187 ierr = PetscInfo1(A,"Option %s not relevent\n",MatOptions[op]);CHKERRQ(ierr); 188 break; 189 case MAT_IGNORE_LOWER_TRIANGULAR: 190 a->ignore_ltriangular = flg; 191 break; 192 case MAT_ERROR_LOWER_TRIANGULAR: 193 a->ignore_ltriangular = flg; 194 break; 195 case MAT_GETROW_UPPERTRIANGULAR: 196 a->getrow_utriangular = flg; 197 break; 198 default: 199 SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op); 200 } 201 PetscFunctionReturn(0); 202 } 203 204 #undef __FUNCT__ 205 #define __FUNCT__ "MatGetRow_SeqSBAIJ" 206 PetscErrorCode MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **v) 207 { 208 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 209 PetscErrorCode ierr; 210 PetscInt itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*cols_i,bs2; 211 MatScalar *aa,*aa_i; 212 PetscScalar *v_i; 213 214 PetscFunctionBegin; 215 if (A && !a->getrow_utriangular) SETERRQ(PETSC_ERR_SUP,"MatGetRow is not supported for SBAIJ matrix format. Getting the upper triangular part of row, run with -mat_getrow_uppertriangular, call MatSetOption(mat,MAT_GETROW_UPPERTRIANGULAR,PETSC_TRUE) or MatGetRowUpperTriangular()"); 216 /* Get the upper triangular part of the row */ 217 bs = A->rmap->bs; 218 ai = a->i; 219 aj = a->j; 220 aa = a->a; 221 bs2 = a->bs2; 222 223 if (row < 0 || row >= A->rmap->N) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Row %D out of range", row); 224 225 bn = row/bs; /* Block number */ 226 bp = row % bs; /* Block position */ 227 M = ai[bn+1] - ai[bn]; 228 *ncols = bs*M; 229 230 if (v) { 231 *v = 0; 232 if (*ncols) { 233 ierr = PetscMalloc((*ncols+row)*sizeof(PetscScalar),v);CHKERRQ(ierr); 234 for (i=0; i<M; i++) { /* for each block in the block row */ 235 v_i = *v + i*bs; 236 aa_i = aa + bs2*(ai[bn] + i); 237 for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];} 238 } 239 } 240 } 241 242 if (cols) { 243 *cols = 0; 244 if (*ncols) { 245 ierr = PetscMalloc((*ncols+row)*sizeof(PetscInt),cols);CHKERRQ(ierr); 246 for (i=0; i<M; i++) { /* for each block in the block row */ 247 cols_i = *cols + i*bs; 248 itmp = bs*aj[ai[bn] + i]; 249 for (j=0; j<bs; j++) {cols_i[j] = itmp++;} 250 } 251 } 252 } 253 254 /*search column A(0:row-1,row) (=A(row,0:row-1)). Could be expensive! */ 255 /* this segment is currently removed, so only entries in the upper triangle are obtained */ 256 #ifdef column_search 257 v_i = *v + M*bs; 258 cols_i = *cols + M*bs; 259 for (i=0; i<bn; i++){ /* for each block row */ 260 M = ai[i+1] - ai[i]; 261 for (j=0; j<M; j++){ 262 itmp = aj[ai[i] + j]; /* block column value */ 263 if (itmp == bn){ 264 aa_i = aa + bs2*(ai[i] + j) + bs*bp; 265 for (k=0; k<bs; k++) { 266 *cols_i++ = i*bs+k; 267 *v_i++ = aa_i[k]; 268 } 269 *ncols += bs; 270 break; 271 } 272 } 273 } 274 #endif 275 PetscFunctionReturn(0); 276 } 277 278 #undef __FUNCT__ 279 #define __FUNCT__ "MatRestoreRow_SeqSBAIJ" 280 PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 281 { 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);} 286 if (v) {ierr = PetscFree(*v);CHKERRQ(ierr);} 287 PetscFunctionReturn(0); 288 } 289 290 #undef __FUNCT__ 291 #define __FUNCT__ "MatGetRowUpperTriangular_SeqSBAIJ" 292 PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A) 293 { 294 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 295 296 PetscFunctionBegin; 297 a->getrow_utriangular = PETSC_TRUE; 298 PetscFunctionReturn(0); 299 } 300 #undef __FUNCT__ 301 #define __FUNCT__ "MatRestoreRowUpperTriangular_SeqSBAIJ" 302 PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A) 303 { 304 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 305 306 PetscFunctionBegin; 307 a->getrow_utriangular = PETSC_FALSE; 308 PetscFunctionReturn(0); 309 } 310 311 #undef __FUNCT__ 312 #define __FUNCT__ "MatTranspose_SeqSBAIJ" 313 PetscErrorCode MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat *B) 314 { 315 PetscErrorCode ierr; 316 PetscFunctionBegin; 317 if (reuse == MAT_INITIAL_MATRIX || *B != A) { 318 ierr = MatDuplicate(A,MAT_COPY_VALUES,B);CHKERRQ(ierr); 319 } 320 PetscFunctionReturn(0); 321 } 322 323 #undef __FUNCT__ 324 #define __FUNCT__ "MatView_SeqSBAIJ_ASCII" 325 static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer) 326 { 327 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 328 PetscErrorCode ierr; 329 PetscInt i,j,bs = A->rmap->bs,k,l,bs2=a->bs2; 330 const char *name; 331 PetscViewerFormat format; 332 333 PetscFunctionBegin; 334 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 335 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 336 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 337 ierr = PetscViewerASCIIPrintf(viewer," block size is %D\n",bs);CHKERRQ(ierr); 338 } else if (format == PETSC_VIEWER_ASCII_MATLAB) { 339 Mat aij; 340 341 if (A->factor && bs>1){ 342 ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored with bs>1. MatView() with PETSC_VIEWER_ASCII_MATLAB is not supported and ignored!\n");CHKERRQ(ierr); 343 PetscFunctionReturn(0); 344 } 345 ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&aij);CHKERRQ(ierr); 346 ierr = MatView(aij,viewer);CHKERRQ(ierr); 347 ierr = MatDestroy(aij);CHKERRQ(ierr); 348 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 349 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 350 for (i=0; i<a->mbs; i++) { 351 for (j=0; j<bs; j++) { 352 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr); 353 for (k=a->i[i]; k<a->i[i+1]; k++) { 354 for (l=0; l<bs; l++) { 355 #if defined(PETSC_USE_COMPLEX) 356 if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 357 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l, 358 PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 359 } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 360 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l, 361 PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 362 } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 363 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 364 } 365 #else 366 if (a->a[bs2*k + l*bs + j] != 0.0) { 367 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr); 368 } 369 #endif 370 } 371 } 372 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 373 } 374 } 375 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 376 } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 377 PetscFunctionReturn(0); 378 } else { 379 if (A->factor && bs>1){ 380 ierr = PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored. MatView_SeqSBAIJ_ASCII() may not display complete or logically correct entries!\n");CHKERRQ(ierr); 381 } 382 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 383 for (i=0; i<a->mbs; i++) { 384 for (j=0; j<bs; j++) { 385 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);CHKERRQ(ierr); 386 for (k=a->i[i]; k<a->i[i+1]; k++) { 387 for (l=0; l<bs; l++) { 388 #if defined(PETSC_USE_COMPLEX) 389 if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) { 390 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l, 391 PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 392 } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) { 393 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l, 394 PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 395 } else { 396 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 397 } 398 #else 399 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr); 400 #endif 401 } 402 } 403 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 404 } 405 } 406 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 407 } 408 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 409 PetscFunctionReturn(0); 410 } 411 412 #undef __FUNCT__ 413 #define __FUNCT__ "MatView_SeqSBAIJ_Draw_Zoom" 414 static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 415 { 416 Mat A = (Mat) Aa; 417 Mat_SeqSBAIJ *a=(Mat_SeqSBAIJ*)A->data; 418 PetscErrorCode ierr; 419 PetscInt row,i,j,k,l,mbs=a->mbs,color,bs=A->rmap->bs,bs2=a->bs2; 420 PetscMPIInt rank; 421 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r; 422 MatScalar *aa; 423 MPI_Comm comm; 424 PetscViewer viewer; 425 426 PetscFunctionBegin; 427 /* 428 This is nasty. If this is called from an originally parallel matrix 429 then all processes call this,but only the first has the matrix so the 430 rest should return immediately. 431 */ 432 ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr); 433 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 434 if (rank) PetscFunctionReturn(0); 435 436 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 437 438 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 439 PetscDrawString(draw, .3*(xl+xr), .3*(yl+yr), PETSC_DRAW_BLACK, "symmetric"); 440 441 /* loop over matrix elements drawing boxes */ 442 color = PETSC_DRAW_BLUE; 443 for (i=0,row=0; i<mbs; i++,row+=bs) { 444 for (j=a->i[i]; j<a->i[i+1]; j++) { 445 y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0; 446 x_l = a->j[j]*bs; x_r = x_l + 1.0; 447 aa = a->a + j*bs2; 448 for (k=0; k<bs; k++) { 449 for (l=0; l<bs; l++) { 450 if (PetscRealPart(*aa++) >= 0.) continue; 451 ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 452 } 453 } 454 } 455 } 456 color = PETSC_DRAW_CYAN; 457 for (i=0,row=0; i<mbs; i++,row+=bs) { 458 for (j=a->i[i]; j<a->i[i+1]; j++) { 459 y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0; 460 x_l = a->j[j]*bs; x_r = x_l + 1.0; 461 aa = a->a + j*bs2; 462 for (k=0; k<bs; k++) { 463 for (l=0; l<bs; l++) { 464 if (PetscRealPart(*aa++) != 0.) continue; 465 ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 466 } 467 } 468 } 469 } 470 471 color = PETSC_DRAW_RED; 472 for (i=0,row=0; i<mbs; i++,row+=bs) { 473 for (j=a->i[i]; j<a->i[i+1]; j++) { 474 y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0; 475 x_l = a->j[j]*bs; x_r = x_l + 1.0; 476 aa = a->a + j*bs2; 477 for (k=0; k<bs; k++) { 478 for (l=0; l<bs; l++) { 479 if (PetscRealPart(*aa++) <= 0.) continue; 480 ierr = PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 481 } 482 } 483 } 484 } 485 PetscFunctionReturn(0); 486 } 487 488 #undef __FUNCT__ 489 #define __FUNCT__ "MatView_SeqSBAIJ_Draw" 490 static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer) 491 { 492 PetscErrorCode ierr; 493 PetscReal xl,yl,xr,yr,w,h; 494 PetscDraw draw; 495 PetscTruth isnull; 496 497 PetscFunctionBegin; 498 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 499 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 500 501 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 502 xr = A->rmap->N; yr = A->rmap->N; h = yr/10.0; w = xr/10.0; 503 xr += w; yr += h; xl = -w; yl = -h; 504 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 505 ierr = PetscDrawZoom(draw,MatView_SeqSBAIJ_Draw_Zoom,A);CHKERRQ(ierr); 506 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 507 PetscFunctionReturn(0); 508 } 509 510 #undef __FUNCT__ 511 #define __FUNCT__ "MatView_SeqSBAIJ" 512 PetscErrorCode MatView_SeqSBAIJ(Mat A,PetscViewer viewer) 513 { 514 PetscErrorCode ierr; 515 PetscTruth iascii,isdraw; 516 517 PetscFunctionBegin; 518 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 519 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr); 520 if (iascii){ 521 ierr = MatView_SeqSBAIJ_ASCII(A,viewer);CHKERRQ(ierr); 522 } else if (isdraw) { 523 ierr = MatView_SeqSBAIJ_Draw(A,viewer);CHKERRQ(ierr); 524 } else { 525 Mat B; 526 ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 527 ierr = MatView(B,viewer);CHKERRQ(ierr); 528 ierr = MatDestroy(B);CHKERRQ(ierr); 529 } 530 PetscFunctionReturn(0); 531 } 532 533 534 #undef __FUNCT__ 535 #define __FUNCT__ "MatGetValues_SeqSBAIJ" 536 PetscErrorCode MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[]) 537 { 538 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 539 PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 540 PetscInt *ai = a->i,*ailen = a->ilen; 541 PetscInt brow,bcol,ridx,cidx,bs=A->rmap->bs,bs2=a->bs2; 542 MatScalar *ap,*aa = a->a; 543 544 PetscFunctionBegin; 545 for (k=0; k<m; k++) { /* loop over rows */ 546 row = im[k]; brow = row/bs; 547 if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */ 548 if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1); 549 rp = aj + ai[brow] ; ap = aa + bs2*ai[brow] ; 550 nrow = ailen[brow]; 551 for (l=0; l<n; l++) { /* loop over columns */ 552 if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */ 553 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 554 col = in[l] ; 555 bcol = col/bs; 556 cidx = col%bs; 557 ridx = row%bs; 558 high = nrow; 559 low = 0; /* assume unsorted */ 560 while (high-low > 5) { 561 t = (low+high)/2; 562 if (rp[t] > bcol) high = t; 563 else low = t; 564 } 565 for (i=low; i<high; i++) { 566 if (rp[i] > bcol) break; 567 if (rp[i] == bcol) { 568 *v++ = ap[bs2*i+bs*cidx+ridx]; 569 goto finished; 570 } 571 } 572 *v++ = 0.0; 573 finished:; 574 } 575 } 576 PetscFunctionReturn(0); 577 } 578 579 580 #undef __FUNCT__ 581 #define __FUNCT__ "MatSetValuesBlocked_SeqSBAIJ" 582 PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 583 { 584 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 585 PetscErrorCode ierr; 586 PetscInt *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,lastcol = -1; 587 PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen; 588 PetscInt *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=A->rmap->bs,stepval; 589 PetscTruth roworiented=a->roworiented; 590 const PetscScalar *value = v; 591 MatScalar *ap,*aa = a->a,*bap; 592 593 PetscFunctionBegin; 594 if (roworiented) { 595 stepval = (n-1)*bs; 596 } else { 597 stepval = (m-1)*bs; 598 } 599 for (k=0; k<m; k++) { /* loop over added rows */ 600 row = im[k]; 601 if (row < 0) continue; 602 #if defined(PETSC_USE_DEBUG) 603 if (row >= a->mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,a->mbs-1); 604 #endif 605 rp = aj + ai[row]; 606 ap = aa + bs2*ai[row]; 607 rmax = imax[row]; 608 nrow = ailen[row]; 609 low = 0; 610 high = nrow; 611 for (l=0; l<n; l++) { /* loop over added columns */ 612 if (in[l] < 0) continue; 613 col = in[l]; 614 #if defined(PETSC_USE_DEBUG) 615 if (col >= a->nbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",col,a->nbs-1); 616 #endif 617 if (col < row) continue; /* ignore lower triangular block */ 618 if (roworiented) { 619 value = v + k*(stepval+bs)*bs + l*bs; 620 } else { 621 value = v + l*(stepval+bs)*bs + k*bs; 622 } 623 if (col <= lastcol) low = 0; else high = nrow; 624 lastcol = col; 625 while (high-low > 7) { 626 t = (low+high)/2; 627 if (rp[t] > col) high = t; 628 else low = t; 629 } 630 for (i=low; i<high; i++) { 631 if (rp[i] > col) break; 632 if (rp[i] == col) { 633 bap = ap + bs2*i; 634 if (roworiented) { 635 if (is == ADD_VALUES) { 636 for (ii=0; ii<bs; ii++,value+=stepval) { 637 for (jj=ii; jj<bs2; jj+=bs) { 638 bap[jj] += *value++; 639 } 640 } 641 } else { 642 for (ii=0; ii<bs; ii++,value+=stepval) { 643 for (jj=ii; jj<bs2; jj+=bs) { 644 bap[jj] = *value++; 645 } 646 } 647 } 648 } else { 649 if (is == ADD_VALUES) { 650 for (ii=0; ii<bs; ii++,value+=stepval) { 651 for (jj=0; jj<bs; jj++) { 652 *bap++ += *value++; 653 } 654 } 655 } else { 656 for (ii=0; ii<bs; ii++,value+=stepval) { 657 for (jj=0; jj<bs; jj++) { 658 *bap++ = *value++; 659 } 660 } 661 } 662 } 663 goto noinsert2; 664 } 665 } 666 if (nonew == 1) goto noinsert2; 667 if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col); 668 MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 669 N = nrow++ - 1; high++; 670 /* shift up all the later entries in this row */ 671 for (ii=N; ii>=i; ii--) { 672 rp[ii+1] = rp[ii]; 673 ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr); 674 } 675 if (N >= i) { 676 ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr); 677 } 678 rp[i] = col; 679 bap = ap + bs2*i; 680 if (roworiented) { 681 for (ii=0; ii<bs; ii++,value+=stepval) { 682 for (jj=ii; jj<bs2; jj+=bs) { 683 bap[jj] = *value++; 684 } 685 } 686 } else { 687 for (ii=0; ii<bs; ii++,value+=stepval) { 688 for (jj=0; jj<bs; jj++) { 689 *bap++ = *value++; 690 } 691 } 692 } 693 noinsert2:; 694 low = i; 695 } 696 ailen[row] = nrow; 697 } 698 PetscFunctionReturn(0); 699 } 700 701 #undef __FUNCT__ 702 #define __FUNCT__ "MatAssemblyEnd_SeqSBAIJ" 703 PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode) 704 { 705 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 706 PetscErrorCode ierr; 707 PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 708 PetscInt m = A->rmap->N,*ip,N,*ailen = a->ilen; 709 PetscInt mbs = a->mbs,bs2 = a->bs2,rmax = 0; 710 MatScalar *aa = a->a,*ap; 711 712 PetscFunctionBegin; 713 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 714 715 if (m) rmax = ailen[0]; 716 for (i=1; i<mbs; i++) { 717 /* move each row back by the amount of empty slots (fshift) before it*/ 718 fshift += imax[i-1] - ailen[i-1]; 719 rmax = PetscMax(rmax,ailen[i]); 720 if (fshift) { 721 ip = aj + ai[i]; ap = aa + bs2*ai[i]; 722 N = ailen[i]; 723 for (j=0; j<N; j++) { 724 ip[j-fshift] = ip[j]; 725 ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr); 726 } 727 } 728 ai[i] = ai[i-1] + ailen[i-1]; 729 } 730 if (mbs) { 731 fshift += imax[mbs-1] - ailen[mbs-1]; 732 ai[mbs] = ai[mbs-1] + ailen[mbs-1]; 733 } 734 /* reset ilen and imax for each row */ 735 for (i=0; i<mbs; i++) { 736 ailen[i] = imax[i] = ai[i+1] - ai[i]; 737 } 738 a->nz = ai[mbs]; 739 740 /* diagonals may have moved, reset it */ 741 if (a->diag) { 742 ierr = PetscMemcpy(a->diag,ai,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 743 } 744 if (fshift && a->nounused == -1) { 745 SETERRQ4(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D block size %D, %D unneeded", m, A->cmap->n, A->rmap->bs, fshift*bs2); 746 } 747 ierr = PetscInfo5(A,"Matrix size: %D X %D, block size %D; storage space: %D unneeded, %D used\n",m,A->rmap->N,A->rmap->bs,fshift*bs2,a->nz*bs2);CHKERRQ(ierr); 748 ierr = PetscInfo1(A,"Number of mallocs during MatSetValues is %D\n",a->reallocs);CHKERRQ(ierr); 749 ierr = PetscInfo1(A,"Most nonzeros blocks in any row is %D\n",rmax);CHKERRQ(ierr); 750 a->reallocs = 0; 751 A->info.nz_unneeded = (PetscReal)fshift*bs2; 752 PetscFunctionReturn(0); 753 } 754 755 /* 756 This function returns an array of flags which indicate the locations of contiguous 757 blocks that should be zeroed. for eg: if bs = 3 and is = [0,1,2,3,5,6,7,8,9] 758 then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)] 759 Assume: sizes should be long enough to hold all the values. 760 */ 761 #undef __FUNCT__ 762 #define __FUNCT__ "MatZeroRows_SeqSBAIJ_Check_Blocks" 763 PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[],PetscInt n,PetscInt bs,PetscInt sizes[], PetscInt *bs_max) 764 { 765 PetscInt i,j,k,row; 766 PetscTruth flg; 767 768 PetscFunctionBegin; 769 for (i=0,j=0; i<n; j++) { 770 row = idx[i]; 771 if (row%bs!=0) { /* Not the begining of a block */ 772 sizes[j] = 1; 773 i++; 774 } else if (i+bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */ 775 sizes[j] = 1; /* Also makes sure atleast 'bs' values exist for next else */ 776 i++; 777 } else { /* Begining of the block, so check if the complete block exists */ 778 flg = PETSC_TRUE; 779 for (k=1; k<bs; k++) { 780 if (row+k != idx[i+k]) { /* break in the block */ 781 flg = PETSC_FALSE; 782 break; 783 } 784 } 785 if (flg) { /* No break in the bs */ 786 sizes[j] = bs; 787 i+= bs; 788 } else { 789 sizes[j] = 1; 790 i++; 791 } 792 } 793 } 794 *bs_max = j; 795 PetscFunctionReturn(0); 796 } 797 798 799 /* Only add/insert a(i,j) with i<=j (blocks). 800 Any a(i,j) with i>j input by user is ingored. 801 */ 802 803 #undef __FUNCT__ 804 #define __FUNCT__ "MatSetValues_SeqSBAIJ" 805 PetscErrorCode MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 806 { 807 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 808 PetscErrorCode ierr; 809 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1; 810 PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented; 811 PetscInt *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol; 812 PetscInt ridx,cidx,bs2=a->bs2; 813 MatScalar *ap,value,*aa=a->a,*bap; 814 815 PetscFunctionBegin; 816 for (k=0; k<m; k++) { /* loop over added rows */ 817 row = im[k]; /* row number */ 818 brow = row/bs; /* block row number */ 819 if (row < 0) continue; 820 #if defined(PETSC_USE_DEBUG) 821 if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1); 822 #endif 823 rp = aj + ai[brow]; /*ptr to beginning of column value of the row block*/ 824 ap = aa + bs2*ai[brow]; /*ptr to beginning of element value of the row block*/ 825 rmax = imax[brow]; /* maximum space allocated for this row */ 826 nrow = ailen[brow]; /* actual length of this row */ 827 low = 0; 828 829 for (l=0; l<n; l++) { /* loop over added columns */ 830 if (in[l] < 0) continue; 831 #if defined(PETSC_USE_DEBUG) 832 if (in[l] >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->rmap->N-1); 833 #endif 834 col = in[l]; 835 bcol = col/bs; /* block col number */ 836 837 if (brow > bcol) { 838 if (a->ignore_ltriangular){ 839 continue; /* ignore lower triangular values */ 840 } else { 841 SETERRQ(PETSC_ERR_USER,"Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)"); 842 } 843 } 844 845 ridx = row % bs; cidx = col % bs; /*row and col index inside the block */ 846 if ((brow==bcol && ridx<=cidx) || (brow<bcol)){ 847 /* element value a(k,l) */ 848 if (roworiented) { 849 value = v[l + k*n]; 850 } else { 851 value = v[k + l*m]; 852 } 853 854 /* move pointer bap to a(k,l) quickly and add/insert value */ 855 if (col <= lastcol) low = 0; high = nrow; 856 lastcol = col; 857 while (high-low > 7) { 858 t = (low+high)/2; 859 if (rp[t] > bcol) high = t; 860 else low = t; 861 } 862 for (i=low; i<high; i++) { 863 if (rp[i] > bcol) break; 864 if (rp[i] == bcol) { 865 bap = ap + bs2*i + bs*cidx + ridx; 866 if (is == ADD_VALUES) *bap += value; 867 else *bap = value; 868 /* for diag block, add/insert its symmetric element a(cidx,ridx) */ 869 if (brow == bcol && ridx < cidx){ 870 bap = ap + bs2*i + bs*ridx + cidx; 871 if (is == ADD_VALUES) *bap += value; 872 else *bap = value; 873 } 874 goto noinsert1; 875 } 876 } 877 878 if (nonew == 1) goto noinsert1; 879 if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col); 880 MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 881 882 N = nrow++ - 1; high++; 883 /* shift up all the later entries in this row */ 884 for (ii=N; ii>=i; ii--) { 885 rp[ii+1] = rp[ii]; 886 ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr); 887 } 888 if (N>=i) { 889 ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr); 890 } 891 rp[i] = bcol; 892 ap[bs2*i + bs*cidx + ridx] = value; 893 noinsert1:; 894 low = i; 895 } 896 } /* end of loop over added columns */ 897 ailen[brow] = nrow; 898 } /* end of loop over added rows */ 899 PetscFunctionReturn(0); 900 } 901 902 #undef __FUNCT__ 903 #define __FUNCT__ "MatICCFactor_SeqSBAIJ" 904 PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo *info) 905 { 906 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)inA->data; 907 Mat outA; 908 PetscErrorCode ierr; 909 PetscTruth row_identity; 910 911 PetscFunctionBegin; 912 if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 is supported for in-place icc"); 913 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 914 if (!row_identity) SETERRQ(PETSC_ERR_SUP,"Matrix reordering is not supported"); 915 if (inA->rmap->bs != 1) SETERRQ1(PETSC_ERR_SUP,"Matrix block size %D is not supported",inA->rmap->bs); /* Need to replace MatCholeskyFactorSymbolic_SeqSBAIJ_MSR()! */ 916 917 outA = inA; 918 inA->factor = MAT_FACTOR_ICC; 919 920 ierr = MatMarkDiagonal_SeqSBAIJ(inA);CHKERRQ(ierr); 921 ierr = MatSeqSBAIJSetNumericFactorization(inA,row_identity);CHKERRQ(ierr); 922 923 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 924 if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr); } 925 a->row = row; 926 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 927 if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr); } 928 a->col = row; 929 930 /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */ 931 if (a->icol) {ierr = ISInvertPermutation(row,PETSC_DECIDE, &a->icol);CHKERRQ(ierr);} 932 ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr); 933 934 if (!a->solve_work) { 935 ierr = PetscMalloc((inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr); 936 ierr = PetscLogObjectMemory(inA,(inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar));CHKERRQ(ierr); 937 } 938 939 ierr = MatCholeskyFactorNumeric(outA,inA,info);CHKERRQ(ierr); 940 PetscFunctionReturn(0); 941 } 942 943 EXTERN_C_BEGIN 944 #undef __FUNCT__ 945 #define __FUNCT__ "MatSeqSBAIJSetColumnIndices_SeqSBAIJ" 946 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt *indices) 947 { 948 Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data; 949 PetscInt i,nz,n; 950 951 PetscFunctionBegin; 952 nz = baij->maxnz; 953 n = mat->cmap->n; 954 for (i=0; i<nz; i++) { 955 baij->j[i] = indices[i]; 956 } 957 baij->nz = nz; 958 for (i=0; i<n; i++) { 959 baij->ilen[i] = baij->imax[i]; 960 } 961 PetscFunctionReturn(0); 962 } 963 EXTERN_C_END 964 965 #undef __FUNCT__ 966 #define __FUNCT__ "MatSeqSBAIJSetColumnIndices" 967 /*@ 968 MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows 969 in the matrix. 970 971 Input Parameters: 972 + mat - the SeqSBAIJ matrix 973 - indices - the column indices 974 975 Level: advanced 976 977 Notes: 978 This can be called if you have precomputed the nonzero structure of the 979 matrix and want to provide it to the matrix object to improve the performance 980 of the MatSetValues() operation. 981 982 You MUST have set the correct numbers of nonzeros per row in the call to 983 MatCreateSeqSBAIJ(), and the columns indices MUST be sorted. 984 985 MUST be called before any calls to MatSetValues() 986 987 .seealso: MatCreateSeqSBAIJ 988 @*/ 989 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt *indices) 990 { 991 PetscErrorCode ierr,(*f)(Mat,PetscInt *); 992 993 PetscFunctionBegin; 994 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 995 PetscValidPointer(indices,2); 996 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqSBAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr); 997 if (f) { 998 ierr = (*f)(mat,indices);CHKERRQ(ierr); 999 } else { 1000 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices"); 1001 } 1002 PetscFunctionReturn(0); 1003 } 1004 1005 #undef __FUNCT__ 1006 #define __FUNCT__ "MatCopy_SeqSBAIJ" 1007 PetscErrorCode MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str) 1008 { 1009 PetscErrorCode ierr; 1010 1011 PetscFunctionBegin; 1012 /* If the two matrices have the same copy implementation, use fast copy. */ 1013 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 1014 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 1015 Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data; 1016 1017 if (a->i[A->rmap->N] != b->i[B->rmap->N]) { 1018 SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different"); 1019 } 1020 ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->N])*sizeof(PetscScalar));CHKERRQ(ierr); 1021 } else { 1022 ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr); 1023 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 1024 ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr); 1025 } 1026 PetscFunctionReturn(0); 1027 } 1028 1029 #undef __FUNCT__ 1030 #define __FUNCT__ "MatSetUpPreallocation_SeqSBAIJ" 1031 PetscErrorCode MatSetUpPreallocation_SeqSBAIJ(Mat A) 1032 { 1033 PetscErrorCode ierr; 1034 1035 PetscFunctionBegin; 1036 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(A,-PetscMax(A->rmap->bs,1),PETSC_DEFAULT,0);CHKERRQ(ierr); 1037 PetscFunctionReturn(0); 1038 } 1039 1040 #undef __FUNCT__ 1041 #define __FUNCT__ "MatGetArray_SeqSBAIJ" 1042 PetscErrorCode MatGetArray_SeqSBAIJ(Mat A,PetscScalar *array[]) 1043 { 1044 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 1045 PetscFunctionBegin; 1046 *array = a->a; 1047 PetscFunctionReturn(0); 1048 } 1049 1050 #undef __FUNCT__ 1051 #define __FUNCT__ "MatRestoreArray_SeqSBAIJ" 1052 PetscErrorCode MatRestoreArray_SeqSBAIJ(Mat A,PetscScalar *array[]) 1053 { 1054 PetscFunctionBegin; 1055 PetscFunctionReturn(0); 1056 } 1057 1058 #include "petscblaslapack.h" 1059 #undef __FUNCT__ 1060 #define __FUNCT__ "MatAXPY_SeqSBAIJ" 1061 PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 1062 { 1063 Mat_SeqSBAIJ *x=(Mat_SeqSBAIJ *)X->data, *y=(Mat_SeqSBAIJ *)Y->data; 1064 PetscErrorCode ierr; 1065 PetscInt i,bs=Y->rmap->bs,bs2,j; 1066 PetscBLASInt one = 1,bnz = PetscBLASIntCast(x->nz); 1067 1068 PetscFunctionBegin; 1069 if (str == SAME_NONZERO_PATTERN) { 1070 PetscScalar alpha = a; 1071 BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one); 1072 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 1073 if (y->xtoy && y->XtoY != X) { 1074 ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 1075 ierr = MatDestroy(y->XtoY);CHKERRQ(ierr); 1076 } 1077 if (!y->xtoy) { /* get xtoy */ 1078 ierr = MatAXPYGetxtoy_Private(x->mbs,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr); 1079 y->XtoY = X; 1080 } 1081 bs2 = bs*bs; 1082 for (i=0; i<x->nz; i++) { 1083 j = 0; 1084 while (j < bs2){ 1085 y->a[bs2*y->xtoy[i]+j] += a*(x->a[bs2*i+j]); 1086 j++; 1087 } 1088 } 1089 ierr = PetscInfo3(Y,"ratio of nnz_s(X)/nnz_s(Y): %D/%D = %G\n",bs2*x->nz,bs2*y->nz,(PetscReal)(bs2*x->nz)/(bs2*y->nz));CHKERRQ(ierr); 1090 } else { 1091 ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr); 1092 ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 1093 ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr); 1094 } 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "MatIsSymmetric_SeqSBAIJ" 1100 PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg) 1101 { 1102 PetscFunctionBegin; 1103 *flg = PETSC_TRUE; 1104 PetscFunctionReturn(0); 1105 } 1106 1107 #undef __FUNCT__ 1108 #define __FUNCT__ "MatIsStructurallySymmetric_SeqSBAIJ" 1109 PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscTruth *flg) 1110 { 1111 PetscFunctionBegin; 1112 *flg = PETSC_TRUE; 1113 PetscFunctionReturn(0); 1114 } 1115 1116 #undef __FUNCT__ 1117 #define __FUNCT__ "MatIsHermitian_SeqSBAIJ" 1118 PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg) 1119 { 1120 PetscFunctionBegin; 1121 *flg = PETSC_FALSE; 1122 PetscFunctionReturn(0); 1123 } 1124 1125 #undef __FUNCT__ 1126 #define __FUNCT__ "MatRealPart_SeqSBAIJ" 1127 PetscErrorCode MatRealPart_SeqSBAIJ(Mat A) 1128 { 1129 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 1130 PetscInt i,nz = a->bs2*a->i[a->mbs]; 1131 MatScalar *aa = a->a; 1132 1133 PetscFunctionBegin; 1134 for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 1135 PetscFunctionReturn(0); 1136 } 1137 1138 #undef __FUNCT__ 1139 #define __FUNCT__ "MatImaginaryPart_SeqSBAIJ" 1140 PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A) 1141 { 1142 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 1143 PetscInt i,nz = a->bs2*a->i[a->mbs]; 1144 MatScalar *aa = a->a; 1145 1146 PetscFunctionBegin; 1147 for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 1148 PetscFunctionReturn(0); 1149 } 1150 1151 /* -------------------------------------------------------------------*/ 1152 static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ, 1153 MatGetRow_SeqSBAIJ, 1154 MatRestoreRow_SeqSBAIJ, 1155 MatMult_SeqSBAIJ_N, 1156 /* 4*/ MatMultAdd_SeqSBAIJ_N, 1157 MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */ 1158 MatMultAdd_SeqSBAIJ_N, 1159 0, 1160 0, 1161 0, 1162 /*10*/ 0, 1163 0, 1164 MatCholeskyFactor_SeqSBAIJ, 1165 MatRelax_SeqSBAIJ, 1166 MatTranspose_SeqSBAIJ, 1167 /*15*/ MatGetInfo_SeqSBAIJ, 1168 MatEqual_SeqSBAIJ, 1169 MatGetDiagonal_SeqSBAIJ, 1170 MatDiagonalScale_SeqSBAIJ, 1171 MatNorm_SeqSBAIJ, 1172 /*20*/ 0, 1173 MatAssemblyEnd_SeqSBAIJ, 1174 0, 1175 MatSetOption_SeqSBAIJ, 1176 MatZeroEntries_SeqSBAIJ, 1177 /*25*/ 0, 1178 0, 1179 0, 1180 0, 1181 0, 1182 /*30*/ MatSetUpPreallocation_SeqSBAIJ, 1183 0, 1184 0, 1185 MatGetArray_SeqSBAIJ, 1186 MatRestoreArray_SeqSBAIJ, 1187 /*35*/ MatDuplicate_SeqSBAIJ, 1188 0, 1189 0, 1190 0, 1191 MatICCFactor_SeqSBAIJ, 1192 /*40*/ MatAXPY_SeqSBAIJ, 1193 MatGetSubMatrices_SeqSBAIJ, 1194 MatIncreaseOverlap_SeqSBAIJ, 1195 MatGetValues_SeqSBAIJ, 1196 MatCopy_SeqSBAIJ, 1197 /*45*/ 0, 1198 MatScale_SeqSBAIJ, 1199 0, 1200 0, 1201 0, 1202 /*50*/ 0, 1203 MatGetRowIJ_SeqSBAIJ, 1204 MatRestoreRowIJ_SeqSBAIJ, 1205 0, 1206 0, 1207 /*55*/ 0, 1208 0, 1209 0, 1210 0, 1211 MatSetValuesBlocked_SeqSBAIJ, 1212 /*60*/ MatGetSubMatrix_SeqSBAIJ, 1213 0, 1214 0, 1215 0, 1216 0, 1217 /*65*/ 0, 1218 0, 1219 0, 1220 0, 1221 0, 1222 /*70*/ MatGetRowMaxAbs_SeqSBAIJ, 1223 0, 1224 0, 1225 0, 1226 0, 1227 /*75*/ 0, 1228 0, 1229 0, 1230 0, 1231 0, 1232 /*80*/ 0, 1233 0, 1234 0, 1235 #if !defined(PETSC_USE_COMPLEX) 1236 MatGetInertia_SeqSBAIJ, 1237 #else 1238 0, 1239 #endif 1240 MatLoad_SeqSBAIJ, 1241 /*85*/ MatIsSymmetric_SeqSBAIJ, 1242 MatIsHermitian_SeqSBAIJ, 1243 MatIsStructurallySymmetric_SeqSBAIJ, 1244 0, 1245 0, 1246 /*90*/ 0, 1247 0, 1248 0, 1249 0, 1250 0, 1251 /*95*/ 0, 1252 0, 1253 0, 1254 0, 1255 0, 1256 /*100*/0, 1257 0, 1258 0, 1259 0, 1260 0, 1261 /*105*/0, 1262 MatRealPart_SeqSBAIJ, 1263 MatImaginaryPart_SeqSBAIJ, 1264 MatGetRowUpperTriangular_SeqSBAIJ, 1265 MatRestoreRowUpperTriangular_SeqSBAIJ, 1266 /*110*/0, 1267 0, 1268 0, 1269 0, 1270 MatMissingDiagonal_SeqSBAIJ 1271 }; 1272 1273 EXTERN_C_BEGIN 1274 #undef __FUNCT__ 1275 #define __FUNCT__ "MatStoreValues_SeqSBAIJ" 1276 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat) 1277 { 1278 Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1279 PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2; 1280 PetscErrorCode ierr; 1281 1282 PetscFunctionBegin; 1283 if (aij->nonew != 1) { 1284 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 1285 } 1286 1287 /* allocate space for values if not already there */ 1288 if (!aij->saved_values) { 1289 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 1290 } 1291 1292 /* copy values over */ 1293 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 1294 PetscFunctionReturn(0); 1295 } 1296 EXTERN_C_END 1297 1298 EXTERN_C_BEGIN 1299 #undef __FUNCT__ 1300 #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ" 1301 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat) 1302 { 1303 Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1304 PetscErrorCode ierr; 1305 PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2; 1306 1307 PetscFunctionBegin; 1308 if (aij->nonew != 1) { 1309 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 1310 } 1311 if (!aij->saved_values) { 1312 SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 1313 } 1314 1315 /* copy values over */ 1316 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 1317 PetscFunctionReturn(0); 1318 } 1319 EXTERN_C_END 1320 1321 EXTERN_C_BEGIN 1322 #undef __FUNCT__ 1323 #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ" 1324 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz) 1325 { 1326 Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data; 1327 PetscErrorCode ierr; 1328 PetscInt i,mbs,bs2, newbs = PetscAbs(bs); 1329 PetscTruth skipallocation = PETSC_FALSE,flg; 1330 1331 PetscFunctionBegin; 1332 B->preallocated = PETSC_TRUE; 1333 if (bs < 0) { 1334 ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr); 1335 ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr); 1336 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1337 bs = PetscAbs(bs); 1338 } 1339 if (nnz && newbs != bs) { 1340 SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz"); 1341 } 1342 bs = newbs; 1343 1344 B->rmap->bs = B->cmap->bs = bs; 1345 ierr = PetscMapSetUp(B->rmap);CHKERRQ(ierr); 1346 ierr = PetscMapSetUp(B->cmap);CHKERRQ(ierr); 1347 1348 mbs = B->rmap->N/bs; 1349 bs2 = bs*bs; 1350 1351 if (mbs*bs != B->rmap->N) { 1352 SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize"); 1353 } 1354 1355 if (nz == MAT_SKIP_ALLOCATION) { 1356 skipallocation = PETSC_TRUE; 1357 nz = 0; 1358 } 1359 1360 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 1361 if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz); 1362 if (nnz) { 1363 for (i=0; i<mbs; i++) { 1364 if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]); 1365 if (nnz[i] > mbs) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than block row length: local row %D value %D rowlength %D",i,nnz[i],mbs); 1366 } 1367 } 1368 1369 B->ops->mult = MatMult_SeqSBAIJ_N; 1370 B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1371 B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1372 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 1373 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr); 1374 if (!flg) { 1375 switch (bs) { 1376 case 1: 1377 B->ops->mult = MatMult_SeqSBAIJ_1; 1378 B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1379 B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1380 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 1381 break; 1382 case 2: 1383 B->ops->mult = MatMult_SeqSBAIJ_2; 1384 B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1385 B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1386 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 1387 break; 1388 case 3: 1389 B->ops->mult = MatMult_SeqSBAIJ_3; 1390 B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1391 B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1392 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 1393 break; 1394 case 4: 1395 B->ops->mult = MatMult_SeqSBAIJ_4; 1396 B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1397 B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1398 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 1399 break; 1400 case 5: 1401 B->ops->mult = MatMult_SeqSBAIJ_5; 1402 B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1403 B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1404 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 1405 break; 1406 case 6: 1407 B->ops->mult = MatMult_SeqSBAIJ_6; 1408 B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1409 B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1410 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 1411 break; 1412 case 7: 1413 B->ops->mult = MatMult_SeqSBAIJ_7; 1414 B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1415 B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1416 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 1417 break; 1418 } 1419 } 1420 1421 b->mbs = mbs; 1422 b->nbs = mbs; 1423 if (!skipallocation) { 1424 if (!b->imax) { 1425 ierr = PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);CHKERRQ(ierr); 1426 ierr = PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));CHKERRQ(ierr); 1427 } 1428 if (!nnz) { 1429 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 1430 else if (nz <= 0) nz = 1; 1431 for (i=0; i<mbs; i++) { 1432 b->imax[i] = nz; 1433 } 1434 nz = nz*mbs; /* total nz */ 1435 } else { 1436 nz = 0; 1437 for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 1438 } 1439 /* b->ilen will count nonzeros in each block row so far. */ 1440 for (i=0; i<mbs; i++) { b->ilen[i] = 0;} 1441 /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 1442 1443 /* allocate the matrix space */ 1444 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 1445 ierr = PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);CHKERRQ(ierr); 1446 ierr = PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 1447 ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr); 1448 ierr = PetscMemzero(b->j,nz*sizeof(PetscInt));CHKERRQ(ierr); 1449 b->singlemalloc = PETSC_TRUE; 1450 1451 /* pointer to beginning of each row */ 1452 b->i[0] = 0; 1453 for (i=1; i<mbs+1; i++) { 1454 b->i[i] = b->i[i-1] + b->imax[i-1]; 1455 } 1456 b->free_a = PETSC_TRUE; 1457 b->free_ij = PETSC_TRUE; 1458 } else { 1459 b->free_a = PETSC_FALSE; 1460 b->free_ij = PETSC_FALSE; 1461 } 1462 1463 B->rmap->bs = bs; 1464 b->bs2 = bs2; 1465 b->nz = 0; 1466 b->maxnz = nz*bs2; 1467 1468 b->inew = 0; 1469 b->jnew = 0; 1470 b->anew = 0; 1471 b->a2anew = 0; 1472 b->permute = PETSC_FALSE; 1473 PetscFunctionReturn(0); 1474 } 1475 EXTERN_C_END 1476 1477 #undef __FUNCT__ 1478 #define __FUNCT__ "MatSeqBAIJSetNumericFactorization" 1479 /* 1480 This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1481 */ 1482 PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat B,PetscTruth natural) 1483 { 1484 PetscErrorCode ierr; 1485 PetscTruth flg; 1486 PetscInt bs = B->rmap->bs; 1487 1488 PetscFunctionBegin; 1489 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr); 1490 if (flg) bs = 8; 1491 1492 if (!natural) { 1493 switch (bs) { 1494 case 1: 1495 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1; 1496 break; 1497 case 2: 1498 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; 1499 break; 1500 case 3: 1501 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; 1502 break; 1503 case 4: 1504 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; 1505 break; 1506 case 5: 1507 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; 1508 break; 1509 case 6: 1510 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; 1511 break; 1512 case 7: 1513 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; 1514 break; 1515 default: 1516 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; 1517 break; 1518 } 1519 } else { 1520 switch (bs) { 1521 case 1: 1522 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering; 1523 break; 1524 case 2: 1525 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; 1526 break; 1527 case 3: 1528 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; 1529 break; 1530 case 4: 1531 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; 1532 break; 1533 case 5: 1534 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; 1535 break; 1536 case 6: 1537 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; 1538 break; 1539 case 7: 1540 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; 1541 break; 1542 default: 1543 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; 1544 break; 1545 } 1546 } 1547 PetscFunctionReturn(0); 1548 } 1549 1550 EXTERN_C_BEGIN 1551 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*); 1552 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*); 1553 EXTERN_C_END 1554 1555 1556 EXTERN_C_BEGIN 1557 #undef __FUNCT__ 1558 #define __FUNCT__ "MatGetFactor_seqsbaij_petsc" 1559 PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B) 1560 { 1561 PetscInt n = A->rmap->n; 1562 PetscErrorCode ierr; 1563 1564 PetscFunctionBegin; 1565 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 1566 ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr); 1567 if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 1568 ierr = MatSetType(*B,MATSEQSBAIJ);CHKERRQ(ierr); 1569 ierr = MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);CHKERRQ(ierr); 1570 (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1571 (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 1572 } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported"); 1573 (*B)->factor = ftype; 1574 PetscFunctionReturn(0); 1575 } 1576 EXTERN_C_END 1577 1578 EXTERN_C_BEGIN 1579 #undef __FUNCT__ 1580 #define __FUNCT__ "MatGetFactorAvailable_seqsbaij_petsc" 1581 PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg) 1582 { 1583 PetscFunctionBegin; 1584 if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 1585 *flg = PETSC_TRUE; 1586 } else { 1587 *flg = PETSC_FALSE; 1588 } 1589 PetscFunctionReturn(0); 1590 } 1591 EXTERN_C_END 1592 1593 EXTERN_C_BEGIN 1594 #if defined(PETSC_HAVE_MUMPS) 1595 extern PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat,MatFactorType,Mat*); 1596 #endif 1597 #if defined(PETSC_HAVE_SPOOLES) 1598 extern PetscErrorCode MatGetFactor_seqsbaij_spooles(Mat,MatFactorType,Mat*); 1599 #endif 1600 EXTERN_C_END 1601 1602 /*MC 1603 MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 1604 based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 1605 1606 Options Database Keys: 1607 . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions() 1608 1609 Level: beginner 1610 1611 .seealso: MatCreateSeqSBAIJ 1612 M*/ 1613 1614 EXTERN_C_BEGIN 1615 #undef __FUNCT__ 1616 #define __FUNCT__ "MatCreate_SeqSBAIJ" 1617 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B) 1618 { 1619 Mat_SeqSBAIJ *b; 1620 PetscErrorCode ierr; 1621 PetscMPIInt size; 1622 PetscTruth flg; 1623 1624 PetscFunctionBegin; 1625 ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 1626 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1"); 1627 1628 ierr = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr); 1629 B->data = (void*)b; 1630 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1631 B->ops->destroy = MatDestroy_SeqSBAIJ; 1632 B->ops->view = MatView_SeqSBAIJ; 1633 B->mapping = 0; 1634 b->row = 0; 1635 b->icol = 0; 1636 b->reallocs = 0; 1637 b->saved_values = 0; 1638 1639 1640 b->roworiented = PETSC_TRUE; 1641 b->nonew = 0; 1642 b->diag = 0; 1643 b->solve_work = 0; 1644 b->mult_work = 0; 1645 B->spptr = 0; 1646 b->keepzeroedrows = PETSC_FALSE; 1647 b->xtoy = 0; 1648 b->XtoY = 0; 1649 1650 b->inew = 0; 1651 b->jnew = 0; 1652 b->anew = 0; 1653 b->a2anew = 0; 1654 b->permute = PETSC_FALSE; 1655 1656 b->ignore_ltriangular = PETSC_FALSE; 1657 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_ignore_lower_triangular",&flg);CHKERRQ(ierr); 1658 if (flg) b->ignore_ltriangular = PETSC_TRUE; 1659 1660 b->getrow_utriangular = PETSC_FALSE; 1661 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_getrow_uppertriangular",&flg);CHKERRQ(ierr); 1662 if (flg) b->getrow_utriangular = PETSC_TRUE; 1663 1664 #if defined(PETSC_HAVE_SPOOLES) 1665 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C", 1666 "MatGetFactor_seqsbaij_spooles", 1667 MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr); 1668 #endif 1669 #if defined(PETSC_HAVE_MUMPS) 1670 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C", 1671 "MatGetFactor_seqsbaij_mumps", 1672 MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr); 1673 #endif 1674 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C", 1675 "MatGetFactorAvailable_seqsbaij_petsc", 1676 MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr); 1677 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C", 1678 "MatGetFactor_seqsbaij_petsc", 1679 MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr); 1680 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 1681 "MatStoreValues_SeqSBAIJ", 1682 MatStoreValues_SeqSBAIJ);CHKERRQ(ierr); 1683 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 1684 "MatRetrieveValues_SeqSBAIJ", 1685 (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr); 1686 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C", 1687 "MatSeqSBAIJSetColumnIndices_SeqSBAIJ", 1688 MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr); 1689 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C", 1690 "MatConvert_SeqSBAIJ_SeqAIJ", 1691 MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr); 1692 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C", 1693 "MatConvert_SeqSBAIJ_SeqBAIJ", 1694 MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr); 1695 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C", 1696 "MatSeqSBAIJSetPreallocation_SeqSBAIJ", 1697 MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr); 1698 1699 B->symmetric = PETSC_TRUE; 1700 B->structurally_symmetric = PETSC_TRUE; 1701 B->symmetric_set = PETSC_TRUE; 1702 B->structurally_symmetric_set = PETSC_TRUE; 1703 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr); 1704 PetscFunctionReturn(0); 1705 } 1706 EXTERN_C_END 1707 1708 #undef __FUNCT__ 1709 #define __FUNCT__ "MatSeqSBAIJSetPreallocation" 1710 /*@C 1711 MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 1712 compressed row) format. For good matrix assembly performance the 1713 user should preallocate the matrix storage by setting the parameter nz 1714 (or the array nnz). By setting these parameters accurately, performance 1715 during matrix assembly can be increased by more than a factor of 50. 1716 1717 Collective on Mat 1718 1719 Input Parameters: 1720 + A - the symmetric matrix 1721 . bs - size of block 1722 . nz - number of block nonzeros per block row (same for all rows) 1723 - nnz - array containing the number of block nonzeros in the upper triangular plus 1724 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1725 1726 Options Database Keys: 1727 . -mat_no_unroll - uses code that does not unroll the loops in the 1728 block calculations (much slower) 1729 . -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1730 1731 Level: intermediate 1732 1733 Notes: 1734 Specify the preallocated storage with either nz or nnz (not both). 1735 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1736 allocation. For additional details, see the users manual chapter on 1737 matrices. 1738 1739 You can call MatGetInfo() to get information on how effective the preallocation was; 1740 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 1741 You can also run with the option -info and look for messages with the string 1742 malloc in them to see if additional memory allocation was needed. 1743 1744 If the nnz parameter is given then the nz parameter is ignored 1745 1746 1747 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1748 @*/ 1749 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[]) 1750 { 1751 PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]); 1752 1753 PetscFunctionBegin; 1754 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 1755 if (f) { 1756 ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr); 1757 } 1758 PetscFunctionReturn(0); 1759 } 1760 1761 #undef __FUNCT__ 1762 #define __FUNCT__ "MatCreateSeqSBAIJ" 1763 /*@C 1764 MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block 1765 compressed row) format. For good matrix assembly performance the 1766 user should preallocate the matrix storage by setting the parameter nz 1767 (or the array nnz). By setting these parameters accurately, performance 1768 during matrix assembly can be increased by more than a factor of 50. 1769 1770 Collective on MPI_Comm 1771 1772 Input Parameters: 1773 + comm - MPI communicator, set to PETSC_COMM_SELF 1774 . bs - size of block 1775 . m - number of rows, or number of columns 1776 . nz - number of block nonzeros per block row (same for all rows) 1777 - nnz - array containing the number of block nonzeros in the upper triangular plus 1778 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1779 1780 Output Parameter: 1781 . A - the symmetric matrix 1782 1783 Options Database Keys: 1784 . -mat_no_unroll - uses code that does not unroll the loops in the 1785 block calculations (much slower) 1786 . -mat_block_size - size of the blocks to use 1787 1788 Level: intermediate 1789 1790 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 1791 MatXXXXSetPreallocation() paradgm instead of this routine directly. This is definitely 1792 true if you plan to use the external direct solvers such as SuperLU, MUMPS or Spooles. 1793 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 1794 1795 Notes: 1796 The number of rows and columns must be divisible by blocksize. 1797 This matrix type does not support complex Hermitian operation. 1798 1799 Specify the preallocated storage with either nz or nnz (not both). 1800 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1801 allocation. For additional details, see the users manual chapter on 1802 matrices. 1803 1804 If the nnz parameter is given then the nz parameter is ignored 1805 1806 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1807 @*/ 1808 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 1809 { 1810 PetscErrorCode ierr; 1811 1812 PetscFunctionBegin; 1813 ierr = MatCreate(comm,A);CHKERRQ(ierr); 1814 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 1815 ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr); 1816 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr); 1817 PetscFunctionReturn(0); 1818 } 1819 1820 #undef __FUNCT__ 1821 #define __FUNCT__ "MatDuplicate_SeqSBAIJ" 1822 PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 1823 { 1824 Mat C; 1825 Mat_SeqSBAIJ *c,*a = (Mat_SeqSBAIJ*)A->data; 1826 PetscErrorCode ierr; 1827 PetscInt i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2; 1828 1829 PetscFunctionBegin; 1830 if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix"); 1831 1832 *B = 0; 1833 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1834 ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr); 1835 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1836 ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1837 c = (Mat_SeqSBAIJ*)C->data; 1838 1839 C->preallocated = PETSC_TRUE; 1840 C->factor = A->factor; 1841 c->row = 0; 1842 c->icol = 0; 1843 c->saved_values = 0; 1844 c->keepzeroedrows = a->keepzeroedrows; 1845 C->assembled = PETSC_TRUE; 1846 1847 ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr); 1848 ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr); 1849 c->bs2 = a->bs2; 1850 c->mbs = a->mbs; 1851 c->nbs = a->nbs; 1852 1853 ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr); 1854 for (i=0; i<mbs; i++) { 1855 c->imax[i] = a->imax[i]; 1856 c->ilen[i] = a->ilen[i]; 1857 } 1858 1859 /* allocate the matrix space */ 1860 ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr); 1861 c->singlemalloc = PETSC_TRUE; 1862 ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1863 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr); 1864 if (mbs > 0) { 1865 ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr); 1866 if (cpvalues == MAT_COPY_VALUES) { 1867 ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1868 } else { 1869 ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1870 } 1871 } 1872 1873 c->roworiented = a->roworiented; 1874 c->nonew = a->nonew; 1875 1876 if (a->diag) { 1877 ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr); 1878 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1879 for (i=0; i<mbs; i++) { 1880 c->diag[i] = a->diag[i]; 1881 } 1882 } else c->diag = 0; 1883 c->nz = a->nz; 1884 c->maxnz = a->maxnz; 1885 c->solve_work = 0; 1886 c->mult_work = 0; 1887 c->free_a = PETSC_TRUE; 1888 c->free_ij = PETSC_TRUE; 1889 *B = C; 1890 ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 1891 PetscFunctionReturn(0); 1892 } 1893 1894 #undef __FUNCT__ 1895 #define __FUNCT__ "MatLoad_SeqSBAIJ" 1896 PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A) 1897 { 1898 Mat_SeqSBAIJ *a; 1899 Mat B; 1900 PetscErrorCode ierr; 1901 int fd; 1902 PetscMPIInt size; 1903 PetscInt i,nz,header[4],*rowlengths=0,M,N,bs=1; 1904 PetscInt *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount; 1905 PetscInt kmax,jcount,block,idx,point,nzcountb,extra_rows; 1906 PetscInt *masked,nmask,tmp,bs2,ishift; 1907 PetscScalar *aa; 1908 MPI_Comm comm = ((PetscObject)viewer)->comm; 1909 1910 PetscFunctionBegin; 1911 ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr); 1912 bs2 = bs*bs; 1913 1914 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1915 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor"); 1916 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1917 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 1918 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object"); 1919 M = header[1]; N = header[2]; nz = header[3]; 1920 1921 if (header[3] < 0) { 1922 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ"); 1923 } 1924 1925 if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices"); 1926 1927 /* 1928 This code adds extra rows to make sure the number of rows is 1929 divisible by the blocksize 1930 */ 1931 mbs = M/bs; 1932 extra_rows = bs - M + bs*(mbs); 1933 if (extra_rows == bs) extra_rows = 0; 1934 else mbs++; 1935 if (extra_rows) { 1936 ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr); 1937 } 1938 1939 /* read in row lengths */ 1940 ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 1941 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 1942 for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1; 1943 1944 /* read in column indices */ 1945 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr); 1946 ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr); 1947 for (i=0; i<extra_rows; i++) jj[nz+i] = M+i; 1948 1949 /* loop over row lengths determining block row lengths */ 1950 ierr = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr); 1951 ierr = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1952 ierr = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr); 1953 ierr = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1954 masked = mask + mbs; 1955 rowcount = 0; nzcount = 0; 1956 for (i=0; i<mbs; i++) { 1957 nmask = 0; 1958 for (j=0; j<bs; j++) { 1959 kmax = rowlengths[rowcount]; 1960 for (k=0; k<kmax; k++) { 1961 tmp = jj[nzcount++]/bs; /* block col. index */ 1962 if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;} 1963 } 1964 rowcount++; 1965 } 1966 s_browlengths[i] += nmask; 1967 1968 /* zero out the mask elements we set */ 1969 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 1970 } 1971 1972 /* create our matrix */ 1973 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 1974 ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr); 1975 ierr = MatSetType(B,type);CHKERRQ(ierr); 1976 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr); 1977 a = (Mat_SeqSBAIJ*)B->data; 1978 1979 /* set matrix "i" values */ 1980 a->i[0] = 0; 1981 for (i=1; i<= mbs; i++) { 1982 a->i[i] = a->i[i-1] + s_browlengths[i-1]; 1983 a->ilen[i-1] = s_browlengths[i-1]; 1984 } 1985 a->nz = a->i[mbs]; 1986 1987 /* read in nonzero values */ 1988 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr); 1989 ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr); 1990 for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0; 1991 1992 /* set "a" and "j" values into matrix */ 1993 nzcount = 0; jcount = 0; 1994 for (i=0; i<mbs; i++) { 1995 nzcountb = nzcount; 1996 nmask = 0; 1997 for (j=0; j<bs; j++) { 1998 kmax = rowlengths[i*bs+j]; 1999 for (k=0; k<kmax; k++) { 2000 tmp = jj[nzcount++]/bs; /* block col. index */ 2001 if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;} 2002 } 2003 } 2004 /* sort the masked values */ 2005 ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr); 2006 2007 /* set "j" values into matrix */ 2008 maskcount = 1; 2009 for (j=0; j<nmask; j++) { 2010 a->j[jcount++] = masked[j]; 2011 mask[masked[j]] = maskcount++; 2012 } 2013 2014 /* set "a" values into matrix */ 2015 ishift = bs2*a->i[i]; 2016 for (j=0; j<bs; j++) { 2017 kmax = rowlengths[i*bs+j]; 2018 for (k=0; k<kmax; k++) { 2019 tmp = jj[nzcountb]/bs ; /* block col. index */ 2020 if (tmp >= i){ 2021 block = mask[tmp] - 1; 2022 point = jj[nzcountb] - bs*tmp; 2023 idx = ishift + bs2*block + j + bs*point; 2024 a->a[idx] = aa[nzcountb]; 2025 } 2026 nzcountb++; 2027 } 2028 } 2029 /* zero out the mask elements we set */ 2030 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 2031 } 2032 if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix"); 2033 2034 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 2035 ierr = PetscFree(s_browlengths);CHKERRQ(ierr); 2036 ierr = PetscFree(aa);CHKERRQ(ierr); 2037 ierr = PetscFree(jj);CHKERRQ(ierr); 2038 ierr = PetscFree(mask);CHKERRQ(ierr); 2039 2040 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2041 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2042 ierr = MatView_Private(B);CHKERRQ(ierr); 2043 *A = B; 2044 PetscFunctionReturn(0); 2045 } 2046 2047 #undef __FUNCT__ 2048 #define __FUNCT__ "MatRelax_SeqSBAIJ" 2049 PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 2050 { 2051 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 2052 MatScalar *aa=a->a,*v,*v1; 2053 PetscScalar *x,*b,*t,sum,d; 2054 PetscErrorCode ierr; 2055 PetscInt m=a->mbs,bs=A->rmap->bs,*ai=a->i,*aj=a->j; 2056 PetscInt nz,nz1,*vj,*vj1,i; 2057 2058 PetscFunctionBegin; 2059 if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat"); 2060 2061 its = its*lits; 2062 if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 2063 2064 if (bs > 1) 2065 SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented"); 2066 2067 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 2068 if (xx != bb) { 2069 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 2070 } else { 2071 b = x; 2072 } 2073 2074 if (!a->relax_work) { 2075 ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr); 2076 } 2077 t = a->relax_work; 2078 2079 if (flag & SOR_ZERO_INITIAL_GUESS) { 2080 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2081 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2082 2083 for (i=0; i<m; i++){ 2084 d = *(aa + ai[i]); /* diag[i] */ 2085 v = aa + ai[i] + 1; 2086 vj = aj + ai[i] + 1; 2087 nz = ai[i+1] - ai[i] - 1; 2088 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2089 x[i] = omega*t[i]/d; 2090 while (nz--) t[*vj++] -= x[i]*(*v++); /* update rhs */ 2091 } 2092 } 2093 2094 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2095 if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){ 2096 t = b; 2097 } 2098 2099 for (i=m-1; i>=0; i--){ 2100 d = *(aa + ai[i]); 2101 v = aa + ai[i] + 1; 2102 vj = aj + ai[i] + 1; 2103 nz = ai[i+1] - ai[i] - 1; 2104 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2105 sum = t[i]; 2106 while (nz--) sum -= x[*vj++]*(*v++); 2107 x[i] = (1-omega)*x[i] + omega*sum/d; 2108 } 2109 t = a->relax_work; 2110 } 2111 its--; 2112 } 2113 2114 while (its--) { 2115 /* 2116 forward sweep: 2117 for i=0,...,m-1: 2118 sum[i] = (b[i] - U(i,:)x )/d[i]; 2119 x[i] = (1-omega)x[i] + omega*sum[i]; 2120 b = b - x[i]*U^T(i,:); 2121 2122 */ 2123 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2124 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2125 2126 for (i=0; i<m; i++){ 2127 d = *(aa + ai[i]); /* diag[i] */ 2128 v = aa + ai[i] + 1; v1=v; 2129 vj = aj + ai[i] + 1; vj1=vj; 2130 nz = ai[i+1] - ai[i] - 1; nz1=nz; 2131 sum = t[i]; 2132 ierr = PetscLogFlops(4*nz-2);CHKERRQ(ierr); 2133 while (nz1--) sum -= (*v1++)*x[*vj1++]; 2134 x[i] = (1-omega)*x[i] + omega*sum/d; 2135 while (nz--) t[*vj++] -= x[i]*(*v++); 2136 } 2137 } 2138 2139 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2140 /* 2141 backward sweep: 2142 b = b - x[i]*U^T(i,:), i=0,...,n-2 2143 for i=m-1,...,0: 2144 sum[i] = (b[i] - U(i,:)x )/d[i]; 2145 x[i] = (1-omega)x[i] + omega*sum[i]; 2146 */ 2147 /* if there was a forward sweep done above then I thing the next two for loops are not needed */ 2148 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2149 2150 for (i=0; i<m-1; i++){ /* update rhs */ 2151 v = aa + ai[i] + 1; 2152 vj = aj + ai[i] + 1; 2153 nz = ai[i+1] - ai[i] - 1; 2154 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2155 while (nz--) t[*vj++] -= x[i]*(*v++); 2156 } 2157 for (i=m-1; i>=0; i--){ 2158 d = *(aa + ai[i]); 2159 v = aa + ai[i] + 1; 2160 vj = aj + ai[i] + 1; 2161 nz = ai[i+1] - ai[i] - 1; 2162 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2163 sum = t[i]; 2164 while (nz--) sum -= x[*vj++]*(*v++); 2165 x[i] = (1-omega)*x[i] + omega*sum/d; 2166 } 2167 } 2168 } 2169 2170 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2171 if (bb != xx) { 2172 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 2173 } 2174 PetscFunctionReturn(0); 2175 } 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "MatCreateSeqSBAIJWithArrays" 2179 /*@ 2180 MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements 2181 (upper triangular entries in CSR format) provided by the user. 2182 2183 Collective on MPI_Comm 2184 2185 Input Parameters: 2186 + comm - must be an MPI communicator of size 1 2187 . bs - size of block 2188 . m - number of rows 2189 . n - number of columns 2190 . i - row indices 2191 . j - column indices 2192 - a - matrix values 2193 2194 Output Parameter: 2195 . mat - the matrix 2196 2197 Level: intermediate 2198 2199 Notes: 2200 The i, j, and a arrays are not copied by this routine, the user must free these arrays 2201 once the matrix is destroyed 2202 2203 You cannot set new nonzero locations into this matrix, that will generate an error. 2204 2205 The i and j indices are 0 based 2206 2207 .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ() 2208 2209 @*/ 2210 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat) 2211 { 2212 PetscErrorCode ierr; 2213 PetscInt ii; 2214 Mat_SeqSBAIJ *sbaij; 2215 2216 PetscFunctionBegin; 2217 if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs); 2218 if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 2219 2220 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 2221 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 2222 ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr); 2223 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 2224 sbaij = (Mat_SeqSBAIJ*)(*mat)->data; 2225 ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr); 2226 2227 sbaij->i = i; 2228 sbaij->j = j; 2229 sbaij->a = a; 2230 sbaij->singlemalloc = PETSC_FALSE; 2231 sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2232 sbaij->free_a = PETSC_FALSE; 2233 sbaij->free_ij = PETSC_FALSE; 2234 2235 for (ii=0; ii<m; ii++) { 2236 sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii]; 2237 #if defined(PETSC_USE_DEBUG) 2238 if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]); 2239 #endif 2240 } 2241 #if defined(PETSC_USE_DEBUG) 2242 for (ii=0; ii<sbaij->i[m]; ii++) { 2243 if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]); 2244 if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]); 2245 } 2246 #endif 2247 2248 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2249 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2250 PetscFunctionReturn(0); 2251 } 2252 2253 2254 2255 2256 2257