1 // Copyright (C) 2018 EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (EDF R&D)
21 #include "vtkGaussToCell.h"
23 #include "vtkAdjacentVertexIterator.h"
24 #include "vtkIntArray.h"
25 #include "vtkCellData.h"
26 #include "vtkPointData.h"
27 #include "vtkCellType.h"
29 #include "vtkCellArray.h"
30 #include "vtkIdTypeArray.h"
32 #include "vtkStreamingDemandDrivenPipeline.h"
33 #include "vtkUnstructuredGrid.h"
34 #include "vtkMultiBlockDataSet.h"
36 #include "vtkInformationStringKey.h"
37 #include "vtkAlgorithmOutput.h"
38 #include "vtkObjectFactory.h"
39 #include "vtkMutableDirectedGraph.h"
40 #include "vtkMultiBlockDataSet.h"
41 #include "vtkDataSet.h"
42 #include "vtkInformationVector.h"
43 #include "vtkInformation.h"
44 #include "vtkDataArraySelection.h"
45 #include "vtkTimeStamp.h"
46 #include "vtkInEdgeIterator.h"
47 #include "vtkInformationDataObjectKey.h"
48 #include "vtkInformationDataObjectMetaDataKey.h"
49 #include "vtkInformationDoubleVectorKey.h"
50 #include "vtkExecutive.h"
51 #include "vtkVariantArray.h"
52 #include "vtkStringArray.h"
53 #include "vtkDoubleArray.h"
54 #include "vtkFloatArray.h"
55 #include "vtkCharArray.h"
56 #include "vtkLongArray.h"
57 #include "vtkUnsignedCharArray.h"
58 #include "vtkDataSetAttributes.h"
59 #include "vtkDemandDrivenPipeline.h"
60 #include "vtkDataObjectTreeIterator.h"
61 #include "vtkWarpScalar.h"
62 #include "vtkQuadratureSchemeDefinition.h"
63 #include "vtkInformationQuadratureSchemeDefinitionVectorKey.h"
64 #include "vtkCompositeDataToUnstructuredGridFilter.h"
65 #include "vtkMultiBlockDataGroupFilter.h"
67 #include "MEDCouplingMemArray.hxx"
68 #include "MEDCouplingUMesh.hxx"
69 #include "MEDCouplingFieldDouble.hxx"
70 #include "InterpKernelAutoPtr.hxx"
71 #include "InterpKernelGaussCoords.hxx"
78 using MEDCoupling::DataArray;
79 using MEDCoupling::DataArrayInt;
80 using MEDCoupling::DataArrayDouble;
81 using MEDCoupling::MEDCouplingMesh;
82 using MEDCoupling::MEDCouplingUMesh;
83 using MEDCoupling::DynamicCastSafe;
84 using MEDCoupling::MEDCouplingFieldDouble;
85 using MEDCoupling::ON_GAUSS_PT;
86 using MEDCoupling::MCAuto;
88 vtkStandardNewMacro(vtkGaussToCell);
90 vtkInformationDoubleVectorKey *GetMEDReaderMetaDataIfAny()
92 static const char ZE_KEY[]="vtkMEDReader::GAUSS_DATA";
93 MEDCoupling::GlobalDict *gd(MEDCoupling::GlobalDict::GetInstance());
94 if(!gd->hasKey(ZE_KEY))
96 std::string ptSt(gd->value(ZE_KEY));
98 std::istringstream iss(ptSt); iss >> pt;
99 return reinterpret_cast<vtkInformationDoubleVectorKey *>(pt);
102 bool IsInformationOK(vtkInformation *info, std::vector<double>& data)
104 vtkInformationDoubleVectorKey *key(GetMEDReaderMetaDataIfAny());
107 // Check the information contain meta data key
110 int lgth(key->Length(info));
111 const double *data2(info->Get(key));
112 data.insert(data.end(),data2,data2+lgth);
116 void ExtractInfo(vtkInformationVector *inputVector, vtkUnstructuredGrid *& usgIn)
118 vtkInformation *inputInfo(inputVector->GetInformationObject(0));
119 vtkDataSet *input(0);
120 vtkDataSet *input0(vtkDataSet::SafeDownCast(inputInfo->Get(vtkDataObject::DATA_OBJECT())));
121 vtkMultiBlockDataSet *input1(vtkMultiBlockDataSet::SafeDownCast(inputInfo->Get(vtkDataObject::DATA_OBJECT())));
127 throw INTERP_KERNEL::Exception("Input dataSet must be a DataSet or single elt multi block dataset expected !");
128 if(input1->GetNumberOfBlocks()!=1)
129 throw INTERP_KERNEL::Exception("Input dataSet is a multiblock dataset with not exactly one block ! Use MergeBlocks or ExtractBlocks filter before calling this filter !");
130 vtkDataObject *input2(input1->GetBlock(0));
132 throw INTERP_KERNEL::Exception("Input dataSet is a multiblock dataset with exactly one block but this single element is NULL !");
133 vtkDataSet *input2c(vtkDataSet::SafeDownCast(input2));
135 throw INTERP_KERNEL::Exception("Input dataSet is a multiblock dataset with exactly one block but this single element is not a dataset ! Use MergeBlocks or ExtractBlocks filter before calling this filter !");
139 throw INTERP_KERNEL::Exception("Input data set is NULL !");
140 usgIn=vtkUnstructuredGrid::SafeDownCast(input);
142 throw INTERP_KERNEL::Exception("Input data set is not an unstructured mesh ! This filter works only on unstructured meshes !");
145 vtkGaussToCell::vtkGaussToCell():avgStatus(true),maxStatus(false),minStatus(false)
147 this->SetNumberOfInputPorts(1);
148 this->SetNumberOfOutputPorts(1);
151 vtkGaussToCell::~vtkGaussToCell()
155 void vtkGaussToCell::SetAvgFlag(bool avgStatus)
157 if(this->avgStatus!=avgStatus)
159 this->avgStatus=avgStatus;
164 void vtkGaussToCell::SetMaxFlag(bool maxStatus)
166 if(this->maxStatus!=maxStatus)
168 this->maxStatus=maxStatus;
173 void vtkGaussToCell::SetMinFlag(bool minStatus)
175 if(this->minStatus!=minStatus)
177 this->minStatus=minStatus;
182 int vtkGaussToCell::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
184 //std::cerr << "########################################## vtkGaussToCell::RequestInformation ##########################################" << std::endl;
187 vtkUnstructuredGrid *usgIn(0);
188 ExtractInfo(inputVector[0],usgIn);
190 catch(INTERP_KERNEL::Exception& e)
192 std::ostringstream oss;
193 oss << "Exception has been thrown in vtkGaussToCell::RequestInformation : " << e.what() << std::endl;
194 if(this->HasObserver("ErrorEvent") )
195 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
197 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
198 vtkObject::BreakOnError();
204 typedef void (*DataComputer) (const double *inData, const vtkIdType *offData, const std::vector<int> *nbgPerCell, int zeNbCompo, vtkIdType outNbCells, double *outData);
206 void ComputeAvg(const double *inData, const vtkIdType *offData, const std::vector<int> *nbgPerCell, int zeNbCompo, vtkIdType outNbCells, double *outData)
208 std::fill(outData,outData+outNbCells*zeNbCompo,0.);
209 for(auto i=0;i<outNbCells;i++,outData+=zeNbCompo)
211 auto NbGaussPt((*nbgPerCell)[i]);
212 for(auto j=0;j<NbGaussPt;j++)
213 std::transform(inData+(offData[i]+j)*zeNbCompo,inData+(offData[i]+(j+1))*zeNbCompo,outData,outData,[](const double& v, const double& w) { return v+w; });
214 double deno(1./(double)NbGaussPt);
215 std::transform(outData,outData+zeNbCompo,outData,[deno](const double& v) { return v*deno; });
219 void ComputeMax(const double *inData, const vtkIdType *offData, const std::vector<int> *nbgPerCell, int zeNbCompo, vtkIdType outNbCells, double *outData)
221 std::fill(outData,outData+outNbCells*zeNbCompo,-std::numeric_limits<double>::max());
222 for(auto i=0;i<outNbCells;i++,outData+=zeNbCompo)
224 auto NbGaussPt((*nbgPerCell)[i]);
225 for(auto j=0;j<NbGaussPt;j++)
226 std::transform(inData+(offData[i]+j)*zeNbCompo,inData+(offData[i]+(j+1))*zeNbCompo,outData,outData,[](const double& v, const double& w) { return std::max(v,w); });
230 void ComputeMin(const double *inData, const vtkIdType *offData, const std::vector<int> *nbgPerCell, int zeNbCompo, vtkIdType outNbCells, double *outData)
232 std::fill(outData,outData+outNbCells*zeNbCompo,std::numeric_limits<double>::max());
233 for(auto i=0;i<outNbCells;i++,outData+=zeNbCompo)
235 auto NbGaussPt((*nbgPerCell)[i]);
236 for(auto j=0;j<NbGaussPt;j++)
237 std::transform(inData+(offData[i]+j)*zeNbCompo,inData+(offData[i]+(j+1))*zeNbCompo,outData,outData,[](const double& v, const double& w) { return std::min(v,w); });
241 void DealWith(const char *postName, vtkDoubleArray *zearray, vtkIdTypeArray *offsets, const std::vector<int> *nbgPerCell, vtkIdType outNbCells, vtkDoubleArray *zeOutArray, DataComputer dc)
243 std::ostringstream oss;
244 oss << zearray->GetName() << '_' << postName;
245 int zeNbCompo(zearray->GetNumberOfComponents());
247 std::string st(oss.str());
248 zeOutArray->SetName(st.c_str());
250 zeOutArray->SetNumberOfComponents(zeNbCompo);
251 zeOutArray->SetNumberOfTuples(outNbCells);
252 double *outData(zeOutArray->GetPointer(0));
253 const double *inData(zearray->GetPointer(0));
254 const auto *offData(offsets->GetPointer(0));
255 for(auto i=0;i<zeNbCompo;i++)
257 const char *comp(zearray->GetComponentName(i));
259 zeOutArray->SetComponentName(i,comp);
261 dc(inData,offData,nbgPerCell,zeNbCompo,outNbCells,outData);
264 int vtkGaussToCell::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
266 //std::cerr << "########################################## vtkGaussToCell::RequestData ##########################################" << std::endl;
269 std::vector<double> GaussAdvData;
270 bool isOK(IsInformationOK(inputVector[0]->GetInformationObject(0),GaussAdvData));
272 throw INTERP_KERNEL::Exception("Sorry but no advanced gauss info found ! Expect to be called right after a MEDReader containing Gauss Points !");
273 vtkUnstructuredGrid *usgIn(0);
274 ExtractInfo(inputVector[0],usgIn);
275 vtkInformation *outInfo(outputVector->GetInformationObject(0));
276 vtkUnstructuredGrid *output(vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())));
277 output->ShallowCopy(usgIn);
279 std::string zeArrOffset;
280 int nArrays(usgIn->GetFieldData()->GetNumberOfArrays());
281 std::map<vtkIdTypeArray *,std::vector<int> > offsetKeyMap;//Map storing for each offsets array the corresponding nb of Gauss Points per cell
282 for(int i=0;i<nArrays;i++)
284 vtkDataArray *array(usgIn->GetFieldData()->GetArray(i));
287 const char* arrayOffsetName(array->GetInformation()->Get(vtkQuadratureSchemeDefinition::QUADRATURE_OFFSET_ARRAY_NAME()));
290 std::string arrOffsetNameCpp(arrayOffsetName);
291 if(arrOffsetNameCpp.find("ELGA@")==std::string::npos)
293 if(zeArrOffset.empty())
294 zeArrOffset=arrOffsetNameCpp;
296 if(zeArrOffset!=arrOffsetNameCpp)
298 throw INTERP_KERNEL::Exception("ComputeGaussToCell : error in QUADRATURE_OFFSET_ARRAY_NAME for Gauss fields array !");
300 vtkDataArray *offTmp(usgIn->GetCellData()->GetArray(zeArrOffset.c_str()));
303 std::ostringstream oss; oss << "ComputeGaussToCell : cell field " << zeArrOffset << " not found !";
304 throw INTERP_KERNEL::Exception(oss.str());
306 vtkIdTypeArray *offsets(vtkIdTypeArray::SafeDownCast(offTmp));
309 std::ostringstream oss; oss << "ComputeGaussToCell : cell field " << zeArrOffset << " exists but not with the right type of data !";
310 throw INTERP_KERNEL::Exception(oss.str());
312 vtkDoubleArray *zearray(vtkDoubleArray::SafeDownCast(array));
316 std::map<vtkIdTypeArray *,std::vector<int> >::iterator nbgPerCellPt(offsetKeyMap.find(offsets));
317 const std::vector<int> *nbgPerCell(nullptr);
318 if(nbgPerCellPt==offsetKeyMap.end())
321 vtkInformation *info(offsets->GetInformation());
323 throw INTERP_KERNEL::Exception("info is null ! Internal error ! Looks bad !");
324 vtkInformationQuadratureSchemeDefinitionVectorKey *key(vtkQuadratureSchemeDefinition::DICTIONARY());
326 throw INTERP_KERNEL::Exception("No quadrature key in info included in offets array ! Internal error ! Looks bad !");
327 int dictSize(key->Size(info));
328 INTERP_KERNEL::AutoPtr<vtkQuadratureSchemeDefinition *> dict(new vtkQuadratureSchemeDefinition *[dictSize]);
329 key->GetRange(info,dict,0,0,dictSize);
330 auto nbOfCells(output->GetNumberOfCells());
331 std::vector<int> nbg(nbOfCells);
332 for(auto cellId=0;cellId<nbOfCells;cellId++)
334 int ct(output->GetCellType(cellId));
335 vtkQuadratureSchemeDefinition *gaussLoc(dict[ct]);
338 std::ostringstream oss; oss << "For cell " << cellId << " no Gauss info attached !";
339 throw INTERP_KERNEL::Exception(oss.str());
341 int np(gaussLoc->GetNumberOfQuadraturePoints());
344 nbgPerCell=&((*(offsetKeyMap.emplace(offsets,std::move(nbg)).first)).second);
348 nbgPerCell=&((*nbgPerCellPt).second);
350 auto outNbCells(nbgPerCell->size());
353 vtkNew<vtkDoubleArray> zeOutArray;
354 DealWith("avg",zearray,offsets,nbgPerCell,outNbCells,zeOutArray,ComputeAvg);
355 output->GetCellData()->AddArray(zeOutArray);
359 vtkNew<vtkDoubleArray> zeOutArray;
360 DealWith("max",zearray,offsets,nbgPerCell,outNbCells,zeOutArray,ComputeMax);
361 output->GetCellData()->AddArray(zeOutArray);
365 vtkNew<vtkDoubleArray> zeOutArray;
366 DealWith("min",zearray,offsets,nbgPerCell,outNbCells,zeOutArray,ComputeMin);
367 output->GetCellData()->AddArray(zeOutArray);
371 catch(INTERP_KERNEL::Exception& e)
373 std::ostringstream oss;
374 oss << "Exception has been thrown in vtkGaussToCell::RequestData : " << e.what() << std::endl;
375 if(this->HasObserver("ErrorEvent") )
376 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
378 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
379 vtkObject::BreakOnError();
385 void vtkGaussToCell::PrintSelf(ostream& os, vtkIndent indent)
387 this->Superclass::PrintSelf(os, indent);