83 CeedElemRestriction er_in,
84 CeedElemRestriction* er_out,
89 ierr = CeedElemRestrictionGetCeed(er_in, &ceed); PCeedChk(ierr);
91 CeedInt numelem, numcomp, elemsize;
93 ierr = CeedElemRestrictionGetNumElements(er_in, &numelem); PCeedChk(ierr);
94 ierr = CeedElemRestrictionGetLVectorSize(er_in, &numnodes); PCeedChk(ierr);
95 ierr = CeedElemRestrictionGetElementSize(er_in, &elemsize); PCeedChk(ierr);
96 ierr = CeedElemRestrictionGetNumComponents(er_in, &numcomp); PCeedChk(ierr);
100 return CeedError(ceed, 1,
"Algebraic element restriction not "
101 "implemented for multiple components.");
105 int coarse_P1d = P1d - order_reduction;
106 int dim = (log((
double) elemsize) / log((
double) P1d)) + 1.e-3;
108 CeedVector in_lvec, in_evec;
109 ierr = CeedElemRestrictionCreateVector(er_in, &in_lvec, &in_evec);
114 CeedScalar * lvec_data;
115 ierr = CeedVectorGetArrayWrite(in_lvec, CEED_MEM_HOST, &lvec_data);
117 for (CeedSize i = 0; i < numnodes; ++i)
119 lvec_data[i] = (CeedScalar) i;
121 ierr = CeedVectorRestoreArray(in_lvec, &lvec_data); PCeedChk(ierr);
122 CeedInt in_layout[3];
123#if CEED_VERSION_GE(0, 13, 0)
124 ierr = CeedElemRestrictionGetELayout(er_in, in_layout); PCeedChk(ierr);
126 ierr = CeedElemRestrictionGetELayout(er_in, &in_layout); PCeedChk(ierr);
128 if (in_layout[0] == 0 && in_layout[1] == 0 && in_layout[2] == 0)
130 return CeedError(ceed, 1,
"Cannot interpret e-vector ordering of given"
131 "CeedElemRestriction!");
133 ierr = CeedElemRestrictionApply(er_in, CEED_NOTRANSPOSE, in_lvec, in_evec,
134 CEED_REQUEST_IMMEDIATE); PCeedChk(ierr);
135 ierr = CeedVectorDestroy(&in_lvec); PCeedChk(ierr);
136 const CeedScalar * in_elem_dof;
137 ierr = CeedVectorGetArrayRead(in_evec, CEED_MEM_HOST, &in_elem_dof);
143 dof_map =
new CeedInt[numnodes];
144 for (CeedSize i = 0; i < numnodes; ++i)
148 CeedInt coarse_elemsize = pow(coarse_P1d,
dim);
149 CeedInt * out_elem_dof =
new CeedInt[coarse_elemsize * numelem];
150 const double rounding_guard = 1.e-10;
151 int running_out_ldof_count = 0;
154 for (
int e = 0; e < numelem; ++e)
157 for (
int i = 0; i < P1d; ++i)
159 for (
int j = 0; j < P1d; ++j)
163 int in_edof = i*P1d + j;
164 const int edof_index = in_edof*in_layout[0] + e*in_layout[2];
165 int in_ldof = in_elem_dof[edof_index] + rounding_guard;
166 bool i_edge = (i == 0 || i == P1d - 1);
167 bool j_edge = (j == 0 || j == P1d - 1);
173 int coarse_i, coarse_j;
174 if (i_edge == j_edge)
184 int left_in_edof, left_in_ldof, right_in_edof, right_in_ldof;
187 left_in_edof = i*P1d + 0;
188 right_in_edof = i*P1d + (P1d - 1);
189 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
191 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
194 coarse_j = (left_in_ldof < right_in_ldof) ?
199 left_in_edof = 0*P1d + j;
200 right_in_edof = (P1d - 1)*P1d + j;
201 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
203 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
205 coarse_i = (left_in_ldof < right_in_ldof) ?
212 if (coarse_i >= 0 && coarse_j >= 0)
214 int out_edof = coarse_i*coarse_P1d + coarse_j;
215 if (dof_map[in_ldof] >= 0)
217 out_elem_dof[e*coarse_elemsize + out_edof] = dof_map[in_ldof];
221 out_elem_dof[e*coarse_elemsize + out_edof] = running_out_ldof_count;
222 dof_map[in_ldof] = running_out_ldof_count;
223 running_out_ldof_count++;
233 for (
int e = 0; e < numelem; ++e)
236 for (
int i = 0; i < P1d; ++i)
238 for (
int j = 0; j < P1d; ++j)
240 for (
int k = 0; k < P1d; ++k)
244 int in_edof = i*P1d*P1d + j*P1d + k;
245 int in_ldof = in_elem_dof[in_edof*in_layout[0]+e*in_layout[2]]
247 bool i_edge = (i == 0 || i == P1d - 1);
248 bool j_edge = (j == 0 || j == P1d - 1);
249 bool k_edge = (k == 0 || k == P1d - 1);
251 if (i_edge) { topo++; }
252 if (j_edge) { topo++; }
253 if (k_edge) { topo++; }
259 int coarse_i, coarse_j, coarse_k;
260 if (topo == 0 || topo == 3)
271 int left_in_edof, left_in_ldof, right_in_edof, right_in_ldof;
274 left_in_edof = 0*P1d*P1d + j*P1d + k;
275 right_in_edof = (P1d - 1)*P1d*P1d + j*P1d + k;
276 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
278 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
280 coarse_i = (left_in_ldof < right_in_ldof) ?
287 left_in_edof = i*P1d*P1d + 0*P1d + k;
288 right_in_edof = i*P1d*P1d + (P1d - 1)*P1d + k;
289 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
291 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
294 coarse_j = (left_in_ldof < right_in_ldof) ?
302 return CeedError(ceed, 1,
303 "Element connectivity does not make sense!");
305 left_in_edof = i*P1d*P1d + j*P1d + 0;
306 right_in_edof = i*P1d*P1d + j*P1d + (P1d - 1);
307 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
309 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
313 coarse_k = (left_in_ldof < right_in_ldof) ?
323 return CeedError(ceed, 1,
324 "Element connectivity does not match topology!");
326 int bottom_left_edof, bottom_right_edof, top_left_edof, top_right_edof;
327 int bottom_left_ldof, bottom_right_ldof, top_left_ldof, top_right_ldof;
330 bottom_left_edof = i*P1d*P1d + 0*P1d + 0;
331 bottom_right_edof = i*P1d*P1d + 0*P1d + (P1d - 1);
332 top_right_edof = i*P1d*P1d + (P1d - 1)*P1d + (P1d - 1);
333 top_left_edof = i*P1d*P1d + (P1d - 1)*P1d + 0;
334 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
336 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
338 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
340 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
342 int m =
min4(bottom_left_ldof, bottom_right_ldof, top_right_ldof,
345 if (m == bottom_left_ldof)
350 else if (m == bottom_right_ldof)
355 else if (m == top_right_ldof)
368 bottom_left_edof = 0*P1d*P1d + j*P1d + 0;
369 bottom_right_edof = 0*P1d*P1d + j*P1d + (P1d - 1);
370 top_right_edof = (P1d - 1)*P1d*P1d + j*P1d + (P1d - 1);
371 top_left_edof = (P1d - 1)*P1d*P1d + j*P1d + 0;
372 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
374 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
376 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
378 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
380 int m =
min4(bottom_left_ldof, bottom_right_ldof, top_right_ldof,
383 if (m == bottom_left_ldof)
388 else if (m == bottom_right_ldof)
393 else if (m == top_right_ldof)
408 return CeedError(ceed, 1,
409 "Element connectivity does not make sense!");
411 bottom_left_edof = 0*P1d*P1d + 0*P1d + k;
412 bottom_right_edof = 0*P1d*P1d + (P1d - 1)*P1d + k;
413 top_right_edof = (P1d - 1)*P1d*P1d + (P1d - 1)*P1d + k;
414 top_left_edof = (P1d - 1)*P1d*P1d + 0*P1d + k;
415 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
417 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
419 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
421 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
423 int m =
min4(bottom_left_ldof, bottom_right_ldof,
424 top_right_ldof, top_left_ldof);
426 if (m == bottom_left_ldof)
431 else if (m == bottom_right_ldof)
436 else if (m == top_right_ldof)
450 if (coarse_i >= 0 && coarse_j >= 0 && coarse_k >= 0)
452 int out_edof = coarse_i*coarse_P1d*coarse_P1d + coarse_j*coarse_P1d + coarse_k;
453 if (dof_map[in_ldof] >= 0)
455 out_elem_dof[e*coarse_elemsize + out_edof] = dof_map[in_ldof];
459 out_elem_dof[e*coarse_elemsize + out_edof] = running_out_ldof_count;
460 dof_map[in_ldof] = running_out_ldof_count;
461 running_out_ldof_count++;
472 return CeedError(ceed, 1,
473 "CeedATPMGElemRestriction does not yet support this dimension.");
476 ierr = CeedVectorRestoreArrayRead(in_evec, &in_elem_dof); PCeedChk(ierr);
477 ierr = CeedVectorDestroy(&in_evec); PCeedChk(ierr);
479 ierr = CeedElemRestrictionCreate(ceed, numelem, coarse_elemsize, numcomp,
480 0, running_out_ldof_count,
481 CEED_MEM_HOST, CEED_COPY_VALUES, out_elem_dof,
482 er_out); PCeedChk(ierr);
484 delete [] out_elem_dof;
525 ierr = CeedBasisGetCeed(basisin, &ceed); PCeedChk(ierr);
527 CeedInt
dim, ncomp, P1d, Q1d;
528 ierr = CeedBasisGetDimension(basisin, &
dim); PCeedChk(ierr);
529 ierr = CeedBasisGetNumComponents(basisin, &ncomp); PCeedChk(ierr);
530 ierr = CeedBasisGetNumNodes1D(basisin, &P1d); PCeedChk(ierr);
531 ierr = CeedBasisGetNumQuadraturePoints1D(basisin, &Q1d); PCeedChk(ierr);
533 CeedInt coarse_P1d = P1d - order_reduction;
535 const CeedScalar *interp1d;
536 ierr = CeedBasisGetInterp1D(basisin, &interp1d); PCeedChk(ierr);
537 const CeedScalar * grad1d;
538 ierr = CeedBasisGetGrad1D(basisin, &grad1d); PCeedChk(ierr);
540 CeedScalar * coarse_interp1d =
new CeedScalar[coarse_P1d * Q1d];
541 CeedScalar * coarse_grad1d =
new CeedScalar[coarse_P1d * Q1d];
542 CeedScalar * fine_nodal_points =
new CeedScalar[P1d];
549 ierr = CeedLobattoQuadrature(P1d, fine_nodal_points, NULL); PCeedChk(ierr);
550 for (
int i = 0; i < P1d; ++i)
552 fine_nodal_points[i] = 0.5 * fine_nodal_points[i] + 0.5;
555 const CeedScalar *interp_ctof;
556 ierr = CeedBasisGetInterp1D(basisc2f, &interp_ctof); PCeedChk(ierr);
558 for (
int i = 0; i < Q1d; ++i)
560 for (
int j = 0; j < coarse_P1d; ++j)
562 coarse_interp1d[i * coarse_P1d + j] = 0.0;
563 coarse_grad1d[i * coarse_P1d + j] = 0.0;
564 for (
int k = 0; k < P1d; ++k)
566 coarse_interp1d[i * coarse_P1d + j] += interp_ctof[k * coarse_P1d + j] *
567 interp1d[i * P1d + k];
568 coarse_grad1d[i * coarse_P1d + j] += interp_ctof[k * coarse_P1d + j] *
574 const CeedScalar * qref1d;
575 ierr = CeedBasisGetQRef(basisin, &qref1d); PCeedChk(ierr);
576 const CeedScalar * qweight1d;
577 ierr = CeedBasisGetQWeights(basisin, &qweight1d); PCeedChk(ierr);
578 ierr = CeedBasisCreateTensorH1(ceed,
dim, ncomp,
579 coarse_P1d, Q1d, coarse_interp1d, coarse_grad1d,
580 qref1d, qweight1d, basisout); PCeedChk(ierr);
582 delete [] fine_nodal_points;
583 delete [] coarse_interp1d;
584 delete [] coarse_grad1d;
590 CeedElemRestriction coarse_er,
591 CeedBasis coarse_basis_in,
592 CeedBasis basis_ctof_in,
595 (void)order_reduction;
600 ierr = CeedOperatorGetCeed(oper, &ceed); PCeedChk(ierr);
603 ierr = CeedOperatorGetQFunction(oper, &qf); PCeedChk(ierr);
604 CeedInt numinputfields, numoutputfields;
605 CeedQFunctionField *inputqfields, *outputqfields;
606 ierr = CeedQFunctionGetFields(qf, &numinputfields, &inputqfields,
607 &numoutputfields, &outputqfields);
609 CeedOperatorField *inputfields, *outputfields;
610 ierr = CeedOperatorGetFields(oper, &numinputfields, &inputfields,
611 &numoutputfields, &outputfields);
614 CeedElemRestriction * er_input =
new CeedElemRestriction[numinputfields];
615 CeedElemRestriction * er_output =
new CeedElemRestriction[numoutputfields];
616 CeedVector * if_vector =
new CeedVector[numinputfields];
617 CeedVector * of_vector =
new CeedVector[numoutputfields];
618 CeedBasis * basis_input =
new CeedBasis[numinputfields];
619 CeedBasis * basis_output =
new CeedBasis[numoutputfields];
620 CeedBasis cbasis = coarse_basis_in;
622 int active_input_basis = -1;
623 for (
int i = 0; i < numinputfields; ++i)
625 ierr = CeedOperatorFieldGetElemRestriction(inputfields[i],
626 &er_input[i]); PCeedChk(ierr);
627 ierr = CeedOperatorFieldGetVector(inputfields[i], &if_vector[i]);
629 ierr = CeedOperatorFieldGetBasis(inputfields[i], &basis_input[i]);
631 if (if_vector[i] == CEED_VECTOR_ACTIVE)
633 if (active_input_basis < 0)
635 active_input_basis = i;
637 else if (basis_input[i] != basis_input[active_input_basis])
639 return CeedError(ceed, 1,
"Two different active input basis!");
643 for (
int i = 0; i < numoutputfields; ++i)
645 ierr = CeedOperatorFieldGetElemRestriction(outputfields[i],
646 &er_output[i]); PCeedChk(ierr);
647 ierr = CeedOperatorFieldGetVector(outputfields[i], &of_vector[i]);
649 ierr = CeedOperatorFieldGetBasis(outputfields[i], &basis_output[i]);
651 if (of_vector[i] == CEED_VECTOR_ACTIVE)
654 if (basis_output[i] != basis_input[active_input_basis])
656 return CeedError(ceed, 1,
"Input and output basis do not match!");
658 if (er_output[i] != er_input[active_input_basis])
660 return CeedError(ceed, 1,
"Input and output elem-restriction do not match!");
666 ierr = CeedOperatorCreate(ceed, qf, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
667 &coper); PCeedChk(ierr);
669 for (
int i = 0; i < numinputfields; ++i)
671#if CEED_VERSION_GE(0, 13, 0)
672 const char * fieldname;
676 ierr = CeedQFunctionFieldGetName(inputqfields[i], &fieldname); PCeedChk(ierr);
677 if (if_vector[i] == CEED_VECTOR_ACTIVE)
679 ierr = CeedOperatorSetField(coper, fieldname, coarse_er, cbasis,
680 if_vector[i]); PCeedChk(ierr);
684 ierr = CeedOperatorSetField(coper, fieldname, er_input[i], basis_input[i],
685 if_vector[i]); PCeedChk(ierr);
687#if CEED_VERSION_GE(0, 13, 0)
688 ierr = CeedVectorDestroy(&if_vector[i]); PCeedChk(ierr);
689 ierr = CeedElemRestrictionDestroy(&er_input[i]); PCeedChk(ierr);
690 ierr = CeedBasisDestroy(&basis_input[i]); PCeedChk(ierr);
693 for (
int i = 0; i < numoutputfields; ++i)
695#if CEED_VERSION_GE(0, 13, 0)
696 const char * fieldname;
700 ierr = CeedQFunctionFieldGetName(outputqfields[i], &fieldname); PCeedChk(ierr);
701 if (of_vector[i] == CEED_VECTOR_ACTIVE)
703 ierr = CeedOperatorSetField(coper, fieldname, coarse_er, cbasis,
704 of_vector[i]); PCeedChk(ierr);
708 ierr = CeedOperatorSetField(coper, fieldname, er_output[i], basis_output[i],
709 of_vector[i]); PCeedChk(ierr);
711#if CEED_VERSION_GE(0, 13, 0)
712 ierr = CeedVectorDestroy(&of_vector[i]); PCeedChk(ierr);
713 ierr = CeedElemRestrictionDestroy(&er_output[i]); PCeedChk(ierr);
714 ierr = CeedBasisDestroy(&basis_output[i]); PCeedChk(ierr);
721 delete [] basis_input;
722 delete [] basis_output;