MatCopyHashToXAIJ_Seq_Hash(Mat A,Mat B)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 */
MatAssemblyEnd_Seq_Hash(Mat A,MatAssemblyType type)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
MatDestroy_Seq_Hash(Mat A)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
MatZeroEntries_Seq_Hash(Mat A)9826cec326SBarry Smith static PetscErrorCode MatZeroEntries_Seq_Hash(Mat A)
9926cec326SBarry Smith {
10026cec326SBarry Smith PetscFunctionBegin;
10126cec326SBarry Smith PetscFunctionReturn(PETSC_SUCCESS);
10226cec326SBarry Smith }
10326cec326SBarry Smith
MatSetRandom_Seq_Hash(Mat A,PetscRandom r)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
MatSetUp_Seq_Hash(Mat A)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