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 ierr = CeedElemRestrictionGetELayout(er_in, &in_layout); PCeedChk(ierr);
124 if (in_layout[0] == 0 && in_layout[1] == 0 && in_layout[2] == 0)
126 return CeedError(ceed, 1,
"Cannot interpret e-vector ordering of given"
127 "CeedElemRestriction!");
129 ierr = CeedElemRestrictionApply(er_in, CEED_NOTRANSPOSE, in_lvec, in_evec,
130 CEED_REQUEST_IMMEDIATE); PCeedChk(ierr);
131 ierr = CeedVectorDestroy(&in_lvec); PCeedChk(ierr);
132 const CeedScalar * in_elem_dof;
133 ierr = CeedVectorGetArrayRead(in_evec, CEED_MEM_HOST, &in_elem_dof);
139 dof_map =
new CeedInt[numnodes];
140 for (CeedSize i = 0; i < numnodes; ++i)
144 CeedInt coarse_elemsize = pow(coarse_P1d,
dim);
145 CeedInt * out_elem_dof =
new CeedInt[coarse_elemsize * numelem];
146 const double rounding_guard = 1.e-10;
147 int running_out_ldof_count = 0;
150 for (
int e = 0; e < numelem; ++e)
153 for (
int i = 0; i < P1d; ++i)
155 for (
int j = 0; j < P1d; ++j)
159 int in_edof = i*P1d + j;
160 const int edof_index = in_edof*in_layout[0] + e*in_layout[2];
161 int in_ldof = in_elem_dof[edof_index] + rounding_guard;
162 bool i_edge = (i == 0 || i == P1d - 1);
163 bool j_edge = (j == 0 || j == P1d - 1);
169 int coarse_i, coarse_j;
170 if (i_edge == j_edge)
180 int left_in_edof, left_in_ldof, right_in_edof, right_in_ldof;
183 left_in_edof = i*P1d + 0;
184 right_in_edof = i*P1d + (P1d - 1);
185 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
187 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
190 coarse_j = (left_in_ldof < right_in_ldof) ?
195 left_in_edof = 0*P1d + j;
196 right_in_edof = (P1d - 1)*P1d + j;
197 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
199 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
201 coarse_i = (left_in_ldof < right_in_ldof) ?
208 if (coarse_i >= 0 && coarse_j >= 0)
210 int out_edof = coarse_i*coarse_P1d + coarse_j;
211 if (dof_map[in_ldof] >= 0)
213 out_elem_dof[e*coarse_elemsize + out_edof] = dof_map[in_ldof];
217 out_elem_dof[e*coarse_elemsize + out_edof] = running_out_ldof_count;
218 dof_map[in_ldof] = running_out_ldof_count;
219 running_out_ldof_count++;
229 for (
int e = 0; e < numelem; ++e)
232 for (
int i = 0; i < P1d; ++i)
234 for (
int j = 0; j < P1d; ++j)
236 for (
int k = 0; k < P1d; ++k)
240 int in_edof = i*P1d*P1d + j*P1d + k;
241 int in_ldof = in_elem_dof[in_edof*in_layout[0]+e*in_layout[2]]
243 bool i_edge = (i == 0 || i == P1d - 1);
244 bool j_edge = (j == 0 || j == P1d - 1);
245 bool k_edge = (k == 0 || k == P1d - 1);
247 if (i_edge) { topo++; }
248 if (j_edge) { topo++; }
249 if (k_edge) { topo++; }
255 int coarse_i, coarse_j, coarse_k;
256 if (topo == 0 || topo == 3)
267 int left_in_edof, left_in_ldof, right_in_edof, right_in_ldof;
270 left_in_edof = 0*P1d*P1d + j*P1d + k;
271 right_in_edof = (P1d - 1)*P1d*P1d + j*P1d + k;
272 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
274 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
276 coarse_i = (left_in_ldof < right_in_ldof) ?
283 left_in_edof = i*P1d*P1d + 0*P1d + k;
284 right_in_edof = i*P1d*P1d + (P1d - 1)*P1d + k;
285 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
287 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
290 coarse_j = (left_in_ldof < right_in_ldof) ?
298 return CeedError(ceed, 1,
299 "Element connectivity does not make sense!");
301 left_in_edof = i*P1d*P1d + j*P1d + 0;
302 right_in_edof = i*P1d*P1d + j*P1d + (P1d - 1);
303 left_in_ldof = in_elem_dof[left_in_edof*in_layout[0]+e*in_layout[2]]
305 right_in_ldof = in_elem_dof[right_in_edof*in_layout[0]+e*in_layout[2]]
309 coarse_k = (left_in_ldof < right_in_ldof) ?
319 return CeedError(ceed, 1,
320 "Element connectivity does not match topology!");
322 int bottom_left_edof, bottom_right_edof, top_left_edof, top_right_edof;
323 int bottom_left_ldof, bottom_right_ldof, top_left_ldof, top_right_ldof;
326 bottom_left_edof = i*P1d*P1d + 0*P1d + 0;
327 bottom_right_edof = i*P1d*P1d + 0*P1d + (P1d - 1);
328 top_right_edof = i*P1d*P1d + (P1d - 1)*P1d + (P1d - 1);
329 top_left_edof = i*P1d*P1d + (P1d - 1)*P1d + 0;
330 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
332 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
334 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
336 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
338 int m =
min4(bottom_left_ldof, bottom_right_ldof, top_right_ldof,
341 if (m == bottom_left_ldof)
346 else if (m == bottom_right_ldof)
351 else if (m == top_right_ldof)
364 bottom_left_edof = 0*P1d*P1d + j*P1d + 0;
365 bottom_right_edof = 0*P1d*P1d + j*P1d + (P1d - 1);
366 top_right_edof = (P1d - 1)*P1d*P1d + j*P1d + (P1d - 1);
367 top_left_edof = (P1d - 1)*P1d*P1d + j*P1d + 0;
368 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
370 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
372 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
374 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
376 int m =
min4(bottom_left_ldof, bottom_right_ldof, top_right_ldof,
379 if (m == bottom_left_ldof)
384 else if (m == bottom_right_ldof)
389 else if (m == top_right_ldof)
404 return CeedError(ceed, 1,
405 "Element connectivity does not make sense!");
407 bottom_left_edof = 0*P1d*P1d + 0*P1d + k;
408 bottom_right_edof = 0*P1d*P1d + (P1d - 1)*P1d + k;
409 top_right_edof = (P1d - 1)*P1d*P1d + (P1d - 1)*P1d + k;
410 top_left_edof = (P1d - 1)*P1d*P1d + 0*P1d + k;
411 bottom_left_ldof = in_elem_dof[bottom_left_edof*in_layout[0]+e*in_layout[2]]
413 bottom_right_ldof = in_elem_dof[bottom_right_edof*in_layout[0]+e*in_layout[2]]
415 top_right_ldof = in_elem_dof[top_right_edof*in_layout[0]+e*in_layout[2]]
417 top_left_ldof = in_elem_dof[top_left_edof*in_layout[0]+e*in_layout[2]]
419 int m =
min4(bottom_left_ldof, bottom_right_ldof,
420 top_right_ldof, top_left_ldof);
422 if (m == bottom_left_ldof)
427 else if (m == bottom_right_ldof)
432 else if (m == top_right_ldof)
446 if (coarse_i >= 0 && coarse_j >= 0 && coarse_k >= 0)
448 int out_edof = coarse_i*coarse_P1d*coarse_P1d + coarse_j*coarse_P1d + coarse_k;
449 if (dof_map[in_ldof] >= 0)
451 out_elem_dof[e*coarse_elemsize + out_edof] = dof_map[in_ldof];
455 out_elem_dof[e*coarse_elemsize + out_edof] = running_out_ldof_count;
456 dof_map[in_ldof] = running_out_ldof_count;
457 running_out_ldof_count++;
468 return CeedError(ceed, 1,
469 "CeedATPMGElemRestriction does not yet support this dimension.");
472 ierr = CeedVectorRestoreArrayRead(in_evec, &in_elem_dof); PCeedChk(ierr);
473 ierr = CeedVectorDestroy(&in_evec); PCeedChk(ierr);
475 ierr = CeedElemRestrictionCreate(ceed, numelem, coarse_elemsize, numcomp,
476 0, running_out_ldof_count,
477 CEED_MEM_HOST, CEED_COPY_VALUES, out_elem_dof,
478 er_out); PCeedChk(ierr);
480 delete [] out_elem_dof;
521 ierr = CeedBasisGetCeed(basisin, &ceed); PCeedChk(ierr);
523 CeedInt
dim, ncomp, P1d, Q1d;
524 ierr = CeedBasisGetDimension(basisin, &
dim); PCeedChk(ierr);
525 ierr = CeedBasisGetNumComponents(basisin, &ncomp); PCeedChk(ierr);
526 ierr = CeedBasisGetNumNodes1D(basisin, &P1d); PCeedChk(ierr);
527 ierr = CeedBasisGetNumQuadraturePoints1D(basisin, &Q1d); PCeedChk(ierr);
529 CeedInt coarse_P1d = P1d - order_reduction;
531 const CeedScalar *interp1d;
532 ierr = CeedBasisGetInterp1D(basisin, &interp1d); PCeedChk(ierr);
533 const CeedScalar * grad1d;
534 ierr = CeedBasisGetGrad1D(basisin, &grad1d); PCeedChk(ierr);
536 CeedScalar * coarse_interp1d =
new CeedScalar[coarse_P1d * Q1d];
537 CeedScalar * coarse_grad1d =
new CeedScalar[coarse_P1d * Q1d];
538 CeedScalar * fine_nodal_points =
new CeedScalar[P1d];
545 ierr = CeedLobattoQuadrature(P1d, fine_nodal_points, NULL); PCeedChk(ierr);
546 for (
int i = 0; i < P1d; ++i)
548 fine_nodal_points[i] = 0.5 * fine_nodal_points[i] + 0.5;
551 const CeedScalar *interp_ctof;
552 ierr = CeedBasisGetInterp1D(basisc2f, &interp_ctof); PCeedChk(ierr);
554 for (
int i = 0; i < Q1d; ++i)
556 for (
int j = 0; j < coarse_P1d; ++j)
558 coarse_interp1d[i * coarse_P1d + j] = 0.0;
559 coarse_grad1d[i * coarse_P1d + j] = 0.0;
560 for (
int k = 0; k < P1d; ++k)
562 coarse_interp1d[i * coarse_P1d + j] += interp_ctof[k * coarse_P1d + j] *
563 interp1d[i * P1d + k];
564 coarse_grad1d[i * coarse_P1d + j] += interp_ctof[k * coarse_P1d + j] *
570 const CeedScalar * qref1d;
571 ierr = CeedBasisGetQRef(basisin, &qref1d); PCeedChk(ierr);
572 const CeedScalar * qweight1d;
573 ierr = CeedBasisGetQWeights(basisin, &qweight1d); PCeedChk(ierr);
574 ierr = CeedBasisCreateTensorH1(ceed,
dim, ncomp,
575 coarse_P1d, Q1d, coarse_interp1d, coarse_grad1d,
576 qref1d, qweight1d, basisout); PCeedChk(ierr);
578 delete [] fine_nodal_points;
579 delete [] coarse_interp1d;
580 delete [] coarse_grad1d;
586 CeedElemRestriction coarse_er,
587 CeedBasis coarse_basis_in,
588 CeedBasis basis_ctof_in,
591 (void)order_reduction;
596 ierr = CeedOperatorGetCeed(oper, &ceed); PCeedChk(ierr);
599 ierr = CeedOperatorGetQFunction(oper, &qf); PCeedChk(ierr);
600 CeedInt numinputfields, numoutputfields;
601 CeedQFunctionField *inputqfields, *outputqfields;
602 ierr = CeedQFunctionGetFields(qf, &numinputfields, &inputqfields,
603 &numoutputfields, &outputqfields);
605 CeedOperatorField *inputfields, *outputfields;
606 ierr = CeedOperatorGetFields(oper, &numinputfields, &inputfields,
607 &numoutputfields, &outputfields);
610 CeedElemRestriction * er_input =
new CeedElemRestriction[numinputfields];
611 CeedElemRestriction * er_output =
new CeedElemRestriction[numoutputfields];
612 CeedVector * if_vector =
new CeedVector[numinputfields];
613 CeedVector * of_vector =
new CeedVector[numoutputfields];
614 CeedBasis * basis_input =
new CeedBasis[numinputfields];
615 CeedBasis * basis_output =
new CeedBasis[numoutputfields];
616 CeedBasis cbasis = coarse_basis_in;
618 int active_input_basis = -1;
619 for (
int i = 0; i < numinputfields; ++i)
621 ierr = CeedOperatorFieldGetElemRestriction(inputfields[i],
622 &er_input[i]); PCeedChk(ierr);
623 ierr = CeedOperatorFieldGetVector(inputfields[i], &if_vector[i]);
625 ierr = CeedOperatorFieldGetBasis(inputfields[i], &basis_input[i]);
627 if (if_vector[i] == CEED_VECTOR_ACTIVE)
629 if (active_input_basis < 0)
631 active_input_basis = i;
633 else if (basis_input[i] != basis_input[active_input_basis])
635 return CeedError(ceed, 1,
"Two different active input basis!");
639 for (
int i = 0; i < numoutputfields; ++i)
641 ierr = CeedOperatorFieldGetElemRestriction(outputfields[i],
642 &er_output[i]); PCeedChk(ierr);
643 ierr = CeedOperatorFieldGetVector(outputfields[i], &of_vector[i]);
645 ierr = CeedOperatorFieldGetBasis(outputfields[i], &basis_output[i]);
647 if (of_vector[i] == CEED_VECTOR_ACTIVE)
650 if (basis_output[i] != basis_input[active_input_basis])
652 return CeedError(ceed, 1,
"Input and output basis do not match!");
654 if (er_output[i] != er_input[active_input_basis])
656 return CeedError(ceed, 1,
"Input and output elem-restriction do not match!");
662 ierr = CeedOperatorCreate(ceed, qf, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
663 &coper); PCeedChk(ierr);
665 for (
int i = 0; i < numinputfields; ++i)
668 ierr = CeedQFunctionFieldGetName(inputqfields[i], &fieldname); PCeedChk(ierr);
669 if (if_vector[i] == CEED_VECTOR_ACTIVE)
671 ierr = CeedOperatorSetField(coper, fieldname, coarse_er, cbasis,
672 if_vector[i]); PCeedChk(ierr);
676 ierr = CeedOperatorSetField(coper, fieldname, er_input[i], basis_input[i],
677 if_vector[i]); PCeedChk(ierr);
680 for (
int i = 0; i < numoutputfields; ++i)
683 ierr = CeedQFunctionFieldGetName(outputqfields[i], &fieldname); PCeedChk(ierr);
684 if (of_vector[i] == CEED_VECTOR_ACTIVE)
686 ierr = CeedOperatorSetField(coper, fieldname, coarse_er, cbasis,
687 of_vector[i]); PCeedChk(ierr);
691 ierr = CeedOperatorSetField(coper, fieldname, er_output[i], basis_output[i],
692 of_vector[i]); PCeedChk(ierr);
699 delete [] basis_input;
700 delete [] basis_output;