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 MatSetOption_SeqSBAIJ, 1175 MatZeroEntries_SeqSBAIJ, 1176 /*24*/ 0, 1177 0, 1178 0, 1179 0, 1180 0, 1181 /*29*/ MatSetUpPreallocation_SeqSBAIJ, 1182 0, 1183 0, 1184 MatGetArray_SeqSBAIJ, 1185 MatRestoreArray_SeqSBAIJ, 1186 /*34*/ MatDuplicate_SeqSBAIJ, 1187 0, 1188 0, 1189 0, 1190 MatICCFactor_SeqSBAIJ, 1191 /*39*/ MatAXPY_SeqSBAIJ, 1192 MatGetSubMatrices_SeqSBAIJ, 1193 MatIncreaseOverlap_SeqSBAIJ, 1194 MatGetValues_SeqSBAIJ, 1195 MatCopy_SeqSBAIJ, 1196 /*44*/ 0, 1197 MatScale_SeqSBAIJ, 1198 0, 1199 0, 1200 0, 1201 /*49*/ 0, 1202 MatGetRowIJ_SeqSBAIJ, 1203 MatRestoreRowIJ_SeqSBAIJ, 1204 0, 1205 0, 1206 /*54*/ 0, 1207 0, 1208 0, 1209 0, 1210 MatSetValuesBlocked_SeqSBAIJ, 1211 /*59*/ MatGetSubMatrix_SeqSBAIJ, 1212 0, 1213 0, 1214 0, 1215 0, 1216 /*64*/ 0, 1217 0, 1218 0, 1219 0, 1220 0, 1221 /*69*/ MatGetRowMaxAbs_SeqSBAIJ, 1222 0, 1223 0, 1224 0, 1225 0, 1226 /*74*/ 0, 1227 0, 1228 0, 1229 0, 1230 0, 1231 /*79*/ 0, 1232 0, 1233 0, 1234 #if !defined(PETSC_USE_COMPLEX) 1235 MatGetInertia_SeqSBAIJ, 1236 #else 1237 0, 1238 #endif 1239 MatLoad_SeqSBAIJ, 1240 /*84*/ MatIsSymmetric_SeqSBAIJ, 1241 MatIsHermitian_SeqSBAIJ, 1242 MatIsStructurallySymmetric_SeqSBAIJ, 1243 0, 1244 0, 1245 /*89*/ 0, 1246 0, 1247 0, 1248 0, 1249 0, 1250 /*94*/ 0, 1251 0, 1252 0, 1253 0, 1254 0, 1255 /*99*/ 0, 1256 0, 1257 0, 1258 0, 1259 0, 1260 /*104*/0, 1261 MatRealPart_SeqSBAIJ, 1262 MatImaginaryPart_SeqSBAIJ, 1263 MatGetRowUpperTriangular_SeqSBAIJ, 1264 MatRestoreRowUpperTriangular_SeqSBAIJ, 1265 /*109*/0, 1266 0, 1267 0, 1268 0, 1269 MatMissingDiagonal_SeqSBAIJ 1270 }; 1271 1272 EXTERN_C_BEGIN 1273 #undef __FUNCT__ 1274 #define __FUNCT__ "MatStoreValues_SeqSBAIJ" 1275 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqSBAIJ(Mat mat) 1276 { 1277 Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1278 PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2; 1279 PetscErrorCode ierr; 1280 1281 PetscFunctionBegin; 1282 if (aij->nonew != 1) { 1283 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 1284 } 1285 1286 /* allocate space for values if not already there */ 1287 if (!aij->saved_values) { 1288 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 1289 } 1290 1291 /* copy values over */ 1292 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 1293 PetscFunctionReturn(0); 1294 } 1295 EXTERN_C_END 1296 1297 EXTERN_C_BEGIN 1298 #undef __FUNCT__ 1299 #define __FUNCT__ "MatRetrieveValues_SeqSBAIJ" 1300 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqSBAIJ(Mat mat) 1301 { 1302 Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data; 1303 PetscErrorCode ierr; 1304 PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2; 1305 1306 PetscFunctionBegin; 1307 if (aij->nonew != 1) { 1308 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 1309 } 1310 if (!aij->saved_values) { 1311 SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 1312 } 1313 1314 /* copy values over */ 1315 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 1316 PetscFunctionReturn(0); 1317 } 1318 EXTERN_C_END 1319 1320 EXTERN_C_BEGIN 1321 #undef __FUNCT__ 1322 #define __FUNCT__ "MatSeqSBAIJSetPreallocation_SeqSBAIJ" 1323 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz) 1324 { 1325 Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data; 1326 PetscErrorCode ierr; 1327 PetscInt i,mbs,bs2, newbs = PetscAbs(bs); 1328 PetscTruth skipallocation = PETSC_FALSE,flg = PETSC_FALSE; 1329 1330 PetscFunctionBegin; 1331 B->preallocated = PETSC_TRUE; 1332 if (bs < 0) { 1333 ierr = PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");CHKERRQ(ierr); 1334 ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);CHKERRQ(ierr); 1335 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1336 bs = PetscAbs(bs); 1337 } 1338 if (nnz && newbs != bs) { 1339 SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz"); 1340 } 1341 bs = newbs; 1342 1343 ierr = PetscMapSetBlockSize(B->rmap,bs);CHKERRQ(ierr); 1344 ierr = PetscMapSetBlockSize(B->cmap,bs);CHKERRQ(ierr); 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 = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);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 = PETSC_FALSE; 1486 PetscInt bs = B->rmap->bs; 1487 1488 PetscFunctionBegin; 1489 ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);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 #if defined(PETSC_HAVE_PASTIX) 1601 extern PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat,MatFactorType,Mat*); 1602 #endif 1603 EXTERN_C_END 1604 1605 /*MC 1606 MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 1607 based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 1608 1609 Options Database Keys: 1610 . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions() 1611 1612 Level: beginner 1613 1614 .seealso: MatCreateSeqSBAIJ 1615 M*/ 1616 1617 EXTERN_C_BEGIN 1618 #undef __FUNCT__ 1619 #define __FUNCT__ "MatCreate_SeqSBAIJ" 1620 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B) 1621 { 1622 Mat_SeqSBAIJ *b; 1623 PetscErrorCode ierr; 1624 PetscMPIInt size; 1625 1626 PetscFunctionBegin; 1627 ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 1628 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1"); 1629 1630 ierr = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr); 1631 B->data = (void*)b; 1632 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1633 B->ops->destroy = MatDestroy_SeqSBAIJ; 1634 B->ops->view = MatView_SeqSBAIJ; 1635 B->mapping = 0; 1636 b->row = 0; 1637 b->icol = 0; 1638 b->reallocs = 0; 1639 b->saved_values = 0; 1640 1641 1642 b->roworiented = PETSC_TRUE; 1643 b->nonew = 0; 1644 b->diag = 0; 1645 b->solve_work = 0; 1646 b->mult_work = 0; 1647 B->spptr = 0; 1648 b->keepzeroedrows = PETSC_FALSE; 1649 b->xtoy = 0; 1650 b->XtoY = 0; 1651 1652 b->inew = 0; 1653 b->jnew = 0; 1654 b->anew = 0; 1655 b->a2anew = 0; 1656 b->permute = PETSC_FALSE; 1657 1658 b->ignore_ltriangular = PETSC_FALSE; 1659 ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&b->ignore_ltriangular,PETSC_NULL);CHKERRQ(ierr); 1660 1661 b->getrow_utriangular = PETSC_FALSE; 1662 ierr = PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&b->getrow_utriangular,PETSC_NULL);CHKERRQ(ierr); 1663 1664 #if defined(PETSC_HAVE_PASTIX) 1665 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_pastix_C", 1666 "MatGetFactor_seqsbaij_pastix", 1667 MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr); 1668 #endif 1669 #if defined(PETSC_HAVE_SPOOLES) 1670 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C", 1671 "MatGetFactor_seqsbaij_spooles", 1672 MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr); 1673 #endif 1674 #if defined(PETSC_HAVE_MUMPS) 1675 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C", 1676 "MatGetFactor_seqsbaij_mumps", 1677 MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr); 1678 #endif 1679 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C", 1680 "MatGetFactorAvailable_seqsbaij_petsc", 1681 MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr); 1682 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C", 1683 "MatGetFactor_seqsbaij_petsc", 1684 MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr); 1685 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 1686 "MatStoreValues_SeqSBAIJ", 1687 MatStoreValues_SeqSBAIJ);CHKERRQ(ierr); 1688 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 1689 "MatRetrieveValues_SeqSBAIJ", 1690 (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr); 1691 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C", 1692 "MatSeqSBAIJSetColumnIndices_SeqSBAIJ", 1693 MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr); 1694 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C", 1695 "MatConvert_SeqSBAIJ_SeqAIJ", 1696 MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr); 1697 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C", 1698 "MatConvert_SeqSBAIJ_SeqBAIJ", 1699 MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr); 1700 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C", 1701 "MatSeqSBAIJSetPreallocation_SeqSBAIJ", 1702 MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr); 1703 1704 B->symmetric = PETSC_TRUE; 1705 B->structurally_symmetric = PETSC_TRUE; 1706 B->symmetric_set = PETSC_TRUE; 1707 B->structurally_symmetric_set = PETSC_TRUE; 1708 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr); 1709 PetscFunctionReturn(0); 1710 } 1711 EXTERN_C_END 1712 1713 #undef __FUNCT__ 1714 #define __FUNCT__ "MatSeqSBAIJSetPreallocation" 1715 /*@C 1716 MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 1717 compressed row) format. For good matrix assembly performance the 1718 user should preallocate the matrix storage by setting the parameter nz 1719 (or the array nnz). By setting these parameters accurately, performance 1720 during matrix assembly can be increased by more than a factor of 50. 1721 1722 Collective on Mat 1723 1724 Input Parameters: 1725 + A - the symmetric matrix 1726 . bs - size of block 1727 . nz - number of block nonzeros per block row (same for all rows) 1728 - nnz - array containing the number of block nonzeros in the upper triangular plus 1729 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1730 1731 Options Database Keys: 1732 . -mat_no_unroll - uses code that does not unroll the loops in the 1733 block calculations (much slower) 1734 . -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1735 1736 Level: intermediate 1737 1738 Notes: 1739 Specify the preallocated storage with either nz or nnz (not both). 1740 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1741 allocation. For additional details, see the users manual chapter on 1742 matrices. 1743 1744 You can call MatGetInfo() to get information on how effective the preallocation was; 1745 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 1746 You can also run with the option -info and look for messages with the string 1747 malloc in them to see if additional memory allocation was needed. 1748 1749 If the nnz parameter is given then the nz parameter is ignored 1750 1751 1752 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1753 @*/ 1754 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[]) 1755 { 1756 PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]); 1757 1758 PetscFunctionBegin; 1759 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 1760 if (f) { 1761 ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr); 1762 } 1763 PetscFunctionReturn(0); 1764 } 1765 1766 #undef __FUNCT__ 1767 #define __FUNCT__ "MatCreateSeqSBAIJ" 1768 /*@C 1769 MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block 1770 compressed row) format. For good matrix assembly performance the 1771 user should preallocate the matrix storage by setting the parameter nz 1772 (or the array nnz). By setting these parameters accurately, performance 1773 during matrix assembly can be increased by more than a factor of 50. 1774 1775 Collective on MPI_Comm 1776 1777 Input Parameters: 1778 + comm - MPI communicator, set to PETSC_COMM_SELF 1779 . bs - size of block 1780 . m - number of rows, or number of columns 1781 . nz - number of block nonzeros per block row (same for all rows) 1782 - nnz - array containing the number of block nonzeros in the upper triangular plus 1783 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1784 1785 Output Parameter: 1786 . A - the symmetric matrix 1787 1788 Options Database Keys: 1789 . -mat_no_unroll - uses code that does not unroll the loops in the 1790 block calculations (much slower) 1791 . -mat_block_size - size of the blocks to use 1792 1793 Level: intermediate 1794 1795 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 1796 MatXXXXSetPreallocation() paradgm instead of this routine directly. 1797 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 1798 1799 Notes: 1800 The number of rows and columns must be divisible by blocksize. 1801 This matrix type does not support complex Hermitian operation. 1802 1803 Specify the preallocated storage with either nz or nnz (not both). 1804 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1805 allocation. For additional details, see the users manual chapter on 1806 matrices. 1807 1808 If the nnz parameter is given then the nz parameter is ignored 1809 1810 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1811 @*/ 1812 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 1813 { 1814 PetscErrorCode ierr; 1815 1816 PetscFunctionBegin; 1817 ierr = MatCreate(comm,A);CHKERRQ(ierr); 1818 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 1819 ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr); 1820 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr); 1821 PetscFunctionReturn(0); 1822 } 1823 1824 #undef __FUNCT__ 1825 #define __FUNCT__ "MatDuplicate_SeqSBAIJ" 1826 PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 1827 { 1828 Mat C; 1829 Mat_SeqSBAIJ *c,*a = (Mat_SeqSBAIJ*)A->data; 1830 PetscErrorCode ierr; 1831 PetscInt i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2; 1832 1833 PetscFunctionBegin; 1834 if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix"); 1835 1836 *B = 0; 1837 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1838 ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr); 1839 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1840 ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1841 c = (Mat_SeqSBAIJ*)C->data; 1842 1843 C->preallocated = PETSC_TRUE; 1844 C->factor = A->factor; 1845 c->row = 0; 1846 c->icol = 0; 1847 c->saved_values = 0; 1848 c->keepzeroedrows = a->keepzeroedrows; 1849 C->assembled = PETSC_TRUE; 1850 1851 ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr); 1852 ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr); 1853 c->bs2 = a->bs2; 1854 c->mbs = a->mbs; 1855 c->nbs = a->nbs; 1856 1857 ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr); 1858 for (i=0; i<mbs; i++) { 1859 c->imax[i] = a->imax[i]; 1860 c->ilen[i] = a->ilen[i]; 1861 } 1862 1863 /* allocate the matrix space */ 1864 ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr); 1865 c->singlemalloc = PETSC_TRUE; 1866 ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1867 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr); 1868 if (mbs > 0) { 1869 ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr); 1870 if (cpvalues == MAT_COPY_VALUES) { 1871 ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1872 } else { 1873 ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1874 } 1875 } 1876 1877 c->roworiented = a->roworiented; 1878 c->nonew = a->nonew; 1879 1880 if (a->diag) { 1881 ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr); 1882 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1883 for (i=0; i<mbs; i++) { 1884 c->diag[i] = a->diag[i]; 1885 } 1886 } else c->diag = 0; 1887 c->nz = a->nz; 1888 c->maxnz = a->maxnz; 1889 c->solve_work = 0; 1890 c->mult_work = 0; 1891 c->free_a = PETSC_TRUE; 1892 c->free_ij = PETSC_TRUE; 1893 *B = C; 1894 ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 1895 PetscFunctionReturn(0); 1896 } 1897 1898 #undef __FUNCT__ 1899 #define __FUNCT__ "MatLoad_SeqSBAIJ" 1900 PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A) 1901 { 1902 Mat_SeqSBAIJ *a; 1903 Mat B; 1904 PetscErrorCode ierr; 1905 int fd; 1906 PetscMPIInt size; 1907 PetscInt i,nz,header[4],*rowlengths=0,M,N,bs=1; 1908 PetscInt *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount; 1909 PetscInt kmax,jcount,block,idx,point,nzcountb,extra_rows; 1910 PetscInt *masked,nmask,tmp,bs2,ishift; 1911 PetscScalar *aa; 1912 MPI_Comm comm = ((PetscObject)viewer)->comm; 1913 1914 PetscFunctionBegin; 1915 ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr); 1916 bs2 = bs*bs; 1917 1918 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1919 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor"); 1920 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1921 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 1922 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object"); 1923 M = header[1]; N = header[2]; nz = header[3]; 1924 1925 if (header[3] < 0) { 1926 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ"); 1927 } 1928 1929 if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices"); 1930 1931 /* 1932 This code adds extra rows to make sure the number of rows is 1933 divisible by the blocksize 1934 */ 1935 mbs = M/bs; 1936 extra_rows = bs - M + bs*(mbs); 1937 if (extra_rows == bs) extra_rows = 0; 1938 else mbs++; 1939 if (extra_rows) { 1940 ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr); 1941 } 1942 1943 /* read in row lengths */ 1944 ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 1945 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 1946 for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1; 1947 1948 /* read in column indices */ 1949 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr); 1950 ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr); 1951 for (i=0; i<extra_rows; i++) jj[nz+i] = M+i; 1952 1953 /* loop over row lengths determining block row lengths */ 1954 ierr = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr); 1955 ierr = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1956 ierr = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr); 1957 ierr = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1958 masked = mask + mbs; 1959 rowcount = 0; nzcount = 0; 1960 for (i=0; i<mbs; i++) { 1961 nmask = 0; 1962 for (j=0; j<bs; j++) { 1963 kmax = rowlengths[rowcount]; 1964 for (k=0; k<kmax; k++) { 1965 tmp = jj[nzcount++]/bs; /* block col. index */ 1966 if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;} 1967 } 1968 rowcount++; 1969 } 1970 s_browlengths[i] += nmask; 1971 1972 /* zero out the mask elements we set */ 1973 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 1974 } 1975 1976 /* create our matrix */ 1977 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 1978 ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr); 1979 ierr = MatSetType(B,type);CHKERRQ(ierr); 1980 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr); 1981 a = (Mat_SeqSBAIJ*)B->data; 1982 1983 /* set matrix "i" values */ 1984 a->i[0] = 0; 1985 for (i=1; i<= mbs; i++) { 1986 a->i[i] = a->i[i-1] + s_browlengths[i-1]; 1987 a->ilen[i-1] = s_browlengths[i-1]; 1988 } 1989 a->nz = a->i[mbs]; 1990 1991 /* read in nonzero values */ 1992 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr); 1993 ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr); 1994 for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0; 1995 1996 /* set "a" and "j" values into matrix */ 1997 nzcount = 0; jcount = 0; 1998 for (i=0; i<mbs; i++) { 1999 nzcountb = nzcount; 2000 nmask = 0; 2001 for (j=0; j<bs; j++) { 2002 kmax = rowlengths[i*bs+j]; 2003 for (k=0; k<kmax; k++) { 2004 tmp = jj[nzcount++]/bs; /* block col. index */ 2005 if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;} 2006 } 2007 } 2008 /* sort the masked values */ 2009 ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr); 2010 2011 /* set "j" values into matrix */ 2012 maskcount = 1; 2013 for (j=0; j<nmask; j++) { 2014 a->j[jcount++] = masked[j]; 2015 mask[masked[j]] = maskcount++; 2016 } 2017 2018 /* set "a" values into matrix */ 2019 ishift = bs2*a->i[i]; 2020 for (j=0; j<bs; j++) { 2021 kmax = rowlengths[i*bs+j]; 2022 for (k=0; k<kmax; k++) { 2023 tmp = jj[nzcountb]/bs ; /* block col. index */ 2024 if (tmp >= i){ 2025 block = mask[tmp] - 1; 2026 point = jj[nzcountb] - bs*tmp; 2027 idx = ishift + bs2*block + j + bs*point; 2028 a->a[idx] = aa[nzcountb]; 2029 } 2030 nzcountb++; 2031 } 2032 } 2033 /* zero out the mask elements we set */ 2034 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 2035 } 2036 if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix"); 2037 2038 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 2039 ierr = PetscFree(s_browlengths);CHKERRQ(ierr); 2040 ierr = PetscFree(aa);CHKERRQ(ierr); 2041 ierr = PetscFree(jj);CHKERRQ(ierr); 2042 ierr = PetscFree(mask);CHKERRQ(ierr); 2043 2044 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2045 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2046 ierr = MatView_Private(B);CHKERRQ(ierr); 2047 *A = B; 2048 PetscFunctionReturn(0); 2049 } 2050 2051 #undef __FUNCT__ 2052 #define __FUNCT__ "MatRelax_SeqSBAIJ" 2053 PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 2054 { 2055 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 2056 MatScalar *aa=a->a,*v,*v1; 2057 PetscScalar *x,*b,*t,sum,d; 2058 PetscErrorCode ierr; 2059 PetscInt m=a->mbs,bs=A->rmap->bs,*ai=a->i,*aj=a->j; 2060 PetscInt nz,nz1,*vj,*vj1,i; 2061 2062 PetscFunctionBegin; 2063 if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat"); 2064 2065 its = its*lits; 2066 if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 2067 2068 if (bs > 1) 2069 SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented"); 2070 2071 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 2072 if (xx != bb) { 2073 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 2074 } else { 2075 b = x; 2076 } 2077 2078 if (!a->relax_work) { 2079 ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr); 2080 } 2081 t = a->relax_work; 2082 2083 if (flag & SOR_ZERO_INITIAL_GUESS) { 2084 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2085 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2086 2087 for (i=0; i<m; i++){ 2088 d = *(aa + ai[i]); /* diag[i] */ 2089 v = aa + ai[i] + 1; 2090 vj = aj + ai[i] + 1; 2091 nz = ai[i+1] - ai[i] - 1; 2092 ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr); 2093 x[i] = omega*t[i]/d; 2094 while (nz--) t[*vj++] -= x[i]*(*v++); /* update rhs */ 2095 } 2096 } 2097 2098 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2099 if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){ 2100 t = b; 2101 } 2102 2103 for (i=m-1; i>=0; i--){ 2104 d = *(aa + ai[i]); 2105 v = aa + ai[i] + 1; 2106 vj = aj + ai[i] + 1; 2107 nz = ai[i+1] - ai[i] - 1; 2108 ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr); 2109 sum = t[i]; 2110 while (nz--) sum -= x[*vj++]*(*v++); 2111 x[i] = (1-omega)*x[i] + omega*sum/d; 2112 } 2113 t = a->relax_work; 2114 } 2115 its--; 2116 } 2117 2118 while (its--) { 2119 /* 2120 forward sweep: 2121 for i=0,...,m-1: 2122 sum[i] = (b[i] - U(i,:)x )/d[i]; 2123 x[i] = (1-omega)x[i] + omega*sum[i]; 2124 b = b - x[i]*U^T(i,:); 2125 2126 */ 2127 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2128 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2129 2130 for (i=0; i<m; i++){ 2131 d = *(aa + ai[i]); /* diag[i] */ 2132 v = aa + ai[i] + 1; v1=v; 2133 vj = aj + ai[i] + 1; vj1=vj; 2134 nz = ai[i+1] - ai[i] - 1; nz1=nz; 2135 sum = t[i]; 2136 ierr = PetscLogFlops(4.0*nz-2);CHKERRQ(ierr); 2137 while (nz1--) sum -= (*v1++)*x[*vj1++]; 2138 x[i] = (1-omega)*x[i] + omega*sum/d; 2139 while (nz--) t[*vj++] -= x[i]*(*v++); 2140 } 2141 } 2142 2143 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2144 /* 2145 backward sweep: 2146 b = b - x[i]*U^T(i,:), i=0,...,n-2 2147 for i=m-1,...,0: 2148 sum[i] = (b[i] - U(i,:)x )/d[i]; 2149 x[i] = (1-omega)x[i] + omega*sum[i]; 2150 */ 2151 /* if there was a forward sweep done above then I thing the next two for loops are not needed */ 2152 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2153 2154 for (i=0; i<m-1; i++){ /* update rhs */ 2155 v = aa + ai[i] + 1; 2156 vj = aj + ai[i] + 1; 2157 nz = ai[i+1] - ai[i] - 1; 2158 ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr); 2159 while (nz--) t[*vj++] -= x[i]*(*v++); 2160 } 2161 for (i=m-1; i>=0; i--){ 2162 d = *(aa + ai[i]); 2163 v = aa + ai[i] + 1; 2164 vj = aj + ai[i] + 1; 2165 nz = ai[i+1] - ai[i] - 1; 2166 ierr = PetscLogFlops(2.0*nz-1);CHKERRQ(ierr); 2167 sum = t[i]; 2168 while (nz--) sum -= x[*vj++]*(*v++); 2169 x[i] = (1-omega)*x[i] + omega*sum/d; 2170 } 2171 } 2172 } 2173 2174 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2175 if (bb != xx) { 2176 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 2177 } 2178 PetscFunctionReturn(0); 2179 } 2180 2181 #undef __FUNCT__ 2182 #define __FUNCT__ "MatCreateSeqSBAIJWithArrays" 2183 /*@ 2184 MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements 2185 (upper triangular entries in CSR format) provided by the user. 2186 2187 Collective on MPI_Comm 2188 2189 Input Parameters: 2190 + comm - must be an MPI communicator of size 1 2191 . bs - size of block 2192 . m - number of rows 2193 . n - number of columns 2194 . i - row indices 2195 . j - column indices 2196 - a - matrix values 2197 2198 Output Parameter: 2199 . mat - the matrix 2200 2201 Level: intermediate 2202 2203 Notes: 2204 The i, j, and a arrays are not copied by this routine, the user must free these arrays 2205 once the matrix is destroyed 2206 2207 You cannot set new nonzero locations into this matrix, that will generate an error. 2208 2209 The i and j indices are 0 based 2210 2211 .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ() 2212 2213 @*/ 2214 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat) 2215 { 2216 PetscErrorCode ierr; 2217 PetscInt ii; 2218 Mat_SeqSBAIJ *sbaij; 2219 2220 PetscFunctionBegin; 2221 if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs); 2222 if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 2223 2224 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 2225 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 2226 ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr); 2227 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 2228 sbaij = (Mat_SeqSBAIJ*)(*mat)->data; 2229 ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr); 2230 2231 sbaij->i = i; 2232 sbaij->j = j; 2233 sbaij->a = a; 2234 sbaij->singlemalloc = PETSC_FALSE; 2235 sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2236 sbaij->free_a = PETSC_FALSE; 2237 sbaij->free_ij = PETSC_FALSE; 2238 2239 for (ii=0; ii<m; ii++) { 2240 sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii]; 2241 #if defined(PETSC_USE_DEBUG) 2242 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]); 2243 #endif 2244 } 2245 #if defined(PETSC_USE_DEBUG) 2246 for (ii=0; ii<sbaij->i[m]; ii++) { 2247 if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]); 2248 if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]); 2249 } 2250 #endif 2251 2252 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2253 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2254 PetscFunctionReturn(0); 2255 } 2256 2257 2258 2259 2260 2261