Salome HOME
Copyright update 2022
[modules/paravis.git] / src / Plugins / MEDWriter / plugin / MEDWriterIO / vtkMEDWriter.cxx
1 // Copyright (C) 2016-2022  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "vtkMEDWriter.h"
22 #include "VTKToMEDMem.h"
23
24 #include <vtkAdjacentVertexIterator.h>
25 #include <vtkAlgorithmOutput.h>
26 #include <vtkCellArray.h>
27 #include <vtkCellData.h>
28 #include <vtkCharArray.h>
29 #include <vtkDataArraySelection.h>
30 #include <vtkDataObjectTreeIterator.h>
31 #include <vtkDataSet.h>
32 #include <vtkDataSetAttributes.h>
33 #include <vtkDemandDrivenPipeline.h>
34 #include <vtkDoubleArray.h>
35 #include <vtkExecutive.h>
36 #include <vtkFloatArray.h>
37 #include <vtkInEdgeIterator.h>
38 #include <vtkInformation.h>
39 #include <vtkInformationDataObjectKey.h>
40 #include <vtkInformationDataObjectMetaDataKey.h>
41 #include <vtkInformationStringKey.h>
42 #include <vtkInformationVector.h>
43 #include <vtkIntArray.h>
44 #include <vtkLongArray.h>
45 #include <vtkMultiBlockDataSet.h>
46 #include <vtkMutableDirectedGraph.h>
47 #include <vtkObjectFactory.h>
48 #include <vtkPointData.h>
49 #include <vtkPolyData.h>
50 #include <vtkRectilinearGrid.h>
51 #include <vtkStreamingDemandDrivenPipeline.h>
52 #include <vtkStringArray.h>
53 #include <vtkTimeStamp.h>
54 #include <vtkUnsignedCharArray.h>
55 #include <vtkUnstructuredGrid.h>
56 #include <vtkVariantArray.h>
57 #include <vtkWarpScalar.h>
58
59 #include "MEDCouplingFieldDouble.hxx"
60 #include "MEDCouplingFieldFloat.hxx"
61 #include "MEDCouplingFieldInt.hxx"
62 #include "MEDCouplingMemArray.hxx"
63 #include "MEDCouplingRefCountObject.hxx"
64 #include "MEDFileData.hxx"
65 #include "MEDFileField.hxx"
66 #include "MEDFileMesh.hxx"
67 #include "MEDLoaderTraits.hxx"
68
69 #include <deque>
70 #include <map>
71 #include <sstream>
72
73 vtkStandardNewMacro(vtkMEDWriter)
74
75 using MEDCoupling::MCAuto;
76 using MEDCoupling::MEDFileData;
77 using VTKToMEDMem::Fam;
78 using VTKToMEDMem::Grp;
79
80 vtkInformationDataObjectMetaDataKey* GetMEDReaderMetaDataIfAny()
81 {
82   static const char ZE_KEY[] = "vtkMEDReader::META_DATA";
83   MEDCoupling::GlobalDict* gd(MEDCoupling::GlobalDict::GetInstance());
84   if (!gd->hasKey(ZE_KEY))
85     return 0;
86   std::string ptSt(gd->value(ZE_KEY));
87   void* pt(0);
88   std::istringstream iss(ptSt);
89   iss >> pt;
90   return reinterpret_cast<vtkInformationDataObjectMetaDataKey*>(pt);
91 }
92
93 bool IsInformationOK(vtkInformation* info)
94 {
95   vtkInformationDataObjectMetaDataKey* key(GetMEDReaderMetaDataIfAny());
96   if (!key)
97     return false;
98   // Check the information contain meta data key
99   if (!info->Has(key))
100     return false;
101   // Recover Meta Data
102   vtkMutableDirectedGraph* sil(vtkMutableDirectedGraph::SafeDownCast(info->Get(key)));
103   if (!sil)
104     return false;
105   int idNames(0);
106   vtkAbstractArray* verticesNames(sil->GetVertexData()->GetAbstractArray("Names", idNames));
107   vtkStringArray* verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
108   if (!verticesNames2)
109     return false;
110   for (int i = 0; i < verticesNames2->GetNumberOfValues(); i++)
111   {
112     vtkStdString& st(verticesNames2->GetValue(i));
113     if (st == "MeshesFamsGrps")
114       return true;
115   }
116   return false;
117 }
118
119 void LoadFamGrpMapInfo(vtkMutableDirectedGraph* sil, std::string& meshName,
120   std::vector<Grp>& groups, std::vector<Fam>& fams)
121 {
122   if (!sil)
123     throw MZCException("LoadFamGrpMapInfo : internal error !");
124   int idNames(0);
125   vtkAbstractArray* verticesNames(sil->GetVertexData()->GetAbstractArray("Names", idNames));
126   vtkStringArray* verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
127   vtkIdType id0;
128   bool found(false);
129   for (int i = 0; i < verticesNames2->GetNumberOfValues(); i++)
130   {
131     vtkStdString& st(verticesNames2->GetValue(i));
132     if (st == "MeshesFamsGrps")
133     {
134       id0 = i;
135       found = true;
136     }
137   }
138   if (!found)
139     throw INTERP_KERNEL::Exception(
140       "There is an internal error ! The tree on server side has not the expected look !");
141   vtkAdjacentVertexIterator* it0(vtkAdjacentVertexIterator::New());
142   sil->GetAdjacentVertices(id0, it0);
143   while (it0->HasNext())
144   {
145     vtkIdType id1(it0->Next());
146     std::string mName((const char*)verticesNames2->GetValue(id1));
147     meshName = mName;
148     vtkAdjacentVertexIterator* it1(vtkAdjacentVertexIterator::New());
149     sil->GetAdjacentVertices(id1, it1);
150     vtkIdType idZeGrps(it1->Next()); // zeGroups
151     vtkAdjacentVertexIterator* itGrps(vtkAdjacentVertexIterator::New());
152     sil->GetAdjacentVertices(idZeGrps, itGrps);
153     while (itGrps->HasNext())
154     {
155       vtkIdType idg(itGrps->Next());
156       Grp grp((const char*)verticesNames2->GetValue(idg));
157       vtkAdjacentVertexIterator* itGrps2(vtkAdjacentVertexIterator::New());
158       sil->GetAdjacentVertices(idg, itGrps2);
159       std::vector<std::string> famsOnGroup;
160       while (itGrps2->HasNext())
161       {
162         vtkIdType idgf(itGrps2->Next());
163         famsOnGroup.push_back(std::string((const char*)verticesNames2->GetValue(idgf)));
164       }
165       grp.setFamilies(famsOnGroup);
166       itGrps2->Delete();
167       groups.push_back(grp);
168     }
169     itGrps->Delete();
170     vtkIdType idZeFams(it1->Next()); // zeFams
171     it1->Delete();
172     vtkAdjacentVertexIterator* itFams(vtkAdjacentVertexIterator::New());
173     sil->GetAdjacentVertices(idZeFams, itFams);
174     while (itFams->HasNext())
175     {
176       vtkIdType idf(itFams->Next());
177       Fam fam((const char*)verticesNames2->GetValue(idf));
178       fams.push_back(fam);
179     }
180     itFams->Delete();
181   }
182   it0->Delete();
183 }
184
185 vtkMEDWriter::vtkMEDWriter()
186   : WriteAllTimeSteps(0)
187   , NumberOfTimeSteps(0)
188   , CurrentTimeIndex(0)
189   , FileName(0)
190 {
191 }
192
193 vtkMEDWriter::~vtkMEDWriter() {}
194
195 int vtkMEDWriter::RequestInformation(
196   vtkInformation* /*request*/, vtkInformationVector** inputVector, vtkInformationVector* /*outputVector*/)
197 {
198   // std::cerr << "########################################## vtkMEDWriter::RequestInformation
199   // ########################################## " << (const char *) this->FileName << std::endl;
200   vtkInformation* inInfo(inputVector[0]->GetInformationObject(0));
201   if (inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()))
202     this->NumberOfTimeSteps = inInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
203   else
204     this->NumberOfTimeSteps = 0;
205   return 1;
206 }
207
208 int vtkMEDWriter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request),
209   vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector))
210 {
211   double* inTimes(
212     inputVector[0]->GetInformationObject(0)->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()));
213   if (inTimes && this->WriteAllTimeSteps)
214   {
215     double timeReq(inTimes[this->CurrentTimeIndex]);
216     inputVector[0]->GetInformationObject(0)->Set(
217       vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP(), timeReq);
218   }
219   return 1;
220 }
221
222 void ExceptionDisplayer(vtkMEDWriter* self, const std::string& fileName, std::exception& e)
223 {
224   std::ostringstream oss;
225   oss << "Exception has been thrown in vtkMEDWriter::RequestData : During writing of \"" << fileName
226       << "\", the following exception has been thrown : " << e.what() << std::endl;
227   if (self->HasObserver("ErrorEvent"))
228     self->InvokeEvent("ErrorEvent", const_cast<char*>(oss.str().c_str()));
229   else
230     vtkOutputWindowDisplayErrorText(const_cast<char*>(oss.str().c_str()));
231   vtkObject::BreakOnError();
232 }
233
234 int vtkMEDWriter::RequestData(
235   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
236 {
237   // std::cerr << "########################################## vtkMEDWriter::RequestData
238   // ########################################## " << (const char *) this->FileName << std::endl;
239   try
240   {
241     bool writeAll((this->WriteAllTimeSteps != 0 && this->NumberOfTimeSteps > 0));
242     if (writeAll)
243     {
244       if (this->CurrentTimeIndex == 0)
245         request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1);
246     }
247     else
248     {
249       request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING());
250       this->CurrentTimeIndex = 0;
251     }
252     //////////////
253     vtkInformation* inputInfo(inputVector[0]->GetInformationObject(0));
254     std::string meshName;
255     std::vector<Grp> groups;
256     std::vector<Fam> fams;
257     if (IsInformationOK(inputInfo))
258     {
259       vtkMutableDirectedGraph* famGrpGraph(
260         vtkMutableDirectedGraph::SafeDownCast(inputInfo->Get(GetMEDReaderMetaDataIfAny())));
261       LoadFamGrpMapInfo(famGrpGraph, meshName, groups, fams);
262     }
263     vtkInformation* outInfo(outputVector->GetInformationObject(0));
264     vtkDataObject* input(vtkDataObject::SafeDownCast(inputInfo->Get(vtkDataObject::DATA_OBJECT())));
265     if (!input)
266       throw MZCException(
267         "Not recognized data object in input of the MEDWriter ! Maybe not implemented yet !");
268     double timeStep;
269     {
270       vtkInformation* inInfo(inputVector[0]->GetInformationObject(0));
271       vtkDataObject* input(vtkDataObject::GetData(inInfo));
272       timeStep = input->GetInformation()->Get(vtkDataObject::DATA_TIME_STEP());
273     }
274     ////////////
275     MCAuto<MEDFileData> mfd(MEDFileData::New());
276     WriteMEDFileFromVTKGDS(mfd, input, timeStep, this->CurrentTimeIndex);
277     PutFamGrpInfoIfAny(mfd, meshName, groups, fams);
278     if (this->WriteAllTimeSteps == 0 ||
279       (this->WriteAllTimeSteps != 0 && this->CurrentTimeIndex == 0))
280       mfd->write(this->FileName, 2);
281     else
282     {
283       mfd->getFields()->write(this->FileName, 0);
284     }
285     outInfo->Set(vtkDataObject::DATA_OBJECT(), input);
286     ///////////
287     if (writeAll)
288     {
289       this->CurrentTimeIndex++;
290       if (this->CurrentTimeIndex >= this->NumberOfTimeSteps)
291       {
292         request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING());
293         this->CurrentTimeIndex = 0;
294       }
295     }
296   }
297   catch (INTERP_KERNEL::Exception& e)
298   {
299     ExceptionDisplayer(this, (const char*)this->FileName, e);
300     return 0;
301   }
302   catch (MZCException& e)
303   {
304     ExceptionDisplayer(this, (const char*)this->FileName, e);
305     return 0;
306   }
307   return 1;
308 }
309
310 void vtkMEDWriter::PrintSelf(ostream& os, vtkIndent indent)
311 {
312   this->Superclass::PrintSelf(os, indent);
313 }
314
315 int vtkMEDWriter::Write()
316 {
317   this->Update();
318   return 0;
319 }