37 ConstrainedOperator(CeedOperator oper,
const Array<int> &ess_tdofs_,
40 ~ConstrainedOperator();
41 void Mult(
const Vector& x, Vector& y)
const;
42 CeedOperator GetCeedOperator()
const;
43 const Array<int> &GetEssentialTrueDofs()
const;
48 ceed::Operator *unconstrained_op;
52ConstrainedOperator::ConstrainedOperator(
54 const Array<int> &ess_tdofs_,
56 : ess_tdofs(ess_tdofs_), P(P_)
58 unconstrained_op =
new ceed::Operator(oper);
60 height = width = rap->
Height();
61 bool own_rap = (rap != unconstrained_op);
65ConstrainedOperator::ConstrainedOperator(CeedOperator oper,
67 : ConstrainedOperator(oper, Array<int>(), P_)
70ConstrainedOperator::~ConstrainedOperator()
72 delete constrained_op;
73 delete unconstrained_op;
76void ConstrainedOperator::Mult(
const Vector& x, Vector& y)
const
78 constrained_op->Mult(x, y);
81CeedOperator ConstrainedOperator::GetCeedOperator()
const
83 return unconstrained_op->GetCeedOperator();
86const Array<int> &ConstrainedOperator::GetEssentialTrueDofs()
const
100 CeedSize in_len, out_len;
101 int ierr = CeedOperatorGetActiveVectorLengths(oper, &in_len, &out_len);
103 *size = (CeedInt)in_len;
104 MFEM_VERIFY(in_len == out_len,
"not a square CeedOperator");
105 MFEM_VERIFY(in_len == *size,
"size overflow");
112 CeedOperator ceed_op = op.GetCeedOperator();
113 const Array<int> &ess_tdofs = op.GetEssentialTrueDofs();
119 ierr = CeedVectorCreate(internal::ceed, length, &diagceed); PCeedChk(ierr);
121 ierr = CeedGetPreferredMemType(internal::ceed, &mem); PCeedChk(ierr);
122 if (!Device::Allows(Backend::CUDA) || mem != CEED_MEM_DEVICE)
126 Vector local_diag(length);
127 CeedScalar *ptr = (mem == CEED_MEM_HOST) ? local_diag.
HostWrite() :
128 local_diag.
Write(
true);
129 ierr = CeedVectorSetArray(diagceed, mem, CEED_USE_POINTER, ptr);
131 ierr = CeedOperatorLinearAssembleDiagonal(ceed_op, diagceed,
132 CEED_REQUEST_IMMEDIATE);
134 ierr = CeedVectorTakeArray(diagceed, mem, NULL); PCeedChk(ierr);
149 const int cheb_order = 3;
154 const double jacobi_scale = 0.65;
157 ierr = CeedVectorDestroy(&diagceed); PCeedChk(ierr);
164class AssembledAMG :
public Solver
169 MFEM_ASSERT(P != NULL,
"Provided HypreParMatrix is invalid!");
170 height = width = oper.Height();
173 const Array<int> ess_tdofs = oper.GetEssentialTrueDofs();
175 ierr = CeedOperatorFullAssemble(oper.GetCeedOperator(), &mat_local);
181 op_assembled =
RAP(&hypre_local, P);
183 HypreParMatrix *mat_e = op_assembled->EliminateRowsCols(ess_tdofs);
185 amg =
new HypreBoomerAMG(*op_assembled);
186 amg->SetPrintLevel(0);
189 void Mult(
const Vector &x, Vector &y)
const override { amg->Mult(x, y); }
197 SparseMatrix *mat_local;
198 HypreParMatrix *op_assembled;
209 ho_boundary_ones = 0.0;
210 const int *ho_ess_tdofs_h = ho_ess_tdofs.
HostRead();
211 for (
int i=0; i<ho_ess_tdofs.
Size(); ++i)
213 ho_boundary_ones[ho_ess_tdofs_h[i]] = 1.0;
217 auto lobo = lo_boundary_ones.
HostRead();
218 for (
int i = 0; i < lo_boundary_ones.
Size(); ++i)
222 alg_lo_ess_tdofs.
Append(i);
235 MFEM_ABORT(
"This integrator does not support Ceed!");
243 ierr = CeedOperatorCreateComposite(internal::ceed, &op); PCeedChk(ierr);
245 MFEM_VERIFY(form.
GetBBFI()->Size() == 0,
246 "Not implemented for this integrator!");
247 MFEM_VERIFY(form.
GetFBFI()->Size() == 0,
248 "Not implemented for this integrator!");
249 MFEM_VERIFY(form.
GetBFBFI()->Size() == 0,
250 "Not implemented for this integrator!");
254 for (
int i = 0; i < bffis->
Size(); ++i)
263 CeedElemRestriction er,
270 ierr = CeedOperatorIsComposite(op, &isComposite); PCeedChk(ierr);
271 MFEM_ASSERT(isComposite,
"");
273 CeedOperator op_coarse;
274 ierr = CeedOperatorCreateComposite(internal::ceed,
275 &op_coarse); PCeedChk(ierr);
278 CeedOperator *subops;
279 ierr = CeedOperatorCompositeGetNumSub(op, &nsub); PCeedChk(ierr);
280 ierr = CeedOperatorCompositeGetSubList(op, &subops); PCeedChk(ierr);
281 for (
int isub=0; isub<nsub; ++isub)
283 CeedOperator subop = subops[isub];
284 CeedBasis basis_coarse, basis_c2f;
285 CeedOperator subop_coarse;
287 &basis_c2f, &subop_coarse); PCeedChk(ierr);
290 ierr = CeedBasisDestroy(&basis_coarse); PCeedChk(ierr);
291 ierr = CeedBasisDestroy(&basis_c2f); PCeedChk(ierr);
292 ierr = CeedOperatorCompositeAddSub(op_coarse, subop_coarse);
294 ierr = CeedOperatorDestroy(&subop_coarse); PCeedChk(ierr);
299AlgebraicMultigrid::AlgebraicMultigrid(
306 ceed_operators.
SetSize(nlevels);
315 for (
int ilevel=nlevels-2; ilevel>=0; --ilevel)
319 ceed_operators[ilevel+1],
space.GetCeedElemRestriction(),
320 space.GetCeedCoarseToFine(),
space.GetOrderReduction());
328 for (
int ilevel=0; ilevel<nlevels; ++ilevel)
332 ConstrainedOperator *op =
new ConstrainedOperator(
352 if (P_mat) { smoother =
new AssembledAMG(*op, P_mat); }
368int AlgebraicInterpolation::Initialize(
369 Ceed ceed, CeedBasis basisctof,
370 CeedElemRestriction erestrictu_coarse, CeedElemRestriction erestrictu_fine)
375 ierr = CeedElemRestrictionGetLVectorSize(erestrictu_coarse, &
width);
377 ierr = CeedElemRestrictionGetLVectorSize(erestrictu_fine, &
height);
381 const int bp3_ncompu = 1;
382 CeedQFunction l_qf_restrict, l_qf_prolong;
383 ierr = CeedQFunctionCreateIdentity(ceed, bp3_ncompu, CEED_EVAL_NONE,
384 CEED_EVAL_INTERP, &l_qf_restrict); PCeedChk(ierr);
385 ierr = CeedQFunctionCreateIdentity(ceed, bp3_ncompu, CEED_EVAL_INTERP,
386 CEED_EVAL_NONE, &l_qf_prolong); PCeedChk(ierr);
388 qf_restrict = l_qf_restrict;
389 qf_prolong = l_qf_prolong;
391 CeedVector c_fine_multiplicity;
392 ierr = CeedVectorCreate(ceed,
height, &c_fine_multiplicity); PCeedChk(ierr);
393 ierr = CeedVectorSetValue(c_fine_multiplicity, 0.0); PCeedChk(ierr);
397 ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE,
398 CEED_QFUNCTION_NONE, &op_restrict); PCeedChk(ierr);
399 ierr = CeedOperatorSetField(op_restrict,
"input", erestrictu_fine,
400 CEED_BASIS_NONE, CEED_VECTOR_ACTIVE); PCeedChk(ierr);
401 ierr = CeedOperatorSetField(op_restrict,
"output", erestrictu_coarse,
402 basisctof, CEED_VECTOR_ACTIVE); PCeedChk(ierr);
406 ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE,
407 CEED_QFUNCTION_NONE, &op_interp); PCeedChk(ierr);
408 ierr = CeedOperatorSetField(op_interp,
"input", erestrictu_coarse,
409 basisctof, CEED_VECTOR_ACTIVE); PCeedChk(ierr);
410 ierr = CeedOperatorSetField(op_interp,
"output", erestrictu_fine,
411 CEED_BASIS_NONE, CEED_VECTOR_ACTIVE); PCeedChk(ierr);
413 ierr = CeedElemRestrictionGetMultiplicity(erestrictu_fine,
414 c_fine_multiplicity); PCeedChk(ierr);
415 ierr = CeedVectorCreate(ceed,
height, &fine_multiplicity_r); PCeedChk(ierr);
417 CeedScalar* fine_r_data;
418 const CeedScalar* fine_data;
419 ierr = CeedVectorGetArrayWrite(fine_multiplicity_r, CEED_MEM_HOST,
420 &fine_r_data); PCeedChk(ierr);
421 ierr = CeedVectorGetArrayRead(c_fine_multiplicity, CEED_MEM_HOST,
422 &fine_data); PCeedChk(ierr);
423 for (CeedSize i = 0; i <
height; ++i)
425 fine_r_data[i] = 1.0 / fine_data[i];
428 ierr = CeedVectorRestoreArray(fine_multiplicity_r, &fine_r_data);
430 ierr = CeedVectorRestoreArrayRead(c_fine_multiplicity, &fine_data);
432 ierr = CeedVectorDestroy(&c_fine_multiplicity); PCeedChk(ierr);
434 ierr = CeedVectorCreate(ceed,
height, &fine_work); PCeedChk(ierr);
436 ierr = CeedVectorCreate(ceed,
height, &v_); PCeedChk(ierr);
437 ierr = CeedVectorCreate(ceed,
width, &u_); PCeedChk(ierr);
442int AlgebraicInterpolation::Finalize()
446 ierr = CeedQFunctionDestroy(&qf_restrict); PCeedChk(ierr);
447 ierr = CeedQFunctionDestroy(&qf_prolong); PCeedChk(ierr);
448 ierr = CeedOperatorDestroy(&op_interp); PCeedChk(ierr);
449 ierr = CeedOperatorDestroy(&op_restrict); PCeedChk(ierr);
450 ierr = CeedVectorDestroy(&fine_multiplicity_r); PCeedChk(ierr);
451 ierr = CeedVectorDestroy(&fine_work); PCeedChk(ierr);
457 Ceed ceed, CeedBasis basisctof,
458 CeedElemRestriction erestrictu_coarse,
459 CeedElemRestriction erestrictu_fine)
462 CeedSize lo_nldofs, ho_nldofs;
463 ierr = CeedElemRestrictionGetLVectorSize(erestrictu_coarse, &lo_nldofs);
465 ierr = CeedElemRestrictionGetLVectorSize(erestrictu_fine,
466 &ho_nldofs); PCeedChk(ierr);
468 width = (int)lo_nldofs;
469 MFEM_VERIFY(ho_nldofs ==
height,
"height overflow");
470 MFEM_VERIFY(lo_nldofs ==
width,
"width overflow");
472 ierr = Initialize(ceed, basisctof, erestrictu_coarse, erestrictu_fine);
479 ierr = CeedVectorDestroy(&v_); PCeedChk(ierr);
480 ierr = CeedVectorDestroy(&u_); PCeedChk(ierr);
483 ierr = CeedBasisDestroy(&basisctof_); PCeedChk(ierr);
494 CeedVectorGetCeed(
a, &ceed);
496 CeedSize length, length2;
497 ierr = CeedVectorGetLength(
a, &length); PCeedChk(ierr);
498 ierr = CeedVectorGetLength(
b, &length2); PCeedChk(ierr);
499 if (length != length2)
501 return CeedError(ceed, 1,
"Vector sizes don't match");
507 mem = CEED_MEM_DEVICE;
514 const CeedScalar *b_data;
515 ierr = CeedVectorGetArray(
a, mem, &a_data); PCeedChk(ierr);
516 ierr = CeedVectorGetArrayRead(
b, mem, &b_data); PCeedChk(ierr);
517 MFEM_VERIFY(
int(length) == length,
"length overflow");
519 {a_data[i] *= b_data[i];});
521 ierr = CeedVectorRestoreArray(
a, &a_data); PCeedChk(ierr);
522 ierr = CeedVectorRestoreArrayRead(
b, &b_data); PCeedChk(ierr);
530 const CeedScalar *in_ptr;
533 ierr = CeedGetPreferredMemType(internal::ceed, &mem); PCeedChk(ierr);
545 ierr = CeedVectorSetArray(u_, mem, CEED_USE_POINTER,
546 const_cast<CeedScalar*
>(in_ptr)); PCeedChk(ierr);
547 ierr = CeedVectorSetArray(v_, mem, CEED_USE_POINTER,
548 out_ptr); PCeedChk(ierr);
550 ierr = CeedOperatorApply(op_interp, u_, v_,
551 CEED_REQUEST_IMMEDIATE); PCeedChk(ierr);
554 ierr = CeedVectorTakeArray(u_, mem,
const_cast<CeedScalar**
>(&in_ptr));
556 ierr = CeedVectorTakeArray(v_, mem, &out_ptr); PCeedChk(ierr);
564 ierr = CeedGetPreferredMemType(internal::ceed, &mem); PCeedChk(ierr);
565 const CeedScalar *in_ptr;
578 ierr = CeedVectorSetArray(v_, mem, CEED_USE_POINTER,
579 const_cast<CeedScalar*
>(in_ptr)); PCeedChk(ierr);
580 ierr = CeedVectorSetArray(u_, mem, CEED_USE_POINTER,
581 out_ptr); PCeedChk(ierr);
584 ierr = CeedVectorGetLength(v_, &length); PCeedChk(ierr);
586 const CeedScalar *multiplicitydata;
587 CeedScalar *workdata;
588 ierr = CeedVectorGetArrayRead(fine_multiplicity_r, mem,
589 &multiplicitydata); PCeedChk(ierr);
590 ierr = CeedVectorGetArrayWrite(fine_work, mem, &workdata); PCeedChk(ierr);
591 MFEM_VERIFY((
int)length == length,
"length overflow");
593 {workdata[i] = in_ptr[i] * multiplicitydata[i];});
594 ierr = CeedVectorRestoreArrayRead(fine_multiplicity_r,
596 ierr = CeedVectorRestoreArray(fine_work, &workdata); PCeedChk(ierr);
598 ierr = CeedOperatorApply(op_restrict, fine_work, u_,
599 CEED_REQUEST_IMMEDIATE); PCeedChk(ierr);
601 ierr = CeedVectorTakeArray(v_, mem,
const_cast<CeedScalar**
>(&in_ptr));
603 ierr = CeedVectorTakeArray(u_, mem, &out_ptr); PCeedChk(ierr);
610 int current_order = order;
611 while (current_order > 0)
614 current_order = current_order/2;
629 ceed_interpolations.SetSize(nlevels-1);
630 R_tr.SetSize(nlevels-1);
634 current_order = order;
636 Ceed ceed = internal::ceed;
638 CeedElemRestriction er = fine_er;
650 for (
int ilevel=nlevels-2; ilevel>=0; --ilevel)
652 const int order_reduction = current_order - (current_order/2);
659 *
fespaces[ilevel+1], er, current_order,
dim, order_reduction, gc);
667 *
fespaces[ilevel+1], er, current_order,
dim, order_reduction);
669 current_order = current_order/2;
673 space->GetCeedCoarseToFine(),
674 space->GetCeedElemRestriction(),
686 prolongations[ilevel] = ceed_interpolations[ilevel]->SetupRAP(
687 space->GetProlongationMatrix(), R_tr[ilevel]);
691 er =
space->GetCeedElemRestriction();
697 CeedElemRestriction fine_er,
701) : order_reduction(order_reduction_)
716 MFEM_VERIFY(
ndofs == ndofs_,
"ndofs overflow");
733 CeedElemRestriction fine_er,
736 int order_reduction_,
744 MFEM_VERIFY((
int)lsize == lsize,
"size overflow");
751 group_ldof.
MakeI(group_ldof_fine.
Size());
752 for (
int g=1; g<group_ldof_fine.
Size(); ++g)
754 int nldof_fine_g = group_ldof_fine.
RowSize(g);
755 const int *ldof_fine_g = group_ldof_fine.
GetRow(g);
756 for (
int i=0; i<nldof_fine_g; ++i)
758 int icoarse =
dof_map[ldof_fine_g[i]];
762 ldof_group[icoarse] = g;
767 for (
int g=1; g<group_ldof_fine.
Size(); ++g)
769 int nldof_fine_g = group_ldof_fine.
RowSize(g);
770 const int *ldof_fine_g = group_ldof_fine.
GetRow(g);
771 for (
int i=0; i<nldof_fine_g; ++i)
773 int icoarse =
dof_map[ldof_fine_g[i]];
785 for (
int i=0; i<lsize; ++i)
787 int g = ldof_group[i];
790 ldof_ltdof[i] = ltsize;
795 gc->
Bcast(ldof_ltdof);