49 #ifndef Intrepid2_DirectSumBasis_h
50 #define Intrepid2_DirectSumBasis_h
52 #include <Kokkos_View.hpp>
53 #include <Kokkos_DynRankView.hpp>
67 template<
typename Basis1,
typename Basis2>
69 :
public Basis<typename Basis1::ExecutionSpace,
70 typename Basis1::OutputValueType,
71 typename Basis1::PointValueType>
79 using OrdinalTypeArray1DHost =
typename Basis1::OrdinalTypeArray1DHost;
80 using OrdinalTypeArray2DHost =
typename Basis1::OrdinalTypeArray2DHost;
82 using ExecutionSpace =
typename Basis1::ExecutionSpace;
83 using OutputValueType =
typename Basis1::OutputValueType;
84 using PointValueType =
typename Basis1::PointValueType;
86 using OutputViewType =
typename Basis1::OutputViewType;
87 using PointViewType =
typename Basis1::PointViewType;
88 using ScalarViewType =
typename Basis1::ScalarViewType;
96 basis1_(basis1),basis2_(basis2)
98 INTREPID2_TEST_FOR_EXCEPTION(basis1.getBasisType() != basis2.getBasisType(), std::invalid_argument,
"basis1 and basis2 must agree in basis type");
99 INTREPID2_TEST_FOR_EXCEPTION(basis1.getBaseCellTopology().getKey() != basis2.getBaseCellTopology().getKey(),
100 std::invalid_argument,
"basis1 and basis2 must agree in cell topology");
101 INTREPID2_TEST_FOR_EXCEPTION(basis1.getCoordinateSystem() != basis2.getCoordinateSystem(),
102 std::invalid_argument,
"basis1 and basis2 must agree in coordinate system");
105 this->
basisDegree_ = std::max(basis1.getDegree(), basis2.getDegree());
108 std::ostringstream basisName;
109 basisName << basis1.getName() <<
" + " << basis2.getName();
110 name_ = basisName.str();
117 if (this->
basisType_ == BASIS_FEM_HIERARCHICAL)
119 int degreeLength = basis1_.getPolynomialDegreeLength();
120 INTREPID2_TEST_FOR_EXCEPTION(degreeLength != basis2_.getPolynomialDegreeLength(), std::invalid_argument,
"Basis1 and Basis2 must agree on polynomial degree length");
124 for (
int fieldOrdinal1=0; fieldOrdinal1<basis1_.getCardinality(); fieldOrdinal1++)
126 int fieldOrdinal = fieldOrdinal1;
127 auto polynomialDegree = basis1.getPolynomialDegreeOfField(fieldOrdinal1);
128 for (
int d=0; d<degreeLength; d++)
133 for (
int fieldOrdinal2=0; fieldOrdinal2<basis2_.getCardinality(); fieldOrdinal2++)
135 int fieldOrdinal = basis1.getCardinality() + fieldOrdinal2;
137 auto polynomialDegree = basis2.getPolynomialDegreeOfField(fieldOrdinal2);
138 for (
int d=0; d<degreeLength; d++)
150 const ordinal_type tagSize = 4;
151 const ordinal_type posScDim = 0;
152 const ordinal_type posScOrd = 1;
153 const ordinal_type posDfOrd = 2;
159 unsigned spaceDim = cellTopo.getDimension();
161 ordinal_type basis2Offset = basis1_.getCardinality();
163 for (
unsigned d=0; d<=spaceDim; d++)
165 unsigned subcellCount = cellTopo.getSubcellCount(d);
166 for (
unsigned subcellOrdinal=0; subcellOrdinal<subcellCount; subcellOrdinal++)
168 ordinal_type subcellDofCount1 = basis1.getDofCount(d, subcellOrdinal);
169 ordinal_type subcellDofCount2 = basis2.getDofCount(d, subcellOrdinal);
171 ordinal_type subcellDofCount = subcellDofCount1 + subcellDofCount2;
172 for (ordinal_type localDofID=0; localDofID<subcellDofCount; localDofID++)
174 ordinal_type fieldOrdinal;
175 if (localDofID < subcellDofCount1)
178 fieldOrdinal = basis1_.getDofOrdinal(d, subcellOrdinal, localDofID);
183 fieldOrdinal = basis2Offset + basis2_.getDofOrdinal(d, subcellOrdinal, localDofID - subcellDofCount1);
185 tagView(fieldOrdinal*tagSize+0) = d;
186 tagView(fieldOrdinal*tagSize+1) = subcellOrdinal;
187 tagView(fieldOrdinal*tagSize+2) = localDofID;
188 tagView(fieldOrdinal*tagSize+3) = subcellDofCount;
197 this->basisCardinality_,
214 const int basisCardinality1 = basis1_.getCardinality();
215 const int basisCardinality2 = basis2_.getCardinality();
216 const int basisCardinality = basisCardinality1 + basisCardinality2;
218 auto dofCoords1 = Kokkos::subview(dofCoords, std::make_pair(0,basisCardinality1), Kokkos::ALL());
219 auto dofCoords2 = Kokkos::subview(dofCoords, std::make_pair(basisCardinality1,basisCardinality), Kokkos::ALL());
221 basis1_.getDofCoords(dofCoords1);
222 basis2_.getDofCoords(dofCoords2);
232 return name_.c_str();
259 const EOperator operatorType = OPERATOR_VALUE )
const override
261 int cardinality1 = basis1_.getCardinality();
262 int cardinality2 = basis2_.getCardinality();
264 auto range1 = std::make_pair(0,cardinality1);
265 auto range2 = std::make_pair(cardinality1,cardinality1+cardinality2);
266 if (outputValues.rank() == 2)
268 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL());
269 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL());
271 basis1_.getValues(outputValues1, inputPoints, operatorType);
272 basis2_.getValues(outputValues2, inputPoints, operatorType);
274 else if (outputValues.rank() == 3)
276 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL(), Kokkos::ALL());
277 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL(), Kokkos::ALL());
279 basis1_.getValues(outputValues1, inputPoints, operatorType);
280 basis2_.getValues(outputValues2, inputPoints, operatorType);
282 else if (outputValues.rank() == 4)
284 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
285 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
287 basis1_.getValues(outputValues1, inputPoints, operatorType);
288 basis2_.getValues(outputValues2, inputPoints, operatorType);
290 else if (outputValues.rank() == 5)
292 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
293 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
295 basis1_.getValues(outputValues1, inputPoints, operatorType);
296 basis2_.getValues(outputValues2, inputPoints, operatorType);
298 else if (outputValues.rank() == 6)
300 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
301 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
303 basis1_.getValues(outputValues1, inputPoints, operatorType);
304 basis2_.getValues(outputValues2, inputPoints, operatorType);
306 else if (outputValues.rank() == 7)
308 auto outputValues1 = Kokkos::subview(outputValues, range1, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
309 auto outputValues2 = Kokkos::subview(outputValues, range2, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
311 basis1_.getValues(outputValues1, inputPoints, operatorType);
312 basis2_.getValues(outputValues2, inputPoints, operatorType);
316 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported outputValues rank");
Kokkos::View< ordinal_type *, typename Basis_Derived_HDIV_Family1_QUAD< HGRAD_LINE, HVOL_LINE >::ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
Kokkos::View< ordinal_type **, typename Basis_Derived_HDIV_Family1_QUAD< HGRAD_LINE, HVOL_LINE >::ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
virtual void getDofCoords(ScalarViewType dofCoords) const override
Fills in spatial locations (coordinates) of degrees of freedom (nodes) on the reference cell...
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
ordinal_type basisDegree_
Degree of the largest complete polynomial space that can be represented by the basis.
virtual const char * getName() const override
Returns basis name.
EBasis basisType_
Type of the basis.
Basis_DirectSumBasis(Basis1 basis1, Basis2 basis2)
Constructor.
A basis that is the direct sum of two other bases.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, Basis_Derived_HDIV_Family1_QUAD< HGRAD_LINE, HVOL_LINE >::ExecutionSpace > OutputViewType
View type for basis value output.
OrdinalTypeArray2DHost fieldOrdinalPolynomialDegree_
Polynomial degree for each degree of freedom. Only defined for hierarchical bases right now...
void setOrdinalTagData(OrdinalTypeView3D &tagToOrdinal, OrdinalTypeView2D &ordinalToTag, const OrdinalTypeView1D tags, const ordinal_type basisCard, const ordinal_type tagSize, const ordinal_type posScDim, const ordinal_type posScOrd, const ordinal_type posDfOrd)
Fills ordinalToTag_ and tagToOrdinal_ by basis-specific tag data.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, Basis_Derived_HDIV_Family1_QUAD< HGRAD_LINE, HVOL_LINE >::ExecutionSpace > PointViewType
View type for input points.
Kokkos::DynRankView< scalarType, Kokkos::LayoutStride, Basis_Derived_HDIV_Family1_QUAD< HGRAD_LINE, HVOL_LINE >::ExecutionSpace > ScalarViewType
View type for scalars.
OrdinalTypeArray2DHost ordinalToTag_
"true" if tagToOrdinal_ and ordinalToTag_ have been initialized
shards::CellTopology basisCellTopology_
Base topology of the cells for which the basis is defined. See the Shards package for definition of b...