11 double hypre_param[NPARAM];
13 static struct hypre_crs_data **handle_array = 0;
14 static int handle_max = 0;
15 static int handle_n = 0;
18 uint nz,
const uint *Ai,
const uint *Aj,
const double *Av,
19 const uint null_space,
const struct comm *comm,
22 struct hypre_crs_data *hypre_data = tmalloc(
struct hypre_crs_data, 1);
24 hypre_data->nullspace = null_space;
26 comm_dup(&hypre_data->comm,comm);
27 hypre_data->gs_top = gs_setup((
const slong*)
id,n,&hypre_data->comm, 1,
34 double tmp = (double)hypre_data->un;
36 comm_allreduce(&hypre_data->comm,gs_double,gs_add,&tmp,1,&buf);
37 hypre_data->tni = 1./tmp;
40 HYPRE_BoomerAMGCreate(&hypre_data->solver);
41 HYPRE_Solver solver = hypre_data->solver;
43 int uparam = (int) param[0];
48 for (i = 0; i < NPARAM; i++) {
49 hypre_param[i] = param[i+1];
51 printf(
"Custom HYPREsettings[%d]: %.2f\n", i+1, hypre_param[i]);
59 hypre_param[5] = 0.25;
62 hypre_param[8] = 0.01;
63 hypre_param[9] = 0.05;
66 HYPRE_BoomerAMGSetCoarsenType(solver,hypre_param[0]);
67 HYPRE_BoomerAMGSetInterpType(solver,hypre_param[1]);
68 if (null_space == 1 || uparam) {
70 HYPRE_BoomerAMGSetCycleRelaxType(solver, hypre_param[3], 3);
71 HYPRE_BoomerAMGSetCycleNumSweeps(solver, hypre_param[4], 3);
73 HYPRE_BoomerAMGSetStrongThreshold(solver,hypre_param[5]);
74 HYPRE_BoomerAMGSetNonGalerkinTol(solver,hypre_param[6]);
75 HYPRE_BoomerAMGSetLevelNonGalerkinTol(solver,hypre_param[7], 0);
76 HYPRE_BoomerAMGSetLevelNonGalerkinTol(solver,hypre_param[8], 1);
77 HYPRE_BoomerAMGSetLevelNonGalerkinTol(solver,hypre_param[9], 2);
79 HYPRE_BoomerAMGSetMinCoarseSize(solver,2);
80 HYPRE_BoomerAMGSetMaxIter(solver,1);
81 HYPRE_BoomerAMGSetPrintLevel(solver,1);
82 HYPRE_BoomerAMGSetTol(solver,0.0);
85 HYPRE_Int ilower = hypre_data->ilower;
86 HYPRE_Int iupper = ilower + (HYPRE_Int)(hypre_data->un) - 1;
88 HYPRE_IJVectorCreate(hypre_data->comm.c,ilower,iupper,&hypre_data->b);
89 HYPRE_IJVector b = hypre_data->b;
90 HYPRE_IJVectorCreate(hypre_data->comm.c,ilower,iupper,&hypre_data->x);
91 HYPRE_IJVector x = hypre_data->x;
92 HYPRE_IJVectorSetObjectType(b,HYPRE_PARCSR);
93 HYPRE_IJVectorSetObjectType(x,HYPRE_PARCSR);
94 HYPRE_IJVectorInitialize(b);
95 HYPRE_IJVectorInitialize(x);
96 HYPRE_IJVectorAssemble(b);
97 HYPRE_IJVectorAssemble(x);
100 HYPRE_ParVector par_b;
101 HYPRE_ParVector par_x;
102 HYPRE_IJVectorGetObject(b,(
void**) &par_b);
103 HYPRE_IJVectorGetObject(x,(
void**) &par_x);
105 HYPRE_ParCSRMatrix par_A;
106 HYPRE_IJMatrixGetObject(hypre_data->A,(
void**) &par_A);
108 HYPRE_BoomerAMGSetup(solver,par_A,par_b,par_x);
113 sint set_BoomerAMG_parameters(HYPRE_Solver *solver_ptr,
const double *param)
115 HYPRE_Solver solver = *solver_ptr;
121 *
id, uint nz_unassembled,
const uint *Ai,
const uint* Aj,
const double *Av)
127 ulong *uid_p = uid.ptr;
128 struct rid *rid_map = tmalloc(
struct rid,n);
134 comm = hypre_data->comm;
135 gs_top = hypre_data->gs_top;
138 crystal_init(&cr, &comm);
141 assign_dofs_hypre(&uid,rid_map,
id,n,comm.id,gs_top,&cr.data,&comm);
144 array_init(
struct rnz,&mat,nz_unassembled);
145 for(out=mat.ptr,k=0;k<nz_unassembled;++k) {
146 uint i=Ai[k],
j=Aj[k];
double a=Av[k];
147 if(
id[i]==0 ||
id[
j]==0 || fabs(a)==0)
continue;
148 out->
v = a, out->i=rid_map[i], out->
j=rid_map[
j];
151 mat.n = out-(
struct rnz*)mat.ptr;
155 const ulong *
const uid_ptr = uid.ptr;
156 const uint pid = comm.id, np = comm.np;
157 struct array nonlocal_id;
159 const struct rnz *nz, *enz;
165 mat_list_nonlocal_sorted(&nonlocal_id,&mat,
row_distr,uid_ptr,&cr);
166 rlbl = nonlocal_id.ptr;
169 hypre_data->un = uid.n;
171 HYPRE_Int ilower = (HYPRE_Int)(uid_ptr[0]);
172 hypre_data->ilower = ilower;
173 HYPRE_Int iupper = ilower + (HYPRE_Int)(uid.n) - 1;
175 HYPRE_IJMatrixCreate(comm.c,ilower,iupper,ilower,iupper,&hypre_data->A);
176 HYPRE_IJMatrix A_ij = hypre_data->A;
177 HYPRE_IJMatrixSetObjectType(A_ij,HYPRE_PARCSR);
178 HYPRE_IJMatrixInitialize(A_ij);
180 HYPRE_Int mati, matj;
182 HYPRE_Int nrows = 1, ncols = 1;
184 for(nz=mat.ptr,enz=nz+nnz;nz!=enz;++nz)
186 mati = (HYPRE_Int)(uid_ptr[nz->i.i]);
190 matj = (HYPRE_Int)(uid_ptr[nz->
j.
i]);
194 const uint jp = nz->
j.
p, ji = nz->
j.
i;
195 while(rlbl->
rid.
p<jp) ++rlbl;
196 if(rlbl->
rid.
p!=jp) printf(
"Error when assembling matrix\n");
197 while(rlbl->
rid.
i<ji) ++rlbl;
198 if(rlbl->
rid.
i!=ji) printf(
"Error when assembling matrix\n");
199 matj = (HYPRE_Int)(rlbl->
id);
201 HYPRE_IJMatrixSetValues(A_ij, nrows, &ncols, &mati, &matj, &matv);
207 array_free(&nonlocal_id);
210 hypre_data->umap=assign_dofs_hypre(&uid,0,
id,n,pid,gs_top,&cr.data,&comm);
214 HYPRE_IJMatrixAssemble(A_ij);
219 uint i;
const uint un = data->un;
const uint *
const umap = data->umap;
220 HYPRE_Int ilower = data->ilower;
221 HYPRE_IJVector ij_x = data->x;
222 HYPRE_IJVector ij_b = data->b;
223 HYPRE_IJMatrix ij_A = data->A;
224 HYPRE_Solver solver = data->solver;
226 HYPRE_ParVector par_x;
227 HYPRE_ParVector par_b;
228 HYPRE_ParCSRMatrix par_A;
230 gs(b, gs_double,gs_add, 1, data->gs_top, 0);
233 HYPRE_Int ii = ilower + (HYPRE_Int)i;
234 double bb = b[umap[i]];
235 HYPRE_IJVectorSetValues(ij_b,1,&ii,&bb);
238 HYPRE_IJVectorAssemble(ij_b);
239 HYPRE_IJVectorGetObject(ij_b,(
void**) &par_b);
241 HYPRE_IJVectorAssemble(ij_x);
242 HYPRE_IJVectorGetObject(ij_x,(
void **) &par_x);
244 HYPRE_IJMatrixGetObject(ij_A,(
void**) &par_A);
246 HYPRE_BoomerAMGSolve(solver,par_A,par_b,par_x);
251 HYPRE_Int ii = ilower + (HYPRE_Int)i;
253 HYPRE_IJVectorGetValues(ij_x,1,&ii,&xx);
255 if (data->nullspace) avg += xx;
261 comm_allreduce(&data->comm,gs_double,gs_add,&avg,1,&buf);
263 for(i=0;i<un;++i) x[umap[i]] -= avg;
266 gs(x, gs_double,gs_add, 0, data->gs_top, 0);
271 HYPRE_BoomerAMGDestroy(data->solver);
272 HYPRE_IJMatrixDestroy(data->A);
273 HYPRE_IJVectorDestroy(data->x);
274 HYPRE_IJVectorDestroy(data->b);
275 comm_free(&data->comm);
276 gs_free(data->gs_top);
292 static uint *assign_dofs_hypre(
struct array *
const uid,
293 struct rid *
const rid_map,
294 const ulong *
const id,
const uint n,
296 struct gs_data *gs_top, buffer *
const buf,
299 uint i,count, *map=0;
300 struct rid *
const rid = rid_map?rid_map:tmalloc(
struct rid,n);
302 gs_vec(n?&
rid[0].
p:0,2, gs_sint,gs_add,0, gs_top,buf);
303 for(count=0,
i=0;
i<n;++
i) {
305 array_init(ulong,uid,count); uid->n=count;
307 map=tmalloc(uint,count);
308 for(count=0,
i=0;
i<n;++
i) {
312 ulong scan_out[2],scan_buf[2],uln;
313 uln = (ulong) uid->n;
314 comm_scan(scan_out,comm,gs_long,gs_add,&uln,1,scan_buf);
315 ulong uilow = scan_out[0];
316 ulong *
const uid_p = uid->ptr;
318 uid_p[count]=uilow+(ulong)count,
rid[
i].
i=count, ++count;
321 if(rid_map) gs_vec(n?&
rid[0].
p:0,2, gs_sint,gs_add,0, gs_top,buf);
326 static void mat_sort(
struct array *
const mat,
327 const enum mat_order order, buffer *
const buf)
330 case col_major: sarray_sort_4(
struct rnz,mat->ptr,mat->n,
331 j.p,0,j.i,0,
i.p,0,
i.i,0, buf);
break;
332 case row_major: sarray_sort_4(
struct rnz,mat->ptr,mat->n,
333 i.p,0,
i.i,0, j.p,0,j.i,0, buf);
break;
338 static void mat_condense_sorted(
struct array *
const mat)
340 struct rnz *dst,*src, *
const end=(
struct rnz*)mat->ptr+mat->n;
341 if(mat->n<=1)
return;
342 for(dst=mat->ptr;;++dst) {
343 if(dst+1==end)
return;
346 for(src=dst+1;src!=end;++src) {
352 mat->n = (dst+1)-(
struct rnz*)mat->ptr;
355 static void mat_condense(
356 struct array *
const mat,
const enum mat_order order, buffer *
const buf)
358 mat_sort(mat,order,buf); mat_condense_sorted(mat);
361 static void mat_distribute(
362 struct array *
const mat,
const enum distr d,
const enum mat_order o,
363 struct crystal *
const cr)
367 sarray_transfer(
struct rnz,mat, i.p,0, cr);
break;
369 sarray_transfer(
struct rnz,mat,
j.
p,0, cr);
break;
371 mat_condense(mat,o,&cr->data);
374 static void mat_list_nonlocal_sorted(
375 struct array *
const nonlocal_id,
376 const struct array *
const mat,
const enum distr d,
377 const ulong *uid,
struct crystal *
const cr)
379 const uint pid = cr->comm.id;
381 const struct rnz *p, *
const e=(
const struct rnz*)mat->ptr+mat->n;
384 last_rid.p=UINT_MAX,last_rid.i=UINT_MAX; \
385 for(count=0,p=mat->ptr;p!=e;++p) { \
386 if(p->k.p==pid ||
rid_equal(last_rid,p->k)) continue; \
387 last_rid=p->k; ++count; \
390 nonlocal_id->n=count; out=nonlocal_id->ptr; \
391 last_rid.p=UINT_MAX,last_rid.i=UINT_MAX; \
392 for(p=mat->ptr;p!=e;++p) { \
393 if(p->k.p==pid ||
rid_equal(last_rid,p->k)) continue; \
394 (out++)->
rid=last_rid=p->k; \
403 for(out=nonlocal_id->ptr,end=out+nonlocal_id->n;out!=end;++out)
404 out->id=uid[out->rid.i];
406 sarray_sort_2(
struct labelled_rid,nonlocal_id->ptr,nonlocal_id->n,
410 static void mat_list_nonlocal(
411 struct array *
const nonlocal_id,
412 struct array *
const mat,
const enum distr d,
413 const ulong *uid,
struct crystal *
const cr)
419 mat_list_nonlocal_sorted(nonlocal_id,mat,d,uid,cr);
425 uint nz,
const uint *Ai,
const uint *Aj,
const double *Av,
426 const uint null_space,
const struct comm *comm,
429 fail(1,__FILE__,__LINE__,
"recompile with HYPRE support.");
436 fail(1,__FILE__,__LINE__,
"recompile with HYPRE support.");
444 fail(1,__FILE__,__LINE__,
"recompile with HYPRE support.");
#define nz_pos_equal(a, b)
void ccrs_hypre_free(struct hypre_crs_data *data)
struct hypre_crs_data * ccrs_hypre_setup(uint n, const ulong *id, uint nz, const uint *Ai, const uint *Aj, const double *Av, const uint null_space, const struct comm *comm, const double *param)
void ccrs_hypre_solve(double *x, struct hypre_crs_data *data, double *b)
void build_hypre_matrix(struct hypre_crs_data *hypre_data, uint n, const ulong *id, uint nz_unassembled, const uint *Ai, const uint *Aj, const double *Av)