VirtualFluids 0.2.0
Parallel CFD LBM Solver
Loading...
Searching...
No Matches
FileWriter.cpp
Go to the documentation of this file.
1//=======================================================================================
2// ____ ____ __ ______ __________ __ __ __ __
3// \ \ | | | | | _ \ |___ ___| | | | | / \ | |
4// \ \ | | | | | |_) | | | | | | | / \ | |
5// \ \ | | | | | _ / | | | | | | / /\ \ | |
6// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____
7// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______|
8// \ \ | | ________________________________________________________________
9// \ \ | | | ______________________________________________________________|
10// \ \| | | | __ __ __ __ ______ _______
11// \ | | |_____ | | | | | | | | | _ \ / _____)
12// \ | | _____| | | | | | | | | | | \ \ \_______
13// \ | | | | |_____ | \_/ | | | | |_/ / _____ |
14// \ _____| |__| |________| \_______/ |__| |______/ (_______/
15//
16// This file is part of VirtualFluids. VirtualFluids is free software: you can
17// redistribute it and/or modify it under the terms of the GNU General Public
18// License as published by the Free Software Foundation, either version 3 of
19// the License, or (at your option) any later version.
20//
21// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
22// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24// for more details.
25//
26// SPDX-License-Identifier: GPL-3.0-or-later
27// SPDX-FileCopyrightText: Copyright © VirtualFluids Project contributors, see AUTHORS.md in root folder
28//
33//=======================================================================================
34#include "FileWriter.h"
35
36#include <cmath>
37#include <cstdio>
38#include <fstream>
39#include <sstream>
40
43
44#include <logger/Logger.h>
45
46#include <lbm/constants/D3Q27.h>
47
50#include "FilePartCalculator.h"
51#include "Parameter/Parameter.h"
52#include "WriterUtilities.h"
53
54namespace vf::gpu {
55
56std::string makeCollectionFileNameEnding(int ID, int timestep)
57{
58 return "_ID_" + StringUtil::toString<int>(ID) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk";
59}
60
61std::string makePartFileName(const std::string &prefix, uint level, int ID, int part, int timestep)
62{
63 return prefix + "_bin" + WriterUtilities::makePartFileNameEnding(level, ID, part, timestep);
64}
65
66std::string makeMeanPartFileName(const std::string &prefix, uint level, int ID, int part, int timestep)
67{
68 return prefix + "_bin_mean" + WriterUtilities::makePartFileNameEnding(level, ID, part, timestep);
69}
70
71
72std::string makeCollectionFileName(const std::string &prefix, int ID, int timestep)
73{
74 return prefix + "_bin" + makeCollectionFileNameEnding(ID, timestep);
75}
76
77std::string makeMeanCollectionFileName(const std::string &prefix, int ID, int timestep)
78{
79 return prefix + "_bin_mean" + makeCollectionFileNameEnding(ID, timestep);
80}
81
82std::string makePvdCollectionFileName(const std::string &prefix, int mpiProcessID)
83{
84 return prefix + "_bin" + "_ID_" + StringUtil::toString<int>(mpiProcessID);
85}
86
87
88void FileWriter::writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaMemoryManager)
89{
90 unsigned int timestep = para->getTimestepInit();
91 for (int level = para->getCoarse(); level <= para->getFine(); level++) {
92 cudaMemoryManager->cudaCopyPrint(level);
93 writeTimestep(para, timestep, level);
94 }
95
96 this->fileNamesForCollectionFileTimeSeries[timestep] = this->fileNamesForCollectionFile;
97 this->writeCollectionFile(para, timestep);
98
99 if( para->getCalcMean() )
100 this->writeCollectionFileMean(para, timestep);
101}
102
103void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep)
104{
105 for (int level = para->getCoarse(); level <= para->getFine(); level++)
106 writeTimestep(para, timestep, level);
107
108 this->fileNamesForCollectionFileTimeSeries[timestep] = this->fileNamesForCollectionFile;
109 if (timestep == para->getTimestepEnd())
110 this->writePvdCollectionFileForTimeSeries(*para);
111
112 this->writeCollectionFile(para, timestep);
113
114 if( para->getCalcMean() )
115 this->writeCollectionFileMean(para, timestep);
116}
117
118void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep, int level)
119{
120 const unsigned int numberOfParts = FilePartCalculator::calculateNumberOfParts(para->getParH(level)->numberOfNodes);
121 std::vector<std::string> fnames;
122 std::vector<std::string> fnamesMed;
123
124 for (unsigned int i = 1; i <= numberOfParts; i++)
125 {
126 std::string fname = makePartFileName(para->getFName(), level, para->getMyProcessID(), i, timestep);
127 std::string fnameMed = makeMeanPartFileName(para->getFName(), level, para->getMyProcessID(), i, timestep);
128
129 fnames.push_back(fname);
130 fnamesMed.push_back(fnameMed);
131 }
132
133 std::vector<std::string> fnamesLong = writeUnstructuredGridLT(para, level, fnames);
134 for(auto fname : fnamesLong)
135 this->fileNamesForCollectionFile.push_back(fname.substr( fname.find_last_of('/') + 1 ));
136
137 if (para->getCalcMean())
138 {
139 std::vector<std::string> fnamesMeanLong = writeUnstructuredGridMeanLT(para, level, fnamesMed);
140 for(auto fname : fnamesMeanLong)
141 this->fileNamesForCollectionFileMean.push_back(fname.substr( fname.find_last_of('/') + 1 ));
142 }
143}
144
145std::vector<std::string> FileWriter::getNodeDataNames(std::shared_ptr<Parameter> para)
146{
147
148 std::vector<std::string> nodeDataNames;
149 nodeDataNames.push_back("press");
150 nodeDataNames.push_back("rho");
151 nodeDataNames.push_back("vx1");
152 nodeDataNames.push_back("vx2");
153 nodeDataNames.push_back("vx3");
154 nodeDataNames.push_back("geo");
155
156 if(para->getDiffOn())
157 nodeDataNames.push_back("conc");
158
159 if(para->getIsBodyForce())
160 {
161 nodeDataNames.push_back("Fx");
162 nodeDataNames.push_back("Fy");
163 nodeDataNames.push_back("Fz");
164 }
165
166 if(para->getUseTurbulentViscosity())
167 {
168 nodeDataNames.push_back("nut");
169 }
170
171 if (para->getCalcTurbulenceIntensity()) {
172 nodeDataNames.push_back("vxx");
173 nodeDataNames.push_back("vyy");
174 nodeDataNames.push_back("vzz");
175 nodeDataNames.push_back("vxy");
176 nodeDataNames.push_back("vxz");
177 nodeDataNames.push_back("vyz");
178 }
179 return nodeDataNames;
180}
181
182std::vector<std::string> FileWriter::getMeanNodeDataNames(std::shared_ptr<Parameter> para)
183{
184 std::vector<std::string> nodeDataNames;
185
186 if(para->getDiffOn())
187 nodeDataNames.push_back("conc");
188 nodeDataNames.push_back("pressMed");
189 nodeDataNames.push_back("rhoMed");
190 nodeDataNames.push_back("vx1Med");
191 nodeDataNames.push_back("vx2Med");
192 nodeDataNames.push_back("vx3Med");
193 nodeDataNames.push_back("geo");
194
195 return nodeDataNames;
196}
197
198std::string FileWriter::writeCollectionFile(std::shared_ptr<Parameter> para, unsigned int timestep)
199{
200 std::string filename = makeCollectionFileName(para->getFName(), para->getMyProcessID(), timestep);
201 auto nodeDataNames = this->getNodeDataNames(para);
202 std::vector<std::string> cellDataNames;
203 std::string pFileName= WbWriterVtkXmlBinary::getInstance()->writeParallelFile(filename, this->fileNamesForCollectionFile, nodeDataNames, cellDataNames);
204 this->fileNamesForCollectionFile.clear();
205 return pFileName;
206}
207
208std::string FileWriter::writeCollectionFileMean(std::shared_ptr<Parameter> para, unsigned int timestep)
209{
210 std::string filename = makeMeanCollectionFileName(para->getFName(), para->getMyProcessID(), timestep);
211 std::vector<std::string> nodeDataNames = getMeanNodeDataNames(para);
212 std::vector<std::string> cellDataNames;
213 std::string pFileName = WbWriterVtkXmlBinary::getInstance()->writeParallelFile(filename, this->fileNamesForCollectionFileMean, nodeDataNames, cellDataNames);
214 this->fileNamesForCollectionFileMean.clear();
215 return pFileName;
216}
217
218std::string FileWriter::writePvdCollectionFileForTimeSeries(const Parameter &para)
219{
220 const std::string filename = makePvdCollectionFileName(para.getFName(), para.getMyProcessID());
221 return WbWriterVtkXmlBinary::getInstance()->writeCollectionForTimeSeries(filename, this->fileNamesForCollectionFileTimeSeries, false);
222}
223
224std::vector<std::string> FileWriter::writeUnstructuredGridLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
225{
226 std::vector< UbTupleFloat3 > nodes;
227 std::vector< UbTupleUInt8 > cells;
228 std::vector< std::string > nodeDataNames = getNodeDataNames(para);
229
230 std::vector< std::string > outFNames;
231
232 uint dataIndex = 6;
233
235 if(para->getDiffOn()) dataIndex++;
236
238 if(para->getIsBodyForce()) dataIndex+=3;
239
241 if(para->getUseTurbulentViscosity()) dataIndex++;
242
244 if (para->getCalcTurbulenceIntensity()) dataIndex += 6;
245
246 std::array<uint, 8> indicesOfOct;
247 std::array<uint, 8> relativePosInPart;
249 bool allNodesValid;
250 unsigned int startPosition;
251 unsigned int endPosition;
252 unsigned int sizeOfNodes;
253 std::vector< std::vector< double > > nodeData(nodeDataNames.size());
254
255 for (unsigned int part = 0; part < fname.size(); part++)
256 {
257 const LBMSimulationParameter& parH = para->getParHostAsReference(level);
259
262 endPosition = startPosition + sizeOfNodes;
264 cells.clear();
265 nodes.resize(sizeOfNodes);
266 for (uint i = 0; i < (uint)nodeDataNames.size(); i++)
267 nodeData[i].resize(sizeOfNodes);
268
270 for (unsigned int pos = startPosition; pos < endPosition; pos++) {
271 if (parH.typeOfGridNode[pos] == GEO_FLUID) {
273 double x1 = parH.coordinateX[pos];
274 double x2 = parH.coordinateY[pos];
275 double x3 = parH.coordinateZ[pos];
277 relPosInPart = pos - startPosition;
279 nodes[relPosInPart] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
280 nodeData[0][relPosInPart] = (double)parH.pressure[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
281 nodeData[1][relPosInPart] = (double)parH.rho[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
282 nodeData[2][relPosInPart] = (double)parH.velocityX[pos] * (double)para->getVelocityRatio();
283 nodeData[3][relPosInPart] = (double)parH.velocityY[pos] * (double)para->getVelocityRatio();
284 nodeData[4][relPosInPart] = (double)parH.velocityZ[pos] * (double)para->getVelocityRatio();
285 nodeData[5][relPosInPart] = (double)parH.typeOfGridNode[pos];
286
287 if(para->getDiffOn())
288 nodeData[firstConcNode][relPosInPart] = (double)parH.concentration[pos];
289
290 if(para->getIsBodyForce())
291 {
292 nodeData[firstBodyForceNode ][relPosInPart] = (double)parH.forceX_SP[pos] * (double)para->getScaledForceRatio(level);
293 nodeData[firstBodyForceNode + 1][relPosInPart] = (double)parH.forceY_SP[pos] * (double)para->getScaledForceRatio(level);
294 nodeData[firstBodyForceNode + 2][relPosInPart] = (double)parH.forceZ_SP[pos] * (double)para->getScaledForceRatio(level);
295 }
296
297 if(para->getUseTurbulentViscosity())
298 {
299 nodeData[firstNutNode][relPosInPart] = (double)parH.turbulentViscosity[pos] * (double)para->getScaledViscosityRatio(level);
300 }
301
302 if (para->getCalcTurbulenceIntensity()) {
309 }
310
312
313 WriterUtilities::getIndicesOfAllNodesInOct(indicesOfOct, pos, para->getParHostAsReference(level));
314
316 continue;
317 }
318
321
323 if (allNodesValid) {
325 cells.push_back(makeUbTupleFromArray(relativePosInPart));
326 }
327 }
328 }
329 outFNames.push_back( WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodeDataNames, nodeData) );
330 }
331 return outFNames;
332}
333
334std::vector<std::string> FileWriter::writeUnstructuredGridMeanLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
335{
336 std::vector< std::string > outFNames;
337
338 std::vector< UbTupleFloat3 > nodes;
339 std::vector< UbTupleUInt8 > cells;
340 //std::vector< UbTupleUInt8 > cells2;
341 std::vector< std::string > nodeDataNames = getMeanNodeDataNames(para);
342 int startIndex = para->getDiffOn()? 1 : 0;
343
345 unsigned int dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
346 bool neighborsFluid;
347 unsigned int startPosition;
348 unsigned int endPosition;
349 unsigned int sizeOfNodes;
350 std::vector< std::vector< double > > nodeData(nodeDataNames.size());
351
352 //printf("\n test for if... \n");
353 for (unsigned int part = 0; part < fname.size(); part++)
354 {
355 //printf("\n test in if I... \n");
357 sizeOfNodes = FilePartCalculator::calculateNumberOfNodesInPart(para->getParH(level)->numberOfNodes, part);
360 endPosition = startPosition + sizeOfNodes;
362 cells.clear();
363 nodes.resize(sizeOfNodes);
364 for (size_t i = 0; i < nodeDataNames.size(); i++)
365 nodeData[i].resize(sizeOfNodes);
367 //printf("\n test in if II... \n");
368 for (unsigned int pos = startPosition; pos < endPosition; pos++)
369 {
370 if (para->getParH(level)->typeOfGridNode[pos] == GEO_FLUID)
371 {
373 double x1 = para->getParH(level)->coordinateX[pos];
374 double x2 = para->getParH(level)->coordinateY[pos];
375 double x3 = para->getParH(level)->coordinateZ[pos];
377 number1 = pos;
378 dn1 = pos - startPosition;
379 neighborsFluid = true;
381 nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
382 if(para->getDiffOn())
383 nodeData[0][dn1] = (double)para->getParH(level)->meanConcentrationOut[pos];
384 nodeData[startIndex ][dn1] = para->getParH(level)->meanPressureOut[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
385 nodeData[startIndex + 1][dn1] = para->getParH(level)->meanDensityOut[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
386 nodeData[startIndex + 2][dn1] = para->getParH(level)->meanVelocityInXdirectionOut[pos] * para->getVelocityRatio();
387 nodeData[startIndex + 3][dn1] = para->getParH(level)->meanVelocityInYdirectionOut[pos] * para->getVelocityRatio();
388 nodeData[startIndex + 4][dn1] = para->getParH(level)->meanVelocityInZdirectionOut[pos] * para->getVelocityRatio();
389 nodeData[startIndex + 5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
391 number2 = para->getParH(level)->neighborX[number1];
392 number3 = para->getParH(level)->neighborY[number2];
393 number4 = para->getParH(level)->neighborY[number1];
394 number5 = para->getParH(level)->neighborZ[number1];
395 number6 = para->getParH(level)->neighborZ[number2];
396 number7 = para->getParH(level)->neighborZ[number3];
397 number8 = para->getParH(level)->neighborZ[number4];
399 if (para->getParH(level)->typeOfGridNode[number2] != GEO_FLUID ||
400 para->getParH(level)->typeOfGridNode[number3] != GEO_FLUID ||
401 para->getParH(level)->typeOfGridNode[number4] != GEO_FLUID ||
402 para->getParH(level)->typeOfGridNode[number5] != GEO_FLUID ||
403 para->getParH(level)->typeOfGridNode[number6] != GEO_FLUID ||
404 para->getParH(level)->typeOfGridNode[number7] != GEO_FLUID ||
405 para->getParH(level)->typeOfGridNode[number8] != GEO_FLUID) neighborsFluid = false;
407 if (number2 > endPosition ||
408 number3 > endPosition ||
409 number4 > endPosition ||
410 number5 > endPosition ||
411 number6 > endPosition ||
412 number7 > endPosition ||
413 number8 > endPosition) neighborsFluid = false;
415 dn2 = number2 - startPosition;
416 dn3 = number3 - startPosition;
417 dn4 = number4 - startPosition;
418 dn5 = number5 - startPosition;
419 dn6 = number6 - startPosition;
420 dn7 = number7 - startPosition;
421 dn8 = number8 - startPosition;
423 if (WriterUtilities::isPeriodicCell(para->getParHostAsReference(level), number1, number7))
424 continue;
426 if (neighborsFluid == true) cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
428 }
429 }
430 outFNames.push_back(WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodeDataNames, nodeData));
432 }
433 return outFNames;
434}
435
436}
437
static WbWriterVtkXmlBinary * getInstance()
static uint calculateNumberOfParts(uint numberOfNodes)
calculate how many output vtk-files are created for one timestep of the given grid level
static uint calculateStartingPostionOfPart(uint indexOfPart)
static uint calculateNumberOfNodesInPart(uint numberOfNodes, uint indexOfFilePart)
calculate how many grid nodes are written to the file with the given index
void writeTimestep(std::shared_ptr< Parameter > para, unsigned int timestep) override
void writeInit(std::shared_ptr< Parameter > para, std::shared_ptr< CudaMemoryManager > cudaMemoryManager) override
static void getIndicesOfAllNodesInOct(std::array< uint, 8 > &nodeIndices, uint baseNodeOfOct, const LBMSimulationParameter &parH)
use the neighbor relations to find the indices of all nodes in an oct cell
static bool isPeriodicCell(const LBMSimulationParameter &parH, unsigned int baseNodeOfCell, unsigned int otherNodeInCell)
check whether a grid cell is part of a periodic boundary condition
static std::string makePartFileNameEnding(uint level, int processID, int part, int timestep)
create the ending of the file name for a file part
static void calculateRelativeNodeIndexInPart(std::array< uint, 8 > &relativePositionInPart, const std::array< uint, 8 > &indicesOfOct, uint startPositionOfPart)
calculate the node index relative to the start position of the part
static bool areAllNodesInOctValidForWriting(const std::array< uint, 8 > &indicesOfOct, const LBMSimulationParameter &parH, uint endPositionOfPart)
check if all nodes in an oct are valid to be written into an output file
std::shared_ptr< T > SPtr
unsigned int uint
Definition DataTypes.h:47
#define GEO_FLUID
Definition Calculation.h:45
UbTuple< T, T, T, T, T, T, T, T > makeUbTupleFromArray(const std::array< T, 8 > &array)
Definition UbTuple.h:601
UbTuple< T1 > makeUbTuple(T1 const &a1)
Definition UbTuple.h:542
std::string writeOctsWithNodeData(const std::string &filename, std::vector< UbTupleFloat3 > &nodes, std::vector< UbTupleUInt8 > &cells, std::vector< std::string > &datanames, std::vector< std::vector< double > > &nodedata) override
std::string writeParallelFile(const std::string &filename, std::vector< std::string > &pieceSources, std::vector< std::string > &pointDataNames, std::vector< std::string > &cellDataNames) const
std::string writeCollectionForTimeSeries(const std::string &filename, const std::map< uint, std::vector< std::string > > &filesNamesForTimeSteps, bool separateGroups) const
std::string makeCollectionFileName(const std::string &prefix, int ID, int timestep)
std::string makeMeanPartFileName(const std::string &prefix, uint level, int ID, int part, int timestep)
std::string makePartFileName(const std::string &prefix, uint level, int ID, int part, int timestep)
std::string makePvdCollectionFileName(const std::string &prefix, int mpiProcessID)
std::string makeMeanCollectionFileName(const std::string &prefix, int ID, int timestep)
std::string makeCollectionFileNameEnding(int ID, int timestep)