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 ierr = PetscMapSetBlockSize(B->rmap,bs);CHKERRQ(ierr); 1345 ierr = PetscMapSetBlockSize(B->cmap,bs);CHKERRQ(ierr); 1346 ierr = PetscMapSetUp(B->rmap);CHKERRQ(ierr); 1347 ierr = PetscMapSetUp(B->cmap);CHKERRQ(ierr); 1348 1349 mbs = B->rmap->N/bs; 1350 bs2 = bs*bs; 1351 1352 if (mbs*bs != B->rmap->N) { 1353 SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize"); 1354 } 1355 1356 if (nz == MAT_SKIP_ALLOCATION) { 1357 skipallocation = PETSC_TRUE; 1358 nz = 0; 1359 } 1360 1361 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3; 1362 if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz); 1363 if (nnz) { 1364 for (i=0; i<mbs; i++) { 1365 if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]); 1366 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); 1367 } 1368 } 1369 1370 B->ops->mult = MatMult_SeqSBAIJ_N; 1371 B->ops->multadd = MatMultAdd_SeqSBAIJ_N; 1372 B->ops->multtranspose = MatMult_SeqSBAIJ_N; 1373 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N; 1374 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr); 1375 if (!flg) { 1376 switch (bs) { 1377 case 1: 1378 B->ops->mult = MatMult_SeqSBAIJ_1; 1379 B->ops->multadd = MatMultAdd_SeqSBAIJ_1; 1380 B->ops->multtranspose = MatMult_SeqSBAIJ_1; 1381 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1; 1382 break; 1383 case 2: 1384 B->ops->mult = MatMult_SeqSBAIJ_2; 1385 B->ops->multadd = MatMultAdd_SeqSBAIJ_2; 1386 B->ops->multtranspose = MatMult_SeqSBAIJ_2; 1387 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2; 1388 break; 1389 case 3: 1390 B->ops->mult = MatMult_SeqSBAIJ_3; 1391 B->ops->multadd = MatMultAdd_SeqSBAIJ_3; 1392 B->ops->multtranspose = MatMult_SeqSBAIJ_3; 1393 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3; 1394 break; 1395 case 4: 1396 B->ops->mult = MatMult_SeqSBAIJ_4; 1397 B->ops->multadd = MatMultAdd_SeqSBAIJ_4; 1398 B->ops->multtranspose = MatMult_SeqSBAIJ_4; 1399 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4; 1400 break; 1401 case 5: 1402 B->ops->mult = MatMult_SeqSBAIJ_5; 1403 B->ops->multadd = MatMultAdd_SeqSBAIJ_5; 1404 B->ops->multtranspose = MatMult_SeqSBAIJ_5; 1405 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5; 1406 break; 1407 case 6: 1408 B->ops->mult = MatMult_SeqSBAIJ_6; 1409 B->ops->multadd = MatMultAdd_SeqSBAIJ_6; 1410 B->ops->multtranspose = MatMult_SeqSBAIJ_6; 1411 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6; 1412 break; 1413 case 7: 1414 B->ops->mult = MatMult_SeqSBAIJ_7; 1415 B->ops->multadd = MatMultAdd_SeqSBAIJ_7; 1416 B->ops->multtranspose = MatMult_SeqSBAIJ_7; 1417 B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7; 1418 break; 1419 } 1420 } 1421 1422 b->mbs = mbs; 1423 b->nbs = mbs; 1424 if (!skipallocation) { 1425 if (!b->imax) { 1426 ierr = PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);CHKERRQ(ierr); 1427 ierr = PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));CHKERRQ(ierr); 1428 } 1429 if (!nnz) { 1430 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 1431 else if (nz <= 0) nz = 1; 1432 for (i=0; i<mbs; i++) { 1433 b->imax[i] = nz; 1434 } 1435 nz = nz*mbs; /* total nz */ 1436 } else { 1437 nz = 0; 1438 for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 1439 } 1440 /* b->ilen will count nonzeros in each block row so far. */ 1441 for (i=0; i<mbs; i++) { b->ilen[i] = 0;} 1442 /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */ 1443 1444 /* allocate the matrix space */ 1445 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 1446 ierr = PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);CHKERRQ(ierr); 1447 ierr = PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 1448 ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr); 1449 ierr = PetscMemzero(b->j,nz*sizeof(PetscInt));CHKERRQ(ierr); 1450 b->singlemalloc = PETSC_TRUE; 1451 1452 /* pointer to beginning of each row */ 1453 b->i[0] = 0; 1454 for (i=1; i<mbs+1; i++) { 1455 b->i[i] = b->i[i-1] + b->imax[i-1]; 1456 } 1457 b->free_a = PETSC_TRUE; 1458 b->free_ij = PETSC_TRUE; 1459 } else { 1460 b->free_a = PETSC_FALSE; 1461 b->free_ij = PETSC_FALSE; 1462 } 1463 1464 B->rmap->bs = bs; 1465 b->bs2 = bs2; 1466 b->nz = 0; 1467 b->maxnz = nz*bs2; 1468 1469 b->inew = 0; 1470 b->jnew = 0; 1471 b->anew = 0; 1472 b->a2anew = 0; 1473 b->permute = PETSC_FALSE; 1474 PetscFunctionReturn(0); 1475 } 1476 EXTERN_C_END 1477 1478 #undef __FUNCT__ 1479 #define __FUNCT__ "MatSeqBAIJSetNumericFactorization" 1480 /* 1481 This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization 1482 */ 1483 PetscErrorCode MatSeqSBAIJSetNumericFactorization(Mat B,PetscTruth natural) 1484 { 1485 PetscErrorCode ierr; 1486 PetscTruth flg; 1487 PetscInt bs = B->rmap->bs; 1488 1489 PetscFunctionBegin; 1490 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_no_unroll",&flg);CHKERRQ(ierr); 1491 if (flg) bs = 8; 1492 1493 if (!natural) { 1494 switch (bs) { 1495 case 1: 1496 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1; 1497 break; 1498 case 2: 1499 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2; 1500 break; 1501 case 3: 1502 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3; 1503 break; 1504 case 4: 1505 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4; 1506 break; 1507 case 5: 1508 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5; 1509 break; 1510 case 6: 1511 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6; 1512 break; 1513 case 7: 1514 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7; 1515 break; 1516 default: 1517 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N; 1518 break; 1519 } 1520 } else { 1521 switch (bs) { 1522 case 1: 1523 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering; 1524 break; 1525 case 2: 1526 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering; 1527 break; 1528 case 3: 1529 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering; 1530 break; 1531 case 4: 1532 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering; 1533 break; 1534 case 5: 1535 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering; 1536 break; 1537 case 6: 1538 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering; 1539 break; 1540 case 7: 1541 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering; 1542 break; 1543 default: 1544 B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering; 1545 break; 1546 } 1547 } 1548 PetscFunctionReturn(0); 1549 } 1550 1551 EXTERN_C_BEGIN 1552 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*); 1553 EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*); 1554 EXTERN_C_END 1555 1556 1557 EXTERN_C_BEGIN 1558 #undef __FUNCT__ 1559 #define __FUNCT__ "MatGetFactor_seqsbaij_petsc" 1560 PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B) 1561 { 1562 PetscInt n = A->rmap->n; 1563 PetscErrorCode ierr; 1564 1565 PetscFunctionBegin; 1566 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 1567 ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr); 1568 if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 1569 ierr = MatSetType(*B,MATSEQSBAIJ);CHKERRQ(ierr); 1570 ierr = MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);CHKERRQ(ierr); 1571 (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ; 1572 (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ; 1573 } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported"); 1574 (*B)->factor = ftype; 1575 PetscFunctionReturn(0); 1576 } 1577 EXTERN_C_END 1578 1579 EXTERN_C_BEGIN 1580 #undef __FUNCT__ 1581 #define __FUNCT__ "MatGetFactorAvailable_seqsbaij_petsc" 1582 PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg) 1583 { 1584 PetscFunctionBegin; 1585 if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) { 1586 *flg = PETSC_TRUE; 1587 } else { 1588 *flg = PETSC_FALSE; 1589 } 1590 PetscFunctionReturn(0); 1591 } 1592 EXTERN_C_END 1593 1594 EXTERN_C_BEGIN 1595 #if defined(PETSC_HAVE_MUMPS) 1596 extern PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat,MatFactorType,Mat*); 1597 #endif 1598 #if defined(PETSC_HAVE_SPOOLES) 1599 extern PetscErrorCode MatGetFactor_seqsbaij_spooles(Mat,MatFactorType,Mat*); 1600 #endif 1601 #if defined(PETSC_HAVE_PASTIX) 1602 extern PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat,MatFactorType,Mat*); 1603 #endif 1604 EXTERN_C_END 1605 1606 /*MC 1607 MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices, 1608 based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored. 1609 1610 Options Database Keys: 1611 . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions() 1612 1613 Level: beginner 1614 1615 .seealso: MatCreateSeqSBAIJ 1616 M*/ 1617 1618 EXTERN_C_BEGIN 1619 #undef __FUNCT__ 1620 #define __FUNCT__ "MatCreate_SeqSBAIJ" 1621 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqSBAIJ(Mat B) 1622 { 1623 Mat_SeqSBAIJ *b; 1624 PetscErrorCode ierr; 1625 PetscMPIInt size; 1626 PetscTruth flg; 1627 1628 PetscFunctionBegin; 1629 ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 1630 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1"); 1631 1632 ierr = PetscNewLog(B,Mat_SeqSBAIJ,&b);CHKERRQ(ierr); 1633 B->data = (void*)b; 1634 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1635 B->ops->destroy = MatDestroy_SeqSBAIJ; 1636 B->ops->view = MatView_SeqSBAIJ; 1637 B->mapping = 0; 1638 b->row = 0; 1639 b->icol = 0; 1640 b->reallocs = 0; 1641 b->saved_values = 0; 1642 1643 1644 b->roworiented = PETSC_TRUE; 1645 b->nonew = 0; 1646 b->diag = 0; 1647 b->solve_work = 0; 1648 b->mult_work = 0; 1649 B->spptr = 0; 1650 b->keepzeroedrows = PETSC_FALSE; 1651 b->xtoy = 0; 1652 b->XtoY = 0; 1653 1654 b->inew = 0; 1655 b->jnew = 0; 1656 b->anew = 0; 1657 b->a2anew = 0; 1658 b->permute = PETSC_FALSE; 1659 1660 b->ignore_ltriangular = PETSC_FALSE; 1661 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&flg);CHKERRQ(ierr); 1662 if (flg) b->ignore_ltriangular = PETSC_TRUE; 1663 1664 b->getrow_utriangular = PETSC_FALSE; 1665 ierr = PetscOptionsHasName(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&flg);CHKERRQ(ierr); 1666 if (flg) b->getrow_utriangular = PETSC_TRUE; 1667 1668 #if defined(PETSC_HAVE_PASTIX) 1669 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_pastix_C", 1670 "MatGetFactor_seqsbaij_pastix", 1671 MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr); 1672 #endif 1673 #if defined(PETSC_HAVE_SPOOLES) 1674 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_spooles_C", 1675 "MatGetFactor_seqsbaij_spooles", 1676 MatGetFactor_seqsbaij_spooles);CHKERRQ(ierr); 1677 #endif 1678 #if defined(PETSC_HAVE_MUMPS) 1679 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_mumps_C", 1680 "MatGetFactor_seqsbaij_mumps", 1681 MatGetFactor_seqsbaij_mumps);CHKERRQ(ierr); 1682 #endif 1683 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_seqsbaij_petsc_C", 1684 "MatGetFactorAvailable_seqsbaij_petsc", 1685 MatGetFactorAvailable_seqsbaij_petsc);CHKERRQ(ierr); 1686 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_seqsbaij_petsc_C", 1687 "MatGetFactor_seqsbaij_petsc", 1688 MatGetFactor_seqsbaij_petsc);CHKERRQ(ierr); 1689 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 1690 "MatStoreValues_SeqSBAIJ", 1691 MatStoreValues_SeqSBAIJ);CHKERRQ(ierr); 1692 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 1693 "MatRetrieveValues_SeqSBAIJ", 1694 (void*)MatRetrieveValues_SeqSBAIJ);CHKERRQ(ierr); 1695 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C", 1696 "MatSeqSBAIJSetColumnIndices_SeqSBAIJ", 1697 MatSeqSBAIJSetColumnIndices_SeqSBAIJ);CHKERRQ(ierr); 1698 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C", 1699 "MatConvert_SeqSBAIJ_SeqAIJ", 1700 MatConvert_SeqSBAIJ_SeqAIJ);CHKERRQ(ierr); 1701 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C", 1702 "MatConvert_SeqSBAIJ_SeqBAIJ", 1703 MatConvert_SeqSBAIJ_SeqBAIJ);CHKERRQ(ierr); 1704 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C", 1705 "MatSeqSBAIJSetPreallocation_SeqSBAIJ", 1706 MatSeqSBAIJSetPreallocation_SeqSBAIJ);CHKERRQ(ierr); 1707 1708 B->symmetric = PETSC_TRUE; 1709 B->structurally_symmetric = PETSC_TRUE; 1710 B->symmetric_set = PETSC_TRUE; 1711 B->structurally_symmetric_set = PETSC_TRUE; 1712 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);CHKERRQ(ierr); 1713 PetscFunctionReturn(0); 1714 } 1715 EXTERN_C_END 1716 1717 #undef __FUNCT__ 1718 #define __FUNCT__ "MatSeqSBAIJSetPreallocation" 1719 /*@C 1720 MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block 1721 compressed row) format. For good matrix assembly performance the 1722 user should preallocate the matrix storage by setting the parameter nz 1723 (or the array nnz). By setting these parameters accurately, performance 1724 during matrix assembly can be increased by more than a factor of 50. 1725 1726 Collective on Mat 1727 1728 Input Parameters: 1729 + A - the symmetric matrix 1730 . bs - size of block 1731 . nz - number of block nonzeros per block row (same for all rows) 1732 - nnz - array containing the number of block nonzeros in the upper triangular plus 1733 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1734 1735 Options Database Keys: 1736 . -mat_no_unroll - uses code that does not unroll the loops in the 1737 block calculations (much slower) 1738 . -mat_block_size - size of the blocks to use (only works if a negative bs is passed in 1739 1740 Level: intermediate 1741 1742 Notes: 1743 Specify the preallocated storage with either nz or nnz (not both). 1744 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1745 allocation. For additional details, see the users manual chapter on 1746 matrices. 1747 1748 You can call MatGetInfo() to get information on how effective the preallocation was; 1749 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 1750 You can also run with the option -info and look for messages with the string 1751 malloc in them to see if additional memory allocation was needed. 1752 1753 If the nnz parameter is given then the nz parameter is ignored 1754 1755 1756 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1757 @*/ 1758 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[]) 1759 { 1760 PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]); 1761 1762 PetscFunctionBegin; 1763 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 1764 if (f) { 1765 ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr); 1766 } 1767 PetscFunctionReturn(0); 1768 } 1769 1770 #undef __FUNCT__ 1771 #define __FUNCT__ "MatCreateSeqSBAIJ" 1772 /*@C 1773 MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block 1774 compressed row) format. For good matrix assembly performance the 1775 user should preallocate the matrix storage by setting the parameter nz 1776 (or the array nnz). By setting these parameters accurately, performance 1777 during matrix assembly can be increased by more than a factor of 50. 1778 1779 Collective on MPI_Comm 1780 1781 Input Parameters: 1782 + comm - MPI communicator, set to PETSC_COMM_SELF 1783 . bs - size of block 1784 . m - number of rows, or number of columns 1785 . nz - number of block nonzeros per block row (same for all rows) 1786 - nnz - array containing the number of block nonzeros in the upper triangular plus 1787 diagonal portion of each block (possibly different for each block row) or PETSC_NULL 1788 1789 Output Parameter: 1790 . A - the symmetric matrix 1791 1792 Options Database Keys: 1793 . -mat_no_unroll - uses code that does not unroll the loops in the 1794 block calculations (much slower) 1795 . -mat_block_size - size of the blocks to use 1796 1797 Level: intermediate 1798 1799 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 1800 MatXXXXSetPreallocation() paradgm instead of this routine directly. 1801 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 1802 1803 Notes: 1804 The number of rows and columns must be divisible by blocksize. 1805 This matrix type does not support complex Hermitian operation. 1806 1807 Specify the preallocated storage with either nz or nnz (not both). 1808 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1809 allocation. For additional details, see the users manual chapter on 1810 matrices. 1811 1812 If the nnz parameter is given then the nz parameter is ignored 1813 1814 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ() 1815 @*/ 1816 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 1817 { 1818 PetscErrorCode ierr; 1819 1820 PetscFunctionBegin; 1821 ierr = MatCreate(comm,A);CHKERRQ(ierr); 1822 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 1823 ierr = MatSetType(*A,MATSEQSBAIJ);CHKERRQ(ierr); 1824 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr); 1825 PetscFunctionReturn(0); 1826 } 1827 1828 #undef __FUNCT__ 1829 #define __FUNCT__ "MatDuplicate_SeqSBAIJ" 1830 PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 1831 { 1832 Mat C; 1833 Mat_SeqSBAIJ *c,*a = (Mat_SeqSBAIJ*)A->data; 1834 PetscErrorCode ierr; 1835 PetscInt i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2; 1836 1837 PetscFunctionBegin; 1838 if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix"); 1839 1840 *B = 0; 1841 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1842 ierr = MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);CHKERRQ(ierr); 1843 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1844 ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1845 c = (Mat_SeqSBAIJ*)C->data; 1846 1847 C->preallocated = PETSC_TRUE; 1848 C->factor = A->factor; 1849 c->row = 0; 1850 c->icol = 0; 1851 c->saved_values = 0; 1852 c->keepzeroedrows = a->keepzeroedrows; 1853 C->assembled = PETSC_TRUE; 1854 1855 ierr = PetscMapCopy(((PetscObject)A)->comm,A->rmap,C->rmap);CHKERRQ(ierr); 1856 ierr = PetscMapCopy(((PetscObject)A)->comm,A->cmap,C->cmap);CHKERRQ(ierr); 1857 c->bs2 = a->bs2; 1858 c->mbs = a->mbs; 1859 c->nbs = a->nbs; 1860 1861 ierr = PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);CHKERRQ(ierr); 1862 for (i=0; i<mbs; i++) { 1863 c->imax[i] = a->imax[i]; 1864 c->ilen[i] = a->ilen[i]; 1865 } 1866 1867 /* allocate the matrix space */ 1868 ierr = PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);CHKERRQ(ierr); 1869 c->singlemalloc = PETSC_TRUE; 1870 ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1871 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));CHKERRQ(ierr); 1872 if (mbs > 0) { 1873 ierr = PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));CHKERRQ(ierr); 1874 if (cpvalues == MAT_COPY_VALUES) { 1875 ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1876 } else { 1877 ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 1878 } 1879 } 1880 1881 c->roworiented = a->roworiented; 1882 c->nonew = a->nonew; 1883 1884 if (a->diag) { 1885 ierr = PetscMalloc((mbs+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr); 1886 ierr = PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt));CHKERRQ(ierr); 1887 for (i=0; i<mbs; i++) { 1888 c->diag[i] = a->diag[i]; 1889 } 1890 } else c->diag = 0; 1891 c->nz = a->nz; 1892 c->maxnz = a->maxnz; 1893 c->solve_work = 0; 1894 c->mult_work = 0; 1895 c->free_a = PETSC_TRUE; 1896 c->free_ij = PETSC_TRUE; 1897 *B = C; 1898 ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 1899 PetscFunctionReturn(0); 1900 } 1901 1902 #undef __FUNCT__ 1903 #define __FUNCT__ "MatLoad_SeqSBAIJ" 1904 PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A) 1905 { 1906 Mat_SeqSBAIJ *a; 1907 Mat B; 1908 PetscErrorCode ierr; 1909 int fd; 1910 PetscMPIInt size; 1911 PetscInt i,nz,header[4],*rowlengths=0,M,N,bs=1; 1912 PetscInt *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount; 1913 PetscInt kmax,jcount,block,idx,point,nzcountb,extra_rows; 1914 PetscInt *masked,nmask,tmp,bs2,ishift; 1915 PetscScalar *aa; 1916 MPI_Comm comm = ((PetscObject)viewer)->comm; 1917 1918 PetscFunctionBegin; 1919 ierr = PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr); 1920 bs2 = bs*bs; 1921 1922 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1923 if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor"); 1924 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1925 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 1926 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object"); 1927 M = header[1]; N = header[2]; nz = header[3]; 1928 1929 if (header[3] < 0) { 1930 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ"); 1931 } 1932 1933 if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices"); 1934 1935 /* 1936 This code adds extra rows to make sure the number of rows is 1937 divisible by the blocksize 1938 */ 1939 mbs = M/bs; 1940 extra_rows = bs - M + bs*(mbs); 1941 if (extra_rows == bs) extra_rows = 0; 1942 else mbs++; 1943 if (extra_rows) { 1944 ierr = PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");CHKERRQ(ierr); 1945 } 1946 1947 /* read in row lengths */ 1948 ierr = PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 1949 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 1950 for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1; 1951 1952 /* read in column indices */ 1953 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);CHKERRQ(ierr); 1954 ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr); 1955 for (i=0; i<extra_rows; i++) jj[nz+i] = M+i; 1956 1957 /* loop over row lengths determining block row lengths */ 1958 ierr = PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);CHKERRQ(ierr); 1959 ierr = PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1960 ierr = PetscMalloc(2*mbs*sizeof(PetscInt),&mask);CHKERRQ(ierr); 1961 ierr = PetscMemzero(mask,mbs*sizeof(PetscInt));CHKERRQ(ierr); 1962 masked = mask + mbs; 1963 rowcount = 0; nzcount = 0; 1964 for (i=0; i<mbs; i++) { 1965 nmask = 0; 1966 for (j=0; j<bs; j++) { 1967 kmax = rowlengths[rowcount]; 1968 for (k=0; k<kmax; k++) { 1969 tmp = jj[nzcount++]/bs; /* block col. index */ 1970 if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;} 1971 } 1972 rowcount++; 1973 } 1974 s_browlengths[i] += nmask; 1975 1976 /* zero out the mask elements we set */ 1977 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 1978 } 1979 1980 /* create our matrix */ 1981 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 1982 ierr = MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);CHKERRQ(ierr); 1983 ierr = MatSetType(B,type);CHKERRQ(ierr); 1984 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);CHKERRQ(ierr); 1985 a = (Mat_SeqSBAIJ*)B->data; 1986 1987 /* set matrix "i" values */ 1988 a->i[0] = 0; 1989 for (i=1; i<= mbs; i++) { 1990 a->i[i] = a->i[i-1] + s_browlengths[i-1]; 1991 a->ilen[i-1] = s_browlengths[i-1]; 1992 } 1993 a->nz = a->i[mbs]; 1994 1995 /* read in nonzero values */ 1996 ierr = PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);CHKERRQ(ierr); 1997 ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr); 1998 for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0; 1999 2000 /* set "a" and "j" values into matrix */ 2001 nzcount = 0; jcount = 0; 2002 for (i=0; i<mbs; i++) { 2003 nzcountb = nzcount; 2004 nmask = 0; 2005 for (j=0; j<bs; j++) { 2006 kmax = rowlengths[i*bs+j]; 2007 for (k=0; k<kmax; k++) { 2008 tmp = jj[nzcount++]/bs; /* block col. index */ 2009 if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;} 2010 } 2011 } 2012 /* sort the masked values */ 2013 ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr); 2014 2015 /* set "j" values into matrix */ 2016 maskcount = 1; 2017 for (j=0; j<nmask; j++) { 2018 a->j[jcount++] = masked[j]; 2019 mask[masked[j]] = maskcount++; 2020 } 2021 2022 /* set "a" values into matrix */ 2023 ishift = bs2*a->i[i]; 2024 for (j=0; j<bs; j++) { 2025 kmax = rowlengths[i*bs+j]; 2026 for (k=0; k<kmax; k++) { 2027 tmp = jj[nzcountb]/bs ; /* block col. index */ 2028 if (tmp >= i){ 2029 block = mask[tmp] - 1; 2030 point = jj[nzcountb] - bs*tmp; 2031 idx = ishift + bs2*block + j + bs*point; 2032 a->a[idx] = aa[nzcountb]; 2033 } 2034 nzcountb++; 2035 } 2036 } 2037 /* zero out the mask elements we set */ 2038 for (j=0; j<nmask; j++) mask[masked[j]] = 0; 2039 } 2040 if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix"); 2041 2042 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 2043 ierr = PetscFree(s_browlengths);CHKERRQ(ierr); 2044 ierr = PetscFree(aa);CHKERRQ(ierr); 2045 ierr = PetscFree(jj);CHKERRQ(ierr); 2046 ierr = PetscFree(mask);CHKERRQ(ierr); 2047 2048 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2049 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2050 ierr = MatView_Private(B);CHKERRQ(ierr); 2051 *A = B; 2052 PetscFunctionReturn(0); 2053 } 2054 2055 #undef __FUNCT__ 2056 #define __FUNCT__ "MatRelax_SeqSBAIJ" 2057 PetscErrorCode MatRelax_SeqSBAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 2058 { 2059 Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data; 2060 MatScalar *aa=a->a,*v,*v1; 2061 PetscScalar *x,*b,*t,sum,d; 2062 PetscErrorCode ierr; 2063 PetscInt m=a->mbs,bs=A->rmap->bs,*ai=a->i,*aj=a->j; 2064 PetscInt nz,nz1,*vj,*vj1,i; 2065 2066 PetscFunctionBegin; 2067 if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat"); 2068 2069 its = its*lits; 2070 if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 2071 2072 if (bs > 1) 2073 SETERRQ(PETSC_ERR_SUP,"SSOR for block size > 1 is not yet implemented"); 2074 2075 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 2076 if (xx != bb) { 2077 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 2078 } else { 2079 b = x; 2080 } 2081 2082 if (!a->relax_work) { 2083 ierr = PetscMalloc(m*sizeof(PetscScalar),&a->relax_work);CHKERRQ(ierr); 2084 } 2085 t = a->relax_work; 2086 2087 if (flag & SOR_ZERO_INITIAL_GUESS) { 2088 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2089 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2090 2091 for (i=0; i<m; i++){ 2092 d = *(aa + ai[i]); /* diag[i] */ 2093 v = aa + ai[i] + 1; 2094 vj = aj + ai[i] + 1; 2095 nz = ai[i+1] - ai[i] - 1; 2096 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2097 x[i] = omega*t[i]/d; 2098 while (nz--) t[*vj++] -= x[i]*(*v++); /* update rhs */ 2099 } 2100 } 2101 2102 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2103 if (!(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)){ 2104 t = b; 2105 } 2106 2107 for (i=m-1; i>=0; i--){ 2108 d = *(aa + ai[i]); 2109 v = aa + ai[i] + 1; 2110 vj = aj + ai[i] + 1; 2111 nz = ai[i+1] - ai[i] - 1; 2112 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2113 sum = t[i]; 2114 while (nz--) sum -= x[*vj++]*(*v++); 2115 x[i] = (1-omega)*x[i] + omega*sum/d; 2116 } 2117 t = a->relax_work; 2118 } 2119 its--; 2120 } 2121 2122 while (its--) { 2123 /* 2124 forward sweep: 2125 for i=0,...,m-1: 2126 sum[i] = (b[i] - U(i,:)x )/d[i]; 2127 x[i] = (1-omega)x[i] + omega*sum[i]; 2128 b = b - x[i]*U^T(i,:); 2129 2130 */ 2131 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 2132 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2133 2134 for (i=0; i<m; i++){ 2135 d = *(aa + ai[i]); /* diag[i] */ 2136 v = aa + ai[i] + 1; v1=v; 2137 vj = aj + ai[i] + 1; vj1=vj; 2138 nz = ai[i+1] - ai[i] - 1; nz1=nz; 2139 sum = t[i]; 2140 ierr = PetscLogFlops(4*nz-2);CHKERRQ(ierr); 2141 while (nz1--) sum -= (*v1++)*x[*vj1++]; 2142 x[i] = (1-omega)*x[i] + omega*sum/d; 2143 while (nz--) t[*vj++] -= x[i]*(*v++); 2144 } 2145 } 2146 2147 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 2148 /* 2149 backward sweep: 2150 b = b - x[i]*U^T(i,:), i=0,...,n-2 2151 for i=m-1,...,0: 2152 sum[i] = (b[i] - U(i,:)x )/d[i]; 2153 x[i] = (1-omega)x[i] + omega*sum[i]; 2154 */ 2155 /* if there was a forward sweep done above then I thing the next two for loops are not needed */ 2156 ierr = PetscMemcpy(t,b,m*sizeof(PetscScalar));CHKERRQ(ierr); 2157 2158 for (i=0; i<m-1; i++){ /* update rhs */ 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 while (nz--) t[*vj++] -= x[i]*(*v++); 2164 } 2165 for (i=m-1; i>=0; i--){ 2166 d = *(aa + ai[i]); 2167 v = aa + ai[i] + 1; 2168 vj = aj + ai[i] + 1; 2169 nz = ai[i+1] - ai[i] - 1; 2170 ierr = PetscLogFlops(2*nz-1);CHKERRQ(ierr); 2171 sum = t[i]; 2172 while (nz--) sum -= x[*vj++]*(*v++); 2173 x[i] = (1-omega)*x[i] + omega*sum/d; 2174 } 2175 } 2176 } 2177 2178 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2179 if (bb != xx) { 2180 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 2181 } 2182 PetscFunctionReturn(0); 2183 } 2184 2185 #undef __FUNCT__ 2186 #define __FUNCT__ "MatCreateSeqSBAIJWithArrays" 2187 /*@ 2188 MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements 2189 (upper triangular entries in CSR format) provided by the user. 2190 2191 Collective on MPI_Comm 2192 2193 Input Parameters: 2194 + comm - must be an MPI communicator of size 1 2195 . bs - size of block 2196 . m - number of rows 2197 . n - number of columns 2198 . i - row indices 2199 . j - column indices 2200 - a - matrix values 2201 2202 Output Parameter: 2203 . mat - the matrix 2204 2205 Level: intermediate 2206 2207 Notes: 2208 The i, j, and a arrays are not copied by this routine, the user must free these arrays 2209 once the matrix is destroyed 2210 2211 You cannot set new nonzero locations into this matrix, that will generate an error. 2212 2213 The i and j indices are 0 based 2214 2215 .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ() 2216 2217 @*/ 2218 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat) 2219 { 2220 PetscErrorCode ierr; 2221 PetscInt ii; 2222 Mat_SeqSBAIJ *sbaij; 2223 2224 PetscFunctionBegin; 2225 if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs); 2226 if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 2227 2228 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 2229 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 2230 ierr = MatSetType(*mat,MATSEQSBAIJ);CHKERRQ(ierr); 2231 ierr = MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 2232 sbaij = (Mat_SeqSBAIJ*)(*mat)->data; 2233 ierr = PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);CHKERRQ(ierr); 2234 2235 sbaij->i = i; 2236 sbaij->j = j; 2237 sbaij->a = a; 2238 sbaij->singlemalloc = PETSC_FALSE; 2239 sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2240 sbaij->free_a = PETSC_FALSE; 2241 sbaij->free_ij = PETSC_FALSE; 2242 2243 for (ii=0; ii<m; ii++) { 2244 sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii]; 2245 #if defined(PETSC_USE_DEBUG) 2246 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]); 2247 #endif 2248 } 2249 #if defined(PETSC_USE_DEBUG) 2250 for (ii=0; ii<sbaij->i[m]; ii++) { 2251 if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]); 2252 if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]); 2253 } 2254 #endif 2255 2256 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2257 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2258 PetscFunctionReturn(0); 2259 } 2260 2261 2262 2263 2264 2265