3#ifndef vtkDGOperationEvaluator_h
4#define vtkDGOperationEvaluator_h
54template <
typename InputIterator,
typename OutputIterator,
vtkDGSharingType DOFSharing,
71 op, connectivity, values, sideConn, offset, shapeGradient, shapeConnectivity, shapeValues)
75 throw std::logic_error(
"Must have non-null operator.");
77 if (Modifier !=
None && !shapeGradient)
79 throw std::logic_error(
"Must have non-null shape gradient operator.");
83 if (this->CellConnectivity)
85 ncc = this->CellConnectivity->GetNumberOfComponents();
86 this->ConnTuple.resize(ncc);
90 throw std::logic_error(
"DOF sharing requires a cell-connectivity array.");
92 int nvc = this->CellValues->GetNumberOfComponents();
95 this->NumberOfValuesPerFunction = nvc;
96 this->ValueTuple.resize(nvc * ncc);
100 this->NumberOfValuesPerFunction = nvc / this->OpEntry.NumberOfFunctions;
101 this->ValueTuple.resize(nvc);
106 if (Modifier !=
None)
108 this->Jacobian.resize(9);
109 this->ShapeBasisTuple.resize(shapeGradient.NumberOfFunctions * shapeGradient.OperatorSize);
111 if (this->ShapeConnectivity)
113 nsc = this->ShapeConnectivity->GetNumberOfComponents();
114 this->ShapeConnTuple.resize(nsc);
118 throw std::logic_error(
"Shape DOF-sharing requires a shape-connectivity array.");
120 int nvs = this->ShapeValues->GetNumberOfComponents();
123 this->NumberOfShapeValuesPerFunction = nvs;
124 this->ShapeValueTuple.resize(nvs * nsc);
128 this->NumberOfShapeValuesPerFunction = nvs / this->ShapeGradientEntry.NumberOfFunctions;
129 this->ShapeValueTuple.resize(nvs);
136 if (
auto* typedEntry =
140 ShapeSharing>::prepEntry(*typedEntry, this->OpEntry, this->CellConnectivity,
141 this->CellValues, this->SideConnectivity, this->Offset, this->ShapeGradientEntry,
142 this->ShapeConnectivity, this->ShapeValues);
151 auto xx(outIter[tt]);
152 int nc =
static_cast<int>(xx.size());
154 for (
int ii = 0; ii < nc; ++ii)
161 for (
int jj = 0; jj < this->OpEntry.OperatorSize; ++jj)
163 for (
int kk = 0; kk < this->OpEntry.NumberOfFunctions; ++kk)
165 xx[ii * this->OpEntry.OperatorSize + jj] +=
166 this->BasisTuple[kk * this->OpEntry.OperatorSize + jj] *
167 this->ValueTuple[kk * this->NumberOfValuesPerFunction + ii];
177 constexpr int nc = 9;
178 assert(nc == this->ShapeGradientEntry.OperatorSize * this->NumberOfShapeValuesPerFunction);
180 for (
int ii = 0; ii < nc; ++ii)
182 this->Jacobian[ii] = 0.;
186 for (
int jj = 0; jj < this->ShapeGradientEntry.OperatorSize; ++jj)
188 for (
int kk = 0; kk < this->ShapeGradientEntry.NumberOfFunctions; ++kk)
190 this->Jacobian[jj + this->NumberOfShapeValuesPerFunction * ii] +=
191 this->ShapeBasisTuple[kk * this->ShapeGradientEntry.OperatorSize + jj] *
192 this->ShapeValueTuple[kk * this->NumberOfShapeValuesPerFunction + ii];
203 if (this->LastShapeCellId != this->LastCellId)
205 this->ShapeConnectivity->GetUnsignedTuple(this->LastCellId, this->ShapeConnTuple.data());
206 std::size_t nc = this->ShapeConnTuple.size();
207 int nv = this->ShapeValues->GetNumberOfComponents();
208 for (std::size_t jj = 0; jj < nc; ++jj)
210 this->ShapeValues->GetTuple(
211 this->ShapeConnTuple[jj], this->ShapeValueTuple.data() + nv * jj);
218 if (this->LastShapeCellId != this->LastCellId)
220 this->ShapeValues->GetTuple(this->LastCellId, this->ShapeValueTuple.data());
226 throw std::logic_error(
"Invalid shape DOF-sharing enumerant.");
228 this->ShapeGradientEntry.Op(this->RST, this->ShapeBasisTuple);
229 this->ShapeInnerProduct();
237 this->ComputeJacobian();
239 std::array<double, 9> inverseJacobian;
244 auto rr(outIter[ii]);
245 const int nc =
static_cast<int>(rr.size());
248 throw std::logic_error(
"Jacobian must apply to vector or matrix values.");
250 for (
int vv = 0; vv < nc / 3; ++vv)
252 vtkTypeUInt64 mm = 3 * vv;
253 double* vec = rr.data() + mm;
263 this->ComputeJacobian();
267 std::array<double, 3> vec;
268 auto rr(outIter[ii]);
269 const int nc =
static_cast<int>(rr.size());
272 throw std::logic_error(
"Jacobian must apply to vector or matrix values.");
274 for (
int vv = 0; vv < nc / 3; ++vv)
276 vtkTypeUInt64 mm = 3 * vv;
277 vec = { { rr[mm], rr[mm + 1], rr[mm + 2] } };
280 rr[mm ] = norm * (this->Jacobian[0] * vec[0] + this->Jacobian[1] * vec[1] + this->Jacobian[2] * vec[2]);
281 rr[mm + 1] = norm * (this->Jacobian[3] * vec[0] + this->Jacobian[4] * vec[1] + this->Jacobian[5] * vec[2]);
282 rr[mm + 2] = norm * (this->Jacobian[6] * vec[0] + this->Jacobian[7] * vec[1] + this->Jacobian[8] * vec[2]);
288 InputIterator& inIter, OutputIterator& outIter, vtkTypeUInt64 begin, vtkTypeUInt64 end)
const
290 vtkTypeUInt64 currId;
293 for (vtkTypeUInt64 ii = begin; ii != end; ++ii)
295 currId = inIter.GetCellId(ii);
296 this->SideConnectivity->GetUnsignedTuple(currId - this->Offset, this->SideTuple.data());
297 currId = this->SideTuple[0];
298 if (this->LastCellId != currId)
300 this->CellConnectivity->GetUnsignedTuple(currId, this->ConnTuple.data());
301 std::size_t nc = this->ConnTuple.size();
302 int nv = this->CellValues->GetNumberOfComponents();
303 for (std::size_t jj = 0; jj < nc; ++jj)
305 this->CellValues->GetTuple(this->ConnTuple[jj], this->ValueTuple.data() + nv * jj);
307 this->LastCellId = currId;
309 auto param = inIter.GetParameter(ii);
310 for (
int jj = 0; jj < 3; ++jj)
312 this->RST[jj] = param[jj];
314 this->OpEntry.Op(this->RST, this->BasisTuple);
315 this->InnerProduct(ii, outIter);
318 this->ApplyInverseJacobian(ii, outIter);
322 this->ApplyScaledJacobian(ii, outIter);
328 for (vtkTypeUInt64 ii = begin; ii != end; ++ii)
330 currId = inIter.GetCellId(ii);
331 if (this->LastCellId != currId)
335 this->CellConnectivity->GetUnsignedTuple(currId, this->ConnTuple.data());
336 std::size_t nc = this->ConnTuple.size();
337 int nv = this->CellValues->GetNumberOfComponents();
338 for (std::size_t jj = 0; jj < nc; ++jj)
340 this->CellValues->GetTuple(this->ConnTuple[jj], this->ValueTuple.data() + nv * jj);
342 this->LastCellId = currId;
344 auto param = inIter.GetParameter(ii);
345 for (
int jj = 0; jj < 3; ++jj)
347 this->RST[jj] = param[jj];
349 this->OpEntry.Op(this->RST, this->BasisTuple);
350 this->InnerProduct(ii, outIter);
353 this->ApplyInverseJacobian(ii, outIter);
357 this->ApplyScaledJacobian(ii, outIter);
363 for (vtkTypeUInt64 ii = begin; ii != end; ++ii)
365 currId = inIter.GetCellId(ii);
366 this->SideConnectivity->GetUnsignedTuple(currId - this->Offset, this->SideTuple.data());
367 currId = this->SideTuple[0];
368 if (this->LastCellId != currId)
370 this->CellValues->GetTuple(currId, this->ValueTuple.data());
371 this->LastCellId = currId;
373 auto param = inIter.GetParameter(ii);
374 for (
int jj = 0; jj < 3; ++jj)
376 this->RST[jj] = param[jj];
378 this->OpEntry.Op(this->RST, this->BasisTuple);
379 this->InnerProduct(ii, outIter);
382 this->ApplyInverseJacobian(ii, outIter);
386 this->ApplyScaledJacobian(ii, outIter);
392 for (vtkTypeUInt64 ii = begin; ii != end; ++ii)
394 currId = inIter.GetCellId(ii);
397 if (this->LastCellId != currId)
399 this->CellValues->GetTuple(currId, this->ValueTuple.data());
400 this->LastCellId = currId;
402 auto param = inIter.GetParameter(ii);
403 for (
int jj = 0; jj < 3; ++jj)
405 this->RST[jj] = param[jj];
407 this->OpEntry.Op(this->RST, this->BasisTuple);
408 this->InnerProduct(ii, outIter);
411 this->ApplyInverseJacobian(ii, outIter);
415 this->ApplyScaledJacobian(ii, outIter);
433 OutputIterator, DOFSharing, SourceType, Modifier, ShapeSharing>(
434 op, conn, values, sides, offset, shapeGradient, shapeConnectivity, shapeValues));
435 entry.
Function = [&entry](InputIterator& inIter, OutputIterator& outIter, vtkTypeUInt64 begin,
439 DOFSharing, SourceType, Modifier, ShapeSharing
>*>(entry.
State.get());
440 return (*eval)(inIter, outIter, begin, end);
Evaluate a vtkDGOperationEntry on a provided cell ID at provided parametric coordinates.
static void prepEntry(vtkDGOperationStateEntry< InputIterator, OutputIterator > &entry, vtkDGOperatorEntry op, vtkDataArray *conn, vtkDataArray *values, vtkDataArray *sides, vtkTypeUInt64 offset, vtkDGOperatorEntry shapeGradient=vtkDGOperatorEntry(), vtkDataArray *shapeConnectivity=nullptr, vtkDataArray *shapeValues=nullptr)
Prepare an entry for evaluating op with the given data arrays and class template parameters.
void ApplyScaledJacobian(vtkTypeUInt64 ii, OutputIterator &outIter) const
InputIterator InputIteratorType
vtkDGOperationEvaluator(vtkDGOperatorEntry &op, vtkDataArray *connectivity, vtkDataArray *values, vtkDataArray *sideConn, vtkTypeUInt64 offset, vtkDGOperatorEntry shapeGradient=vtkDGOperatorEntry(), vtkDataArray *shapeConnectivity=nullptr, vtkDataArray *shapeValues=nullptr)
OutputIterator OutputIteratorType
void CloneInto(vtkDGOperationStateEntryBase &entry) const override
void InnerProduct(vtkTypeUInt64 tt, OutputIterator &outIter) const
Compute the inner product of this->BasisTuple and this->ValueTuple, storing the result in the tt-th t...
void operator()(InputIterator &inIter, OutputIterator &outIter, vtkTypeUInt64 begin, vtkTypeUInt64 end) const
void ComputeJacobian() const
Compute the shape-attribute Jacobian matrix, storing it in this->Jacobian.
void ShapeInnerProduct() const
Compute the inner product of this->ShapeBasisTuple and this->ShapeValueTuple, storing the result in t...
void ApplyInverseJacobian(vtkTypeUInt64 ii, OutputIterator &outIter) const
This is a base class that exists so that vtkDGOperationState can provide a virtual CloneInto method t...
Encapsulate the state required to evaluate DG cell-attributes.
std::unique_ptr< vtkDGOperationState > State
vtkDGCellRangeEvaluator< InputIterator, OutputIterator > Function
Encapsulate the state required to evaluate DG cell-attributes.
int NumberOfShapeValuesPerFunction
int NumberOfValuesPerFunction
A record for a basis in a function space that is specific to one cell shape.
int OperatorSize
The number of coordinates each operator-function evaluates to.
int NumberOfFunctions
The number of functions in the basis.
abstract superclass for arrays of numeric data
double Determinant()
Compute the determinant of the matrix and return it.
void MultiplyPoint(const float in[3], float out[3])
Multiply a homogeneous coordinate by this matrix, i.e.
#define VTK_ALWAYS_EXPORT
vtkDGShapeModifier
Which type of shape-function post-processing is required.
@ ScaledJacobian
!< For HGRAD
vtkDGSharingType
Whether degrees of freedom (DOF) are shared between cells.
@ Discontinuous
Degrees of freedom are not shared.
@ SharedDOF
Degrees of freedom (DOF) are shared.
vtkDGSideType
Whether cells are stand-alone or sides of other cells.
@ Cells
A cell specified by degrees of freedom held in arrays.
@ Sides
A side specified by a cell ID and an integer index into sides.