1fe1fc275SAlexander static PetscErrorCode MatCopyHashToXAIJ_Seq_Hash(Mat A, Mat B) 226cec326SBarry Smith { 326cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 426cec326SBarry Smith PetscHashIter hi; 526cec326SBarry Smith PetscHashIJKey key; 626cec326SBarry Smith PetscScalar value, *values; 726cec326SBarry Smith PetscInt m, n, *cols, *rowstarts; 826cec326SBarry Smith #if defined(TYPE_BS_ON) 926cec326SBarry Smith PetscInt bs; 1026cec326SBarry Smith #endif 1126cec326SBarry Smith 1226cec326SBarry Smith PetscFunctionBegin; 1326cec326SBarry Smith #if defined(TYPE_BS_ON) 1426cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 15fe1fc275SAlexander if (bs > 1 && A == B) PetscCall(PetscHSetIJDestroy(&a->bht)); 1626cec326SBarry Smith #endif 17fe1fc275SAlexander if (A == B) { 1826cec326SBarry Smith A->preallocated = PETSC_FALSE; /* this was set to true for the MatSetValues_Hash() to work */ 1926cec326SBarry Smith 20aea10558SJacob Faibussowitsch A->ops[0] = a->cops; 21ad79cf63SBarry Smith A->hash_active = PETSC_FALSE; 22fe1fc275SAlexander } 2326cec326SBarry Smith 2426cec326SBarry Smith /* move values from hash format to matrix type format */ 2526cec326SBarry Smith PetscCall(MatGetSize(A, &m, NULL)); 2626cec326SBarry Smith #if defined(TYPE_BS_ON) 27fe1fc275SAlexander if (bs > 1) PetscCall(PetscConcat(PetscConcat(MatSeq, TYPE), SetPreallocation)(B, bs, PETSC_DETERMINE, a->bdnz)); 28fe1fc275SAlexander else PetscCall(PetscConcat(PetscConcat(MatSeq, TYPE), SetPreallocation)(B, 1, PETSC_DETERMINE, a->dnz)); 2926cec326SBarry Smith #else 30fe1fc275SAlexander PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, a->dnz)); 3126cec326SBarry Smith #endif 32fe1fc275SAlexander PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 3326cec326SBarry Smith PetscCall(PetscHMapIJVGetSize(a->ht, &n)); 349f0612e4SBarry Smith /* do not need PetscShmgetAllocateArray() since arrays are temporary */ 3526cec326SBarry Smith PetscCall(PetscMalloc3(n, &cols, m + 1, &rowstarts, n, &values)); 3626cec326SBarry Smith rowstarts[0] = 0; 3726cec326SBarry Smith for (PetscInt i = 0; i < m; i++) rowstarts[i + 1] = rowstarts[i] + a->dnz[i]; 3826cec326SBarry Smith 3926cec326SBarry Smith PetscHashIterBegin(a->ht, hi); 4026cec326SBarry Smith while (!PetscHashIterAtEnd(a->ht, hi)) { 4126cec326SBarry Smith PetscHashIterGetKey(a->ht, hi, key); 4226cec326SBarry Smith PetscHashIterGetVal(a->ht, hi, value); 4326cec326SBarry Smith cols[rowstarts[key.i]] = key.j; 4426cec326SBarry Smith values[rowstarts[key.i]++] = value; 4526cec326SBarry Smith PetscHashIterNext(a->ht, hi); 4626cec326SBarry Smith } 47fe1fc275SAlexander if (A == B) PetscCall(PetscHMapIJVDestroy(&a->ht)); 4826cec326SBarry Smith 4926cec326SBarry Smith for (PetscInt i = 0, start = 0; i < m; i++) { 50fe1fc275SAlexander PetscCall(MatSetValues(B, 1, &i, a->dnz[i], PetscSafePointerPlusOffset(cols, start), PetscSafePointerPlusOffset(values, start), B->insertmode)); 5126cec326SBarry Smith start += a->dnz[i]; 5226cec326SBarry Smith } 5326cec326SBarry Smith PetscCall(PetscFree3(cols, rowstarts, values)); 54fe1fc275SAlexander if (A == B) PetscCall(PetscFree(a->dnz)); 5526cec326SBarry Smith #if defined(TYPE_BS_ON) 56fe1fc275SAlexander if (bs > 1 && A == B) PetscCall(PetscFree(a->bdnz)); 5726cec326SBarry Smith #endif 58fe1fc275SAlexander PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 59fe1fc275SAlexander PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 60fe1fc275SAlexander PetscFunctionReturn(PETSC_SUCCESS); 61fe1fc275SAlexander } 62fe1fc275SAlexander 63fe1fc275SAlexander /* 64fe1fc275SAlexander used by SEQAIJ, BAIJ and SBAIJ to reduce code duplication 65fe1fc275SAlexander 66fe1fc275SAlexander define TYPE to AIJ BAIJ or SBAIJ 67fe1fc275SAlexander TYPE_BS_ON for BAIJ and SBAIJ 68fe1fc275SAlexander 69fe1fc275SAlexander */ 70fe1fc275SAlexander static PetscErrorCode MatAssemblyEnd_Seq_Hash(Mat A, MatAssemblyType type) 71fe1fc275SAlexander { 72fe1fc275SAlexander PetscFunctionBegin; 73fe1fc275SAlexander PetscCall(MatCopyHashToXAIJ(A, A)); 7426cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 7526cec326SBarry Smith } 7626cec326SBarry Smith 7726cec326SBarry Smith static PetscErrorCode MatDestroy_Seq_Hash(Mat A) 7826cec326SBarry Smith { 7926cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 8026cec326SBarry Smith #if defined(TYPE_BS_ON) 8126cec326SBarry Smith PetscInt bs; 8226cec326SBarry Smith #endif 8326cec326SBarry Smith 8426cec326SBarry Smith PetscFunctionBegin; 8526cec326SBarry Smith PetscCall(PetscHMapIJVDestroy(&a->ht)); 8626cec326SBarry Smith PetscCall(PetscFree(a->dnz)); 8726cec326SBarry Smith #if defined(TYPE_BS_ON) 8826cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 8926cec326SBarry Smith if (bs > 1) { 9026cec326SBarry Smith PetscCall(PetscFree(a->bdnz)); 9126cec326SBarry Smith PetscCall(PetscHSetIJDestroy(&a->bht)); 9226cec326SBarry Smith } 9326cec326SBarry Smith #endif 9426cec326SBarry Smith PetscCall((*a->cops.destroy)(A)); 9526cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 9626cec326SBarry Smith } 9726cec326SBarry Smith 9826cec326SBarry Smith static PetscErrorCode MatZeroEntries_Seq_Hash(Mat A) 9926cec326SBarry Smith { 10026cec326SBarry Smith PetscFunctionBegin; 10126cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 10226cec326SBarry Smith } 10326cec326SBarry Smith 10426cec326SBarry Smith static PetscErrorCode MatSetRandom_Seq_Hash(Mat A, PetscRandom r) 10526cec326SBarry Smith { 10626cec326SBarry Smith PetscFunctionBegin; 10726cec326SBarry Smith SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Must set preallocation first"); 10826cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 10926cec326SBarry Smith } 11026cec326SBarry Smith 11126cec326SBarry Smith static PetscErrorCode MatSetUp_Seq_Hash(Mat A) 11226cec326SBarry Smith { 11326cec326SBarry Smith PetscConcat(Mat_Seq, TYPE) *a = (PetscConcat(Mat_Seq, TYPE) *)A->data; 11426cec326SBarry Smith PetscInt m; 11526cec326SBarry Smith #if defined(TYPE_BS_ON) 11626cec326SBarry Smith PetscInt bs; 11726cec326SBarry Smith #endif 11826cec326SBarry Smith 11926cec326SBarry Smith PetscFunctionBegin; 120*666f9b3fSPierre Jolivet PetscCall(PetscInfo(A, "Using hash-based MatSetValues() for MATSEQ" PetscStringize(TYPE) " because no preallocation provided\n")); 12126cec326SBarry Smith PetscCall(PetscLayoutSetUp(A->rmap)); 12226cec326SBarry Smith PetscCall(PetscLayoutSetUp(A->cmap)); 12326cec326SBarry Smith if (A->rmap->bs < 1) A->rmap->bs = 1; 12426cec326SBarry Smith if (A->cmap->bs < 1) A->cmap->bs = 1; 12526cec326SBarry Smith 12626cec326SBarry Smith PetscCall(MatGetLocalSize(A, &m, NULL)); 12726cec326SBarry Smith PetscCall(PetscHMapIJVCreate(&a->ht)); 12826cec326SBarry Smith PetscCall(PetscCalloc1(m, &a->dnz)); 12926cec326SBarry Smith #if defined(TYPE_BS_ON) 13026cec326SBarry Smith PetscCall(MatGetBlockSize(A, &bs)); 13126cec326SBarry Smith if (bs > 1) { 13226cec326SBarry Smith PetscCall(PetscCalloc1(m / bs, &a->bdnz)); 13326cec326SBarry Smith PetscCall(PetscHSetIJCreate(&a->bht)); 13426cec326SBarry Smith } 13526cec326SBarry Smith #endif 13626cec326SBarry Smith 13726cec326SBarry Smith /* keep a record of the operations so they can be reset when the hash handling is complete */ 138aea10558SJacob Faibussowitsch a->cops = A->ops[0]; 13926cec326SBarry Smith A->ops->assemblybegin = NULL; 14026cec326SBarry Smith A->ops->assemblyend = MatAssemblyEnd_Seq_Hash; 14126cec326SBarry Smith A->ops->destroy = MatDestroy_Seq_Hash; 14226cec326SBarry Smith A->ops->zeroentries = MatZeroEntries_Seq_Hash; 14326cec326SBarry Smith A->ops->setrandom = MatSetRandom_Seq_Hash; 144fe1fc275SAlexander A->ops->copyhashtoxaij = MatCopyHashToXAIJ_Seq_Hash; 14526cec326SBarry Smith #if defined(TYPE_BS_ON) 14626cec326SBarry Smith if (bs > 1) A->ops->setvalues = MatSetValues_Seq_Hash_BS; 14726cec326SBarry Smith else 14826cec326SBarry Smith #endif 14926cec326SBarry Smith A->ops->setvalues = MatSetValues_Seq_Hash; 15026cec326SBarry Smith A->ops->setvaluesblocked = NULL; 15126cec326SBarry Smith 15226cec326SBarry Smith A->preallocated = PETSC_TRUE; 153ad79cf63SBarry Smith A->hash_active = PETSC_TRUE; 15426cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 15526cec326SBarry Smith } 156