31 #include <vtkQuadraturePointsGenerator.h> 32 #include <vtkMeshQuality.h> 33 #include <vtkInformationQuadratureSchemeDefinitionVectorKey.h> 34 #include <vtkCellData.h> 35 #include <vtkCellTypes.h> 36 #include <vtkInformation.h> 37 #include <vtkXMLPolyDataWriter.h> 60 .666666666666667, .166666666666667, .166666666666667,
61 .166666666666667, .666666666666667, .166666666666667,
62 .166666666666667, .166666666666667, .666666666666667
65 double TRI3W[] = {0.333333333333333, 0.333333333333333, 0.333333333333333};
70 .585410196624969, .138196601125011, .138196601125011, .138196601125011,
71 .138196601125011, .585410196624969, .138196601125011, .138196601125011,
72 .138196601125011, .138196601125011, .585410196624969, .138196601125011,
73 .138196601125011, .138196601125011, .138196601125011, .585410196624969
77 double TET4W[] = {0.25, 0.25, 0.25, 0.25};
81 0.490562612162344, 0.131445855765802, 0.0352208109008645,
82 0.131445855765802, 0.131445855765802, 0.0352208109008645,
83 0.00943738783765592, 0.0352208109008645, 0.131445855765802,
84 0.490562612162344, 0.131445855765802, 0.0352208109008645,
85 0.0352208109008645, 0.131445855765802, 0.0352208109008645,
86 0.00943738783765592, 0.131445855765802, 0.0352208109008645,
87 0.131445855765802, 0.490562612162344, 0.0352208109008645,
88 0.00943738783765592, 0.0352208109008645, 0.131445855765802,
89 0.0352208109008645, 0.131445855765802, 0.490562612162344,
90 0.131445855765802, 0.00943738783765592, 0.0352208109008645,
91 0.131445855765802, 0.0352208109008645, 0.131445855765802,
92 0.0352208109008645, 0.00943738783765592, 0.0352208109008645,
93 0.490562612162344, 0.131445855765802, 0.0352208109008645,
94 0.131445855765802, 0.0352208109008645, 0.131445855765802,
95 0.0352208109008645, 0.00943738783765592, 0.131445855765802,
96 0.490562612162344, 0.131445855765802, 0.0352208109008645,
97 0.0352208109008645, 0.00943738783765592, 0.0352208109008645,
98 0.131445855765802, 0.131445855765802, 0.0352208109008645,
99 0.131445855765802, 0.490562612162344, 0.00943738783765592,
100 0.0352208109008645, 0.131445855765802, 0.0352208109008645,
101 0.0352208109008645, 0.131445855765802, 0.490562612162344,
104 double HEX8W[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
108 : dataSet(_dataSet), numVolCells(0), totalComponents(0)
110 dataSet->GetCellData()->RemoveArray(
"QuadratureOffSet");
115 const std::vector<int> &_arrayIDs)
119 dataSet->GetCellData()->RemoveArray(
"QuadratureOffSet");
140 std::unique_ptr<GaussCubature>
144 return std::unique_ptr<GaussCubature>(
148 std::shared_ptr<GaussCubature>
151 std::shared_ptr<GaussCubature> cuby;
156 std::shared_ptr<GaussCubature>
160 std::shared_ptr<GaussCubature> cuby;
170 vtkSmartPointer<vtkPointData> pd =
dataSet->GetPointData();
171 int numArr = pd->GetNumberOfArrays();
174 if (arrayID >= numArr)
176 std::cerr <<
"Array ID " << arrayID <<
" not found in dataset" 184 auto key = vtkQuadratureSchemeDefinition::DICTIONARY();
188 dataSet->GetCellTypes(cellTypes);
189 int nCellTypes = cellTypes->GetNumberOfTypes();
193 std::string basename =
"QuadratureOffset";
194 offsets->SetName(basename.c_str());
196 info = offsets->GetInformation();
198 for (
int typeId = 0; typeId < nCellTypes; ++typeId)
200 int cellType = cellTypes->GetCellType(typeId);
206 def->Initialize(VTK_TRIANGLE, 3, 3,
TRI3,
TRI3W);
209 def->Initialize(VTK_TETRA, 4, 4,
TET4,
TET4W);
212 def->Initialize(VTK_HEXAHEDRON, 8, 8,
HEX8,
HEX8W);
215 std::cerr <<
"Error: Cell type: " << cellType <<
" found " 216 <<
"with no quadrature definition provided" << std::endl;
221 key->Set(info, def, cellType);
224 int dictSize = key->Size(info);
225 dict =
new vtkQuadratureSchemeDefinition *[dictSize];
226 key->GetRange(info,
dict, 0, 0, dictSize);
227 vtkIdType numCells =
dataSet->GetNumberOfCells();
229 offsets->SetNumberOfTuples(numCells);
232 std::vector<vtkIdType> chunkOffsets(omp_get_max_threads() + 1, 0);
233 #pragma omp parallel default(none) shared(numCells, chunkOffsets, offsets) 235 vtkIdType subOffset = 0;
244 #pragma omp for schedule(static) 245 for (vtkIdType cellId = 0; cellId < numCells; ++cellId) {
246 offsets->SetValue(cellId, subOffset);
248 dataSet->GetCell(cellId, genCell);
249 int cellType = genCell->GetCellType();
252 vtkQuadratureSchemeDefinition *celldef =
dict[
cellType];
253 subOffset += celldef->GetNumberOfQuadraturePoints();
256 int tid = omp_get_thread_num();
257 chunkOffsets[tid + 1] = subOffset;
261 for (
int i = 1; i < chunkOffsets.size(); ++i) {
262 chunkOffsets[i] = chunkOffsets[i] + chunkOffsets[i - 1];
266 #pragma omp for schedule(static) 267 for (vtkIdType cellId = 0; cellId < numCells; ++cellId) {
268 vtkIdType offset = chunkOffsets[tid] + offsets->GetValue(cellId);
269 offsets->SetValue(cellId, offset);
273 vtkIdType offset = 0;
275 for (
int cellid = 0; cellid < numCells; ++cellid) {
276 offsets->SetValue(cellid, offset);
278 if (cellType >= VTK_TETRA) {
281 vtkQuadratureSchemeDefinition *celldef =
dict[
cellType];
282 offset += celldef->GetNumberOfQuadraturePoints();
286 dataSet->GetCellData()->AddArray(offsets);
290 pointGen->SetInputArrayToProcess
292 vtkDataObject::FIELD_ASSOCIATION_CELLS,
294 pointGen->SetInputData(
dataSet);
296 gaussMesh = vtkPolyData::SafeDownCast(pointGen->GetOutput());
308 return vtkMeshQuality::TriangleArea(genCell);
312 return vtkMeshQuality::QuadArea(genCell);
316 return vtkMeshQuality::TetVolume(genCell);
320 return vtkMeshQuality::HexVolume(genCell);
324 std::cerr <<
"Error: Cell type: " << cellType <<
"found " 325 <<
"with no quadrature definition provided" << std::endl;
340 return vtkMeshQuality::TriangleArea(genCell);
344 return vtkMeshQuality::QuadArea(genCell) / 4.0;
348 return vtkMeshQuality::TetVolume(genCell);
352 return vtkMeshQuality::HexVolume(genCell) / 8.0;
356 std::cerr <<
"Error: Cell type: " << cellType <<
"found " 357 <<
"with no quadrature definition provided" << std::endl;
366 vtkIdType offsets[1];
367 vtkIdTypeArray::FastDownCast(
368 dataSet->GetCellData()->GetArray(
"QuadratureOffset"))
369 ->GetTypedTuple(cellID, offsets);
378 std::cerr <<
"no array have been selected for interpolation" << std::endl;
382 int numDataArr =
gaussMesh->GetPointData()->GetNumberOfArrays();
391 cellID)->GetCellType()]
392 ->GetNumberOfQuadraturePoints();
399 vtkSmartPointer<vtkPointData> pd =
gaussMesh->GetPointData();
400 for (
int i = 0; i < numGaussPoints; ++i)
404 std::vector<double> gaussPnt(x_tmp, x_tmp + 3);
410 pd->GetArray(j)->GetTuple(offset + i, comps);
411 for (
int k = 0; k < numComponents[j]; ++k)
413 data[currcomp] = comps[k];
418 container[i] = std::make_pair(gaussPnt, data);
426 vtkSmartPointer<vtkGenericCell> genCell,
427 const std::vector<vtkSmartPointer<vtkDataArray>> &das,
428 std::vector<vtkSmartPointer<vtkDoubleArray>> &daGausses)
const 431 dataSet->GetCell(cellID, genCell);
435 const double *shapeFunctionWeights =
dict[
cellType]->GetShapeFunctionWeights();
437 int numGaussPoints =
dict[
cellType]->GetNumberOfQuadraturePoints();
441 for (
int j = 0; j < numGaussPoints; ++j)
443 for (
int id = 0;
id < das.size(); ++
id)
445 int numComponent = das[
id]->GetNumberOfComponents();
446 auto *comps =
new double[numComponent];
447 std::vector<double> interps(numComponent, 0.0);
448 for (
int m = 0; m < genCell->GetNumberOfPoints(); ++m)
450 int pntId = genCell->GetPointId(m);
451 das[
id]->GetTuple(pntId, comps);
452 for (
int h = 0; h < numComponent; ++h)
454 interps[h] += comps[h] *
455 shapeFunctionWeights[j * genCell->GetNumberOfPoints() + m];
460 daGausses[
id]->SetTuple(j + offset, interps.data());
463 return numGaussPoints;
471 std::cerr <<
"no arrays selected for interpolation" << std::endl;
475 std::vector<vtkSmartPointer<vtkDoubleArray>> daGausses(
arrayIDs.size());
476 std::vector<vtkSmartPointer<vtkDataArray>> das(
arrayIDs.size());
482 vtkSmartPointer<vtkDataArray> da =
dataSet->GetPointData()->GetArray(
485 int numComponent = da->GetNumberOfComponents();
491 daGauss->SetNumberOfComponents(numComponent);
492 daGauss->SetNumberOfTuples(
gaussMesh->GetNumberOfPoints());
494 daGausses[
id] = daGauss;
498 int numCells =
dataSet->GetNumberOfCells();
500 #pragma omp parallel default(none) shared(numCells, das, daGausses) 502 vtkSmartPointer<vtkGenericCell> genCell =
509 #pragma omp for schedule(static) 510 for (
int i = 0; i < numCells; ++i) {
517 for (
int i = 0; i <
dataSet->GetNumberOfCells(); ++i)
524 gaussMesh->GetPointData()->AddArray(daGausses[
id]);
530 const std::vector<std::string> &newArrayNames) {
531 if (newArrayNames.empty()) {
532 std::cerr <<
"no arrays selected for interpolation" << std::endl;
536 std::vector<vtkSmartPointer<vtkDoubleArray>> daGausses(newArrayNames.size());
537 std::vector<vtkSmartPointer<vtkDataArray>> das(newArrayNames.size());
539 for (
int id = 0;
id < newArrayNames.size(); ++
id) {
541 vtkSmartPointer<vtkDataArray> da =
542 dataSet->GetPointData()->GetArray(&(newArrayNames[
id])[0u]);
544 int numComponent = da->GetNumberOfComponents();
548 daGauss->SetName(&(newArrayNames[
id])[0u]);
549 daGauss->SetNumberOfComponents(numComponent);
550 daGauss->SetNumberOfTuples(
gaussMesh->GetNumberOfPoints());
552 daGausses[
id] = daGauss;
554 int numCells =
dataSet->GetNumberOfCells();
556 #pragma omp parallel default(none) shared(numCells, das, daGausses) 559 vtkSmartPointer<vtkGenericCell> genCell =
566 #pragma omp for schedule(static) 567 for (
int i = 0; i < numCells; ++i) {
573 vtkSmartPointer<vtkGenericCell> genCell =
575 for (
int i = 0; i <
dataSet->GetNumberOfCells(); ++i) {
581 gaussMesh->GetPointData()->AddArray(daGausses[
id]);
587 vtkSmartPointer<vtkGenericCell> genCell,
588 vtkSmartPointer<vtkPointData> pd,
589 std::vector<vtkSmartPointer<vtkDoubleArray>> &integralData,
590 std::vector<std::vector<double>> &totalIntegralData)
const 593 dataSet->GetCell(cellID, genCell);
596 int cellType = genCell->GetCellType();
600 const double* quadWeights;
601 numGaussPoints =
dict[
cellType]->GetNumberOfQuadraturePoints();
612 for (
int j = 0; j < integralData.size(); ++j) {
613 int numComponent = integralData[j]->GetNumberOfComponents();
614 data[j].resize(numComponent, 0.0);
615 auto comps =
new double[numComponent];
616 for (
int i = 0; i < numGaussPoints; ++i) {
617 pd->GetArray(j)->GetTuple(offset + i, comps);
618 for (
int k = 0; k < numComponent; ++k) {
620 if (genCell->GetCellDimension() == 3) {
621 data[j][k] += comps[k] * quadWeights[i];
627 for (
int k = 0; k < numComponent; ++k) {
628 data[j][k] *= jacobian;
629 totalIntegralData[j][k] +=
data[j][k];
632 integralData[j]->SetTuple(cellID,
data[j].
data());
639 vtkSmartPointer<vtkGenericCell> genCell,
640 vtkSmartPointer<vtkPointData> pd,
641 std::vector<vtkSmartPointer<vtkDoubleArray>> &integralData,
642 std::vector<std::vector<double>> &totalIntegralData,
643 const std::vector<std::string> &newArrayNames,
644 bool computeRMSE)
const 647 dataSet->GetCell(cellID, genCell);
651 int numGaussPoints =
dict[
cellType]->GetNumberOfQuadraturePoints();
657 const double *quadWeights =
dict[
cellType]->GetQuadratureWeights();
663 for (
int j = 0; j < integralData.size(); ++j)
665 int numComponent = integralData[j]->GetNumberOfComponents();
666 data[j].resize(numComponent);
667 auto *comps =
new double[numComponent];
668 for (
int i = 0; i < numGaussPoints; ++i)
670 pd->GetArray(&(newArrayNames[j])[0u])->GetTuple(offset + i, comps);
671 for (
int k = 0; k < numComponent; ++k)
674 if (genCell->GetCellDimension() == 3)
676 data[j][k] += comps[k] * quadWeights[i];
684 for (
int k = 0; k < numComponent; ++k)
686 data[j][k] *= jacobian;
687 data[j][k] = (computeRMSE ? std::sqrt(
data[j][k] / volume) :
data[j][k]);
690 totalIntegralData[j][k] +=
data[j][k];
693 integralData[j]->SetTuple(cellID,
data[j].
data());
699 int numCells =
dataSet->GetNumberOfCells();
701 if (
gaussMesh->GetPointData()->GetNumberOfArrays() == 0)
706 vtkSmartPointer<vtkPointData> pd =
gaussMesh->GetPointData();
707 std::vector<vtkSmartPointer<vtkDoubleArray>> cellIntegralData(
arrayIDs.size());
708 std::vector<std::vector<double>> totalIntegralData(
arrayIDs.size());
713 arrName.append(
"Integral");
715 integralDatum->SetName(&arrName[0u]);
717 integralDatum->SetNumberOfTuples(
dataSet->GetNumberOfCells());
718 cellIntegralData[
id] = integralDatum;
723 #pragma omp parallel default(none) shared(numCells, pd, cellIntegralData, totalIntegralData, cerr) 732 auto partialIntegralData = totalIntegralData;
734 #pragma omp for schedule(static) 735 for (
int i = 0; i < numCells; ++i) {
743 for (
int id = 0;
id < partialIntegralData.size(); ++
id) {
744 for (
int k = 0; k < partialIntegralData[
id].size(); ++k) {
745 totalIntegralData[
id][k] += partialIntegralData[
id][k];
752 for (
int i = 0; i < numCells; ++i) {
757 for (
int id = 0;
id <
arrayIDs.size(); ++
id) {
758 dataSet->GetCellData()->AddArray(cellIntegralData[
id]);
760 return totalIntegralData;
764 std::vector<std::vector<double>>
766 const std::vector<std::string> &newArrayNames,
771 vtkSmartPointer<vtkPointData> pd =
gaussMesh->GetPointData();
772 std::vector<vtkSmartPointer<vtkDoubleArray>> cellIntegralData(newArrayNames.size());
773 std::vector<std::vector<double>> totalIntegralData(newArrayNames.size());
774 for (
int id = 0;
id < newArrayNames.size(); ++
id)
776 std::string name = newArrayNames[
id] +
"Integral";
778 integralDatum->SetName(&name[0u]);
779 int numComponent = pd->GetArray(
780 &(newArrayNames[
id])[0u])->GetNumberOfComponents();
781 integralDatum->SetNumberOfComponents(numComponent);
782 integralDatum->SetNumberOfTuples(
dataSet->GetNumberOfCells());
783 cellIntegralData[
id] = integralDatum;
784 totalIntegralData[
id].resize(numComponent, 0);
787 int numCells =
dataSet->GetNumberOfCells();
790 #pragma omp parallel default(none) \ 791 shared(numCells, pd, cellIntegralData, totalIntegralData, newArrayNames, computeRMSE) 799 auto partialIntegralData = totalIntegralData;
800 #pragma omp for schedule(static) 801 for (
int i = 0; i < numCells; ++i) {
803 newArrayNames, computeRMSE);
809 for(
int id = 0;
id < partialIntegralData.size(); ++
id) {
810 for(
int k = 0; k < partialIntegralData[
id].size(); ++k) {
811 totalIntegralData[
id][k] += partialIntegralData[
id][k];
818 for (
int i = 0; i < numCells; ++i) {
820 newArrayNames, computeRMSE);
824 for (
int id = 0;
id < newArrayNames.size(); ++
id)
826 dataSet->GetCellData()->AddArray(cellIntegralData[
id]);
828 return totalIntegralData;
835 writeVTFile<vtkXMLPolyDataWriter>(name,
gaussMesh);
838 std::cerr <<
"Gauss point mesh has not been constructed" << std::endl;
double computeJacobian(vtkSmartPointer< vtkGenericCell > genCell, int cellType) const
data_type data
Edge/face with sorted point ids (a, b, c, ...) is located at some index i in data[b], with data[b][i].first == [a, c] (for edges, third point id treated as -1).
std::vector< int > numComponents
void writeGaussMesh(const char *name) const
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
std::vector< pntDataPair > pntDataPairVec
void interpolateToGaussPoints()
Interpolate values to gauss points for arrays specified in arrayIDs at construction time...
std::vector< std::vector< double > > integrateOverAllCells()
Integrate arrays specified by arrayIDs over all cells.
static GaussCubature * Create(vtkDataSet *_dataSet)
double computeCellVolume(vtkSmartPointer< vtkGenericCell > genCell, int cellType) const
void constructGaussMesh()
GaussCubature(vtkDataSet *_dataSet)
static std::shared_ptr< GaussCubature > CreateShared(vtkDataSet *_dataSet)
vtkIdType id
id in .inp file
int interpolateToGaussPointsAtCell(int cellID, vtkSmartPointer< vtkGenericCell > genCell, const std::vector< vtkSmartPointer< vtkDataArray >> &das, std::vector< vtkSmartPointer< vtkDoubleArray >> &daGausses) const
int getOffset(int cellID) const
vtkSmartPointer< vtkDataSet > dataSet
vtkSmartPointer< vtkPolyData > gaussMesh
pntDataPairVec getGaussPointsAndDataAtCell(int cellID)
Returns coordinates of gauss points and associated data at cell.
std::vector< int > arrayIDs
void integrateOverCell(int cellID, vtkSmartPointer< vtkGenericCell > genCell, vtkSmartPointer< vtkPointData > pd, std::vector< vtkSmartPointer< vtkDoubleArray >> &integralData, std::vector< std::vector< double >> &totalIntegralData) const
vtkQuadratureSchemeDefinition ** dict
static std::unique_ptr< GaussCubature > CreateUnique(vtkDataSet *_dataSet)