Salome HOME
export preselected_id to client
[modules/paravis.git] / src / Plugins / MEDReader / plugin / MEDReaderIO / vtkFileSeriesGroupReader.cxx
1 // Copyright (C) 2022-2024  CEA, EDF
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 <vtkCollection.h>
23 #include <vtkInformation.h>
24 #include <vtkInformationVector.h>
25 #include <vtkMultiBlockDataSet.h>
26 #include <vtkMultiProcessController.h>
27 #include <vtkObjectFactory.h>
28 #include <vtkSmartPointer.h>
29 #include <vtkStreamingDemandDrivenPipeline.h>
30
31 #include "vtkMEDReader.h"
32
33 #include <vector>
34 #include <string>
35
36 vtkStandardNewMacro(vtkFileSeriesGroupReader);
37
38 //=============================================================================
39 struct vtkFileSeriesGroupReaderInternals
40 {
41   std::vector<std::string> FileNames;
42   vtkNew<vtkCollection> ReaderCollection;
43 };
44
45 //=============================================================================
46 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
47   : Internals(new vtkFileSeriesGroupReaderInternals())
48 {
49   this->SetNumberOfInputPorts(0);
50   this->SetNumberOfOutputPorts(1);
51 }
52
53 //-----------------------------------------------------------------------------
54 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
55
56 //----------------------------------------------------------------------------
57 void vtkFileSeriesGroupReader::AddFileName(const char* name)
58 {
59   // Make sure the reader always has a filename set
60   this->ReaderSetFileName(name);
61
62   this->AddFileNameInternal(name);
63   this->Modified();
64 }
65
66 //----------------------------------------------------------------------------
67 void vtkFileSeriesGroupReader::RemoveAllFileNames()
68 {
69   this->RemoveAllFileNamesInternal();
70   this->Modified();
71 }
72
73 //----------------------------------------------------------------------------
74 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
75 {
76   this->Internals->FileNames.clear();
77 }
78
79 //----------------------------------------------------------------------------
80 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
81 {
82   this->Internals->FileNames.emplace_back(name);
83 }
84
85 //----------------------------------------------------------------------------
86 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
87 {
88   return static_cast<unsigned int>(this->Internals->FileNames.size());
89 }
90
91 //----------------------------------------------------------------------------
92 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
93 {
94   if (idx >= this->Internals->FileNames.size())
95   {
96     return nullptr;
97   }
98   return this->Internals->FileNames[idx].c_str();
99 }
100
101 //----------------------------------------------------------------------------
102 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
103 {
104   if (!this->Reader)
105   {
106     return 0;
107   }
108
109   return this->ReaderCanReadFile(filename);
110 }
111
112 //----------------------------------------------------------------------------
113 int vtkFileSeriesGroupReader::RequestInformation(
114   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
115 {
116   return this->Reader->ProcessRequest(request, inputVector, outputVector);
117 }
118
119 //----------------------------------------------------------------------------
120 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
121   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
122 {
123   auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
124   unsigned int nBlock = this->GetNumberOfFileNames();
125   output->SetNumberOfBlocks(nBlock);
126
127   vtkInformation* info = outputVector->GetInformationObject(0);
128   double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
129
130   vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
131   unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
132   unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
133
134   // Simple case, one file/bloc for n proc
135   if (nBlock == 1)
136   {
137     // Make sure the information is up to date
138     this->ReaderSetFileName(this->GetFileName(0));
139     this->Reader->UpdateInformation();
140
141     this->Reader->UpdateTimeStep(time);
142     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
143     output->SetBlock(0, outputReader);
144
145     // Copy the GAUSS_DATA info key
146     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
147     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
148     {
149       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
150     }
151   }
152   // N file/block read by m proc, with n <= m, means 0/1 file/block per proc
153   else if (nBlock <= nProc && iProc < nBlock)
154   {
155     // Distribute in MEDReader only when reading a single file in a single block
156     vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
157
158     // Needed as the MEDReader do not support changing its filename
159     // without reloading everything.
160     this->ReaderSetFileName(this->GetFileName(iProc));
161     vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
162     this->Reader->UpdateInformation();
163
164     this->Reader->UpdateTimeStep(time);
165     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
166     output->SetBlock(iProc, outputReader);
167
168     // Copy the GAUSS_DATA info key
169     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
170     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
171     {
172       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
173     }
174   }
175   // Multiple files/block per proc
176   else
177   {
178     unsigned int nFiles = nBlock / nProc;
179     unsigned int offFile = iProc * nFiles;
180     unsigned int supFiles = nBlock % nProc;
181
182     // Last proc handle remaining files/block
183     if (iProc + 1 == nProc)
184     {
185       nFiles += supFiles;
186     }
187
188     vtkMEDReader* exposedReader = vtkMEDReader::SafeDownCast(this->Reader);
189     this->Internals->ReaderCollection->RemoveAllItems();
190     for (unsigned int i = 0; i < nFiles; i++)
191     {
192       // Create as many MEDReader as we need to avoid deep copy
193       vtkNew<vtkMEDReader> localReader;
194       this->Internals->ReaderCollection->AddItem(localReader.Get());
195
196       for (int iField = 0; iField < exposedReader->GetNumberOfFieldsTreeArrays(); iField++)
197       {
198         const char* name = exposedReader->GetFieldsTreeArrayName(iField);
199         localReader->SetFieldsStatus(name, exposedReader->GetFieldsTreeArrayStatus(name));
200       }
201       for (int iTimes = 0; iTimes < exposedReader->GetNumberOfTimesFlagsArrays(); iTimes++)
202       {
203         const char* name = exposedReader->GetTimesFlagsArrayName(iTimes);
204         localReader->SetTimesFlagsStatus(name, exposedReader->GetTimesFlagsArrayStatus(name));
205       }
206       localReader->GenerateVectors(exposedReader->GetGenerateVect());
207       localReader->ChangeMode(exposedReader->GetIsStdOrMode());
208       localReader->GhostCellGeneratorCallForPara(exposedReader->GetGCGCP());
209       localReader->GetRidOffDebugArrays(exposedReader->GetRemoveDebugArrays());
210
211       // Configure the localReader for usage with the files
212       localReader->SetFileName(this->GetFileName(i + offFile));
213       localReader->SetDistributeWithMPI(false);
214       localReader->UpdateInformation();
215       localReader->UpdateTimeStep(time);
216
217       vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(localReader->GetOutputDataObject(0))->GetBlock(0);
218       output->SetBlock(i + offFile, outputReader);
219
220       if (i == 0)
221       {
222         // Copy the GAUSS_DATA info key of the first filename
223         vtkInformation* mInfo = localReader->GetOutputInformation(0);
224         if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
225         {
226           info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
227         }
228       }
229     }
230   }
231   return 1;
232 }
233
234 //------------------------------------------------------------------------------
235 int vtkFileSeriesGroupReader::FillOutputPortInformation(
236   int vtkNotUsed(port), vtkInformation* info)
237 {
238   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
239   return 1;
240 }
241
242 //-----------------------------------------------------------------------------
243 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
244 {
245   this->Superclass::PrintSelf(os, indent);
246
247   os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")
248      << endl;
249 }