1 // Copyright (C) 2022 CEA/DEN, 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
20 #include "vtkFileSeriesGroupReader.h"
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>
31 #include "vtkMEDReader.h"
36 vtkStandardNewMacro(vtkFileSeriesGroupReader);
38 //=============================================================================
39 struct vtkFileSeriesGroupReaderInternals
41 std::vector<std::string> FileNames;
42 vtkNew<vtkCollection> ReaderCollection;
45 //=============================================================================
46 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
47 : Internals(new vtkFileSeriesGroupReaderInternals())
49 this->SetNumberOfInputPorts(0);
50 this->SetNumberOfOutputPorts(1);
53 //-----------------------------------------------------------------------------
54 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
56 //----------------------------------------------------------------------------
57 void vtkFileSeriesGroupReader::AddFileName(const char* name)
59 // Make sure the reader always has a filename set
60 this->ReaderSetFileName(name);
62 this->AddFileNameInternal(name);
66 //----------------------------------------------------------------------------
67 void vtkFileSeriesGroupReader::RemoveAllFileNames()
69 this->RemoveAllFileNamesInternal();
73 //----------------------------------------------------------------------------
74 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
76 this->Internals->FileNames.clear();
79 //----------------------------------------------------------------------------
80 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
82 this->Internals->FileNames.emplace_back(name);
85 //----------------------------------------------------------------------------
86 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
88 return static_cast<unsigned int>(this->Internals->FileNames.size());
91 //----------------------------------------------------------------------------
92 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
94 if (idx >= this->Internals->FileNames.size())
98 return this->Internals->FileNames[idx].c_str();
101 //----------------------------------------------------------------------------
102 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
109 return this->ReaderCanReadFile(filename);
112 //----------------------------------------------------------------------------
113 int vtkFileSeriesGroupReader::RequestInformation(
114 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
116 return this->Reader->ProcessRequest(request, inputVector, outputVector);
119 //----------------------------------------------------------------------------
120 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
121 vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
123 auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
124 unsigned int nBlock = this->GetNumberOfFileNames();
125 output->SetNumberOfBlocks(nBlock);
127 vtkInformation* info = outputVector->GetInformationObject(0);
128 double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
130 vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
131 unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
132 unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
134 // Simple case, one file/bloc for n proc
137 // Make sure the information is up to date
138 this->ReaderSetFileName(this->GetFileName(0));
139 this->Reader->UpdateInformation();
141 this->Reader->UpdateTimeStep(time);
142 vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
143 output->SetBlock(0, outputReader);
145 // Copy the GAUSS_DATA info key
146 vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
147 if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
149 info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
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)
155 // Distribute in MEDReader only when reading a single file in a single block
156 vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
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();
164 this->Reader->UpdateTimeStep(time);
165 vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
166 output->SetBlock(iProc, outputReader);
168 // Copy the GAUSS_DATA info key
169 vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
170 if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
172 info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
175 // Multiple files/block per proc
178 unsigned int nFiles = nBlock / nProc;
179 unsigned int offFile = iProc * nFiles;
180 unsigned int supFiles = nBlock % nProc;
182 // Last proc handle remaining files/block
183 if (iProc + 1 == nProc)
188 vtkMEDReader* exposedReader = vtkMEDReader::SafeDownCast(this->Reader);
189 this->Internals->ReaderCollection->RemoveAllItems();
190 for (unsigned int i = 0; i < nFiles; i++)
192 // Create as many MEDReader as we need to avoid deep copy
193 vtkNew<vtkMEDReader> localReader;
194 this->Internals->ReaderCollection->AddItem(localReader.Get());
196 for (int iField = 0; iField < exposedReader->GetNumberOfFieldsTreeArrays(); iField++)
198 const char* name = exposedReader->GetFieldsTreeArrayName(iField);
199 localReader->SetFieldsStatus(name, exposedReader->GetFieldsTreeArrayStatus(name));
201 for (int iTimes = 0; iTimes < exposedReader->GetNumberOfTimesFlagsArrays(); iTimes++)
203 const char* name = exposedReader->GetTimesFlagsArrayName(iTimes);
204 localReader->SetTimesFlagsStatus(name, exposedReader->GetTimesFlagsArrayStatus(name));
206 localReader->GenerateVectors(exposedReader->GetGenerateVect());
207 localReader->ChangeMode(exposedReader->GetIsStdOrMode());
208 localReader->GhostCellGeneratorCallForPara(exposedReader->GetGCGCP());
210 // Configure the localReader for usage with the files
211 localReader->SetFileName(this->GetFileName(i + offFile));
212 localReader->SetDistributeWithMPI(false);
213 localReader->UpdateInformation();
214 localReader->UpdateTimeStep(time);
216 vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(localReader->GetOutputDataObject(0))->GetBlock(0);
217 output->SetBlock(i + offFile, outputReader);
221 // Copy the GAUSS_DATA info key of the first filename
222 vtkInformation* mInfo = localReader->GetOutputInformation(0);
223 if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
225 info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
233 //------------------------------------------------------------------------------
234 int vtkFileSeriesGroupReader::FillOutputPortInformation(
235 int vtkNotUsed(port), vtkInformation* info)
237 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
241 //-----------------------------------------------------------------------------
242 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
244 this->Superclass::PrintSelf(os, indent);
246 os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")