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