Salome HOME
Copy GAUSS_DATA key
[modules/paravis.git] / src / Plugins / MEDReader / plugin / MEDReaderIO / vtkFileSeriesGroupReader.cxx
1 // Copyright (C) 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
20 #include "vtkFileSeriesGroupReader.h"
21
22 #include <vtkInformation.h>
23 #include <vtkInformationVector.h>
24 #include <vtkMultiBlockDataSet.h>
25 #include <vtkMultiProcessController.h>
26 #include <vtkObjectFactory.h>
27 #include <vtkSmartPointer.h>
28 #include <vtkStreamingDemandDrivenPipeline.h>
29
30 #include "vtkMEDReader.h"
31
32 #include <vector>
33 #include <string>
34
35 vtkStandardNewMacro(vtkFileSeriesGroupReader);
36
37 //=============================================================================
38 struct vtkFileSeriesGroupReaderInternals
39 {
40   std::vector<std::string> FileNames;
41 };
42
43 //=============================================================================
44 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
45   : Internals(new vtkFileSeriesGroupReaderInternals())
46 {
47   this->SetNumberOfInputPorts(0);
48   this->SetNumberOfOutputPorts(1);
49 }
50
51 //-----------------------------------------------------------------------------
52 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
53
54 //----------------------------------------------------------------------------
55 void vtkFileSeriesGroupReader::AddFileName(const char* name)
56 {
57   // Make sure the reader always has a filename set
58   this->ReaderSetFileName(name);
59
60   this->AddFileNameInternal(name);
61   this->Modified();
62 }
63
64 //----------------------------------------------------------------------------
65 void vtkFileSeriesGroupReader::RemoveAllFileNames()
66 {
67   this->RemoveAllFileNamesInternal();
68   this->Modified();
69 }
70
71 //----------------------------------------------------------------------------
72 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
73 {
74   this->Internals->FileNames.clear();
75 }
76
77 //----------------------------------------------------------------------------
78 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
79 {
80   this->Internals->FileNames.emplace_back(name);
81 }
82
83 //----------------------------------------------------------------------------
84 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
85 {
86   return static_cast<unsigned int>(this->Internals->FileNames.size());
87 }
88
89 //----------------------------------------------------------------------------
90 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
91 {
92   if (idx >= this->Internals->FileNames.size())
93   {
94     return nullptr;
95   }
96   return this->Internals->FileNames[idx].c_str();
97 }
98
99 //----------------------------------------------------------------------------
100 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
101 {
102   if (!this->Reader)
103   {
104     return 0;
105   }
106
107   return this->ReaderCanReadFile(filename);
108 }
109
110 //----------------------------------------------------------------------------
111 int vtkFileSeriesGroupReader::RequestInformation(
112   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
113 {
114   return this->Reader->ProcessRequest(request, inputVector, outputVector);
115 }
116
117 //----------------------------------------------------------------------------
118 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
119   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
120 {
121   auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
122   unsigned int nBlock = this->GetNumberOfFileNames();
123   output->SetNumberOfBlocks(nBlock);
124
125   vtkInformation* info = outputVector->GetInformationObject(0);
126   double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
127
128   vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
129   unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
130   unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
131
132   // Simple case, one file/block per proc
133   if (nBlock == 1 || (nBlock <= nProc && iProc < nBlock))
134   {
135     // Distribute in MEDReader only when reading a single file in a single block
136     iProc = nBlock == 1 ? 0 : iProc;
137     vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(nBlock == 1);
138
139     this->ReaderSetFileName(this->GetFileName(iProc));
140
141     // Needed only when reading a different file on each proc
142     if (nBlock != 1)
143     {
144       vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
145       this->Reader->UpdateInformation();
146     }
147
148     this->Reader->UpdateTimeStep(time);
149     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
150     output->SetBlock(iProc, outputReader);
151
152     // Copy the GAUSS_DATA info key
153     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
154     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
155     {
156       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
157     }
158   }
159   else
160   {
161     // Multiple files/block per proc
162     unsigned int nFiles = nBlock / nProc;
163     unsigned int offFile = iProc * nFiles;
164     unsigned int supFiles = nBlock % nProc;
165
166     // Last proc handle remaining files/block
167     if (iProc + 1 == nProc)
168     {
169       nFiles += supFiles;
170     }
171
172     for (unsigned int i = 0; i < nFiles; i++)
173     {
174       this->ReaderSetFileName(this->GetFileName(i + offFile));
175       vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
176       vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
177       this->Reader->UpdateInformation();
178       this->Reader->UpdateTimeStep(time);
179       vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
180       if (i + 1 == nFiles)
181       {
182         // Last reader, just use the reader output directly
183         output->SetBlock(i + offFile, outputReader);
184       }
185       else
186       {
187         // Need to deep copy as the reader will be reused
188         vtkSmartPointer<vtkDataObject> outputLeaf = vtkSmartPointer<vtkDataObject>::Take(outputReader->NewInstance());
189         outputLeaf->DeepCopy(outputReader);
190         output->SetBlock(i + offFile, outputLeaf);
191       }
192     }
193
194     // Copy the GAUSS_DATA info key for the last reader
195     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
196     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
197     {
198       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
199     }
200   }
201   return 1;
202 }
203
204 //------------------------------------------------------------------------------
205 int vtkFileSeriesGroupReader::FillOutputPortInformation(
206   int vtkNotUsed(port), vtkInformation* info)
207 {
208   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
209   return 1;
210 }
211
212 //-----------------------------------------------------------------------------
213 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
214 {
215   this->Superclass::PrintSelf(os, indent);
216
217   os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")
218      << endl;
219 }