1*26cec326SBarry Smith /* 2*26cec326SBarry Smith used by SEQAIJ, BAIJ and SBAIJ to reduce code duplication 3*26cec326SBarry Smith 4*26cec326SBarry Smith define TYPE to AIJ BAIJ or SBAIJ 5*26cec326SBarry Smith TYPE_BS_ON for BAIJ and SBAIJ 6*26cec326SBarry Smith 7*26cec326SBarry Smith */ 8*26cec326SBarry Smith static PetscErrorCode MatAssemblyEnd_Seq_Hash(Mat A, MatAssemblyType type) 9*26cec326SBarry Smith { 10*26cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 11*26cec326SBarry Smith PetscHashIter hi; 12*26cec326SBarry Smith PetscHashIJKey key; 13*26cec326SBarry Smith PetscScalar value, *values; 14*26cec326SBarry Smith PetscInt m, n, *cols, *rowstarts; 15*26cec326SBarry Smith #if defined(TYPE_BS_ON) 16*26cec326SBarry Smith PetscInt bs; 17*26cec326SBarry Smith #endif 18*26cec326SBarry Smith 19*26cec326SBarry Smith PetscFunctionBegin; 20*26cec326SBarry Smith #if defined(TYPE_BS_ON) 21*26cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 22*26cec326SBarry Smith if (bs > 1) PetscCall(PetscHSetIJDestroy(&a->bht)); 23*26cec326SBarry Smith #endif 24*26cec326SBarry Smith A->preallocated = PETSC_FALSE; /* this was set to true for the MatSetValues_Hash() to work */ 25*26cec326SBarry Smith 26*26cec326SBarry Smith PetscCall(PetscMemcpy(&A->ops, &a->cops, sizeof(*(A->ops)))); 27*26cec326SBarry Smith 28*26cec326SBarry Smith /* move values from hash format to matrix type format */ 29*26cec326SBarry Smith PetscCall(MatGetSize(A, &m, NULL)); 30*26cec326SBarry Smith #if defined(TYPE_BS_ON) 31*26cec326SBarry Smith if (bs > 1) PetscCall(PetscConcat(PetscConcat(MatSeq, TYPE), SetPreallocation)(A, bs, PETSC_DETERMINE, a->bdnz)); 32*26cec326SBarry Smith else PetscCall(PetscConcat(PetscConcat(MatSeq, TYPE), SetPreallocation)(A, 1, PETSC_DETERMINE, a->dnz)); 33*26cec326SBarry Smith #else 34*26cec326SBarry Smith PetscCall(MatSeqAIJSetPreallocation(A, PETSC_DETERMINE, a->dnz)); 35*26cec326SBarry Smith #endif 36*26cec326SBarry Smith PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 37*26cec326SBarry Smith PetscCall(PetscHMapIJVGetSize(a->ht, &n)); 38*26cec326SBarry Smith PetscCall(PetscMalloc3(n, &cols, m + 1, &rowstarts, n, &values)); 39*26cec326SBarry Smith rowstarts[0] = 0; 40*26cec326SBarry Smith for (PetscInt i = 0; i < m; i++) rowstarts[i + 1] = rowstarts[i] + a->dnz[i]; 41*26cec326SBarry Smith 42*26cec326SBarry Smith PetscHashIterBegin(a->ht, hi); 43*26cec326SBarry Smith while (!PetscHashIterAtEnd(a->ht, hi)) { 44*26cec326SBarry Smith PetscHashIterGetKey(a->ht, hi, key); 45*26cec326SBarry Smith PetscHashIterGetVal(a->ht, hi, value); 46*26cec326SBarry Smith cols[rowstarts[key.i]] = key.j; 47*26cec326SBarry Smith values[rowstarts[key.i]++] = value; 48*26cec326SBarry Smith PetscHashIterNext(a->ht, hi); 49*26cec326SBarry Smith } 50*26cec326SBarry Smith PetscCall(PetscHMapIJVDestroy(&a->ht)); 51*26cec326SBarry Smith 52*26cec326SBarry Smith for (PetscInt i = 0, start = 0; i < m; i++) { 53*26cec326SBarry Smith PetscCall(MatSetValues(A, 1, &i, a->dnz[i], &cols[start], &values[start], A->insertmode)); 54*26cec326SBarry Smith start += a->dnz[i]; 55*26cec326SBarry Smith } 56*26cec326SBarry Smith PetscCall(PetscFree3(cols, rowstarts, values)); 57*26cec326SBarry Smith PetscCall(PetscFree(a->dnz)); 58*26cec326SBarry Smith #if defined(TYPE_BS_ON) 59*26cec326SBarry Smith if (bs > 1) PetscCall(PetscFree(a->bdnz)); 60*26cec326SBarry Smith #endif 61*26cec326SBarry Smith PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 62*26cec326SBarry Smith PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 63*26cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 64*26cec326SBarry Smith } 65*26cec326SBarry Smith 66*26cec326SBarry Smith static PetscErrorCode MatDestroy_Seq_Hash(Mat A) 67*26cec326SBarry Smith { 68*26cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 69*26cec326SBarry Smith #if defined(TYPE_BS_ON) 70*26cec326SBarry Smith PetscInt bs; 71*26cec326SBarry Smith #endif 72*26cec326SBarry Smith 73*26cec326SBarry Smith PetscFunctionBegin; 74*26cec326SBarry Smith PetscCall(PetscHMapIJVDestroy(&a->ht)); 75*26cec326SBarry Smith PetscCall(PetscFree(a->dnz)); 76*26cec326SBarry Smith #if defined(TYPE_BS_ON) 77*26cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 78*26cec326SBarry Smith if (bs > 1) { 79*26cec326SBarry Smith PetscCall(PetscFree(a->bdnz)); 80*26cec326SBarry Smith PetscCall(PetscHSetIJDestroy(&a->bht)); 81*26cec326SBarry Smith } 82*26cec326SBarry Smith #endif 83*26cec326SBarry Smith PetscCall((*a->cops.destroy)(A)); 84*26cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 85*26cec326SBarry Smith } 86*26cec326SBarry Smith 87*26cec326SBarry Smith static PetscErrorCode MatZeroEntries_Seq_Hash(Mat A) 88*26cec326SBarry Smith { 89*26cec326SBarry Smith PetscFunctionBegin; 90*26cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 91*26cec326SBarry Smith } 92*26cec326SBarry Smith 93*26cec326SBarry Smith static PetscErrorCode MatSetRandom_Seq_Hash(Mat A, PetscRandom r) 94*26cec326SBarry Smith { 95*26cec326SBarry Smith PetscFunctionBegin; 96*26cec326SBarry Smith SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Must set preallocation first"); 97*26cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 98*26cec326SBarry Smith } 99*26cec326SBarry Smith 100*26cec326SBarry Smith static PetscErrorCode MatSetUp_Seq_Hash(Mat A) 101*26cec326SBarry Smith { 102*26cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 103*26cec326SBarry Smith PetscInt m; 104*26cec326SBarry Smith #if defined(TYPE_BS_ON) 105*26cec326SBarry Smith PetscInt bs; 106*26cec326SBarry Smith #endif 107*26cec326SBarry Smith 108*26cec326SBarry Smith PetscFunctionBegin; 109*26cec326SBarry Smith PetscCall(PetscInfo(A, "Using hash-based MatSetValues() for MATSEQAIJ because no preallocation provided\n")); 110*26cec326SBarry Smith PetscCall(PetscLayoutSetUp(A->rmap)); 111*26cec326SBarry Smith PetscCall(PetscLayoutSetUp(A->cmap)); 112*26cec326SBarry Smith if (A->rmap->bs < 1) A->rmap->bs = 1; 113*26cec326SBarry Smith if (A->cmap->bs < 1) A->cmap->bs = 1; 114*26cec326SBarry Smith 115*26cec326SBarry Smith PetscCall(MatGetLocalSize(A, &m, NULL)); 116*26cec326SBarry Smith PetscCall(PetscHMapIJVCreate(&a->ht)); 117*26cec326SBarry Smith PetscCall(PetscCalloc1(m, &a->dnz)); 118*26cec326SBarry Smith #if defined(TYPE_BS_ON) 119*26cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 120*26cec326SBarry Smith if (bs > 1) { 121*26cec326SBarry Smith PetscCall(PetscCalloc1(m / bs, &a->bdnz)); 122*26cec326SBarry Smith PetscCall(PetscHSetIJCreate(&a->bht)); 123*26cec326SBarry Smith } 124*26cec326SBarry Smith #endif 125*26cec326SBarry Smith 126*26cec326SBarry Smith /* keep a record of the operations so they can be reset when the hash handling is complete */ 127*26cec326SBarry Smith PetscCall(PetscMemcpy(&a->cops, &A->ops, sizeof(*(A->ops)))); 128*26cec326SBarry Smith 129*26cec326SBarry Smith A->ops->assemblybegin = NULL; 130*26cec326SBarry Smith A->ops->assemblyend = MatAssemblyEnd_Seq_Hash; 131*26cec326SBarry Smith A->ops->destroy = MatDestroy_Seq_Hash; 132*26cec326SBarry Smith A->ops->zeroentries = MatZeroEntries_Seq_Hash; 133*26cec326SBarry Smith A->ops->setrandom = MatSetRandom_Seq_Hash; 134*26cec326SBarry Smith #if defined(TYPE_BS_ON) 135*26cec326SBarry Smith if (bs > 1) A->ops->setvalues = MatSetValues_Seq_Hash_BS; 136*26cec326SBarry Smith else 137*26cec326SBarry Smith #endif 138*26cec326SBarry Smith A->ops->setvalues = MatSetValues_Seq_Hash; 139*26cec326SBarry Smith A->ops->setvaluesblocked = NULL; 140*26cec326SBarry Smith 141*26cec326SBarry Smith A->preallocated = PETSC_TRUE; 142*26cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 143*26cec326SBarry Smith } 144