xref: /petsc/src/mat/impls/aij/seq/seqhashmat.h (revision 26cec32642a02ddeaa9481e1a5bd50b8500ffeea)
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