Microflow 3D  v1.0
MFSolver_CPU.cpp
Go to the documentation of this file.
1 // ==============================================================================================
2 // Microflow 3D, http://www.microflow.pwr.edu.pl/
3 // Created by Roman Szafran on 02.03.19.
4 // Modified by Roman Szafran, last on 11.10.2020.
5 // Copyright (c) 2020 Wroclaw University of Science and Technology.
6 // Distributed under the Apache License, Version 2.0. You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0 or see accompanying file license.txt.
8 // Redistributions of source code must retain the above copyright and license notice.
9 // ==============================================================================================
10 
11 // System
12 #include <iostream>
13 #include <memory>
14 #include <chrono>
15 
16 // MF
17 #include "ConsoleWriter.h"
18 #include "CmdLineArgsParser.h"
19 #include "ConfigData.h"
20 #include "ProgramParameters.h"
21 #include "CaseParameters.h"
22 #include "GeometryBuildFromSTL.h"
23 #include "AutoThreading.h"
24 #include "ThreadArray.h"
25 #include "BoundaryFunctions.h"
26 #include "FluidFunctions.h"
27 #include "Collision.h"
28 #include "Initialization.h"
29 #include "ParametersConversion.h"
30 
31 // OpenVDB
32 #include <openvdb/openvdb.h>
33 
34 //-------------------------------------------------------------------------------------------------------------
35 // Use for Development
36 // #define defaultPathToProgramConfigFile "../../Config/Microflow.cfg"
37 // Use for Release
38 #define defaultPathToProgramConfigFile "Config/Microflow.cfg"
39 #define defaultScope "MF01"
40 //-------------------------------------------------------------------------------------------------------------
41 
42 int main(int argc, char** argv) {
43 
44  const char* pPathToProgramConfigFile = defaultPathToProgramConfigFile;
45  // Use for Development
46  // const char* pPathToCaseFolder = "../../Data/Validation_tests/Case_MEDIUM_straight_square_channel";
47  // Use for Release
48  const char* pPathToCaseFolder = "Data/Validation_tests/Case_MEDIUM_straight_square_channel";
49  const char* pPathToCaseFile = "";
50  const char* pPathToThreadFile = "";
51  const char* pScope = defaultScope; // Scope of parameters appropriate for this solver
52  std::string tempString;
53  bool verbose = false; // Verbose mode
54  bool geometryOnly = false; // Only geometry generation and grid voxelization mode
55  auto exitStatus = 0;
56  auto CPU_ThreadsNr = 0;
57 
58 
59  // Microflow 3D let's start!
60  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
61  cout << "Microflow 3D v1.0 " << endl;
62  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
63 
65  cout << "Microflow framework >>> Initialization info:" << endl;
66 
67  // Initialize openvdb library.
68  openvdb::initialize();
69 
70  // Command line parameters parsing
71  auto CmdLineArgsParser_Ptr = MF::Parser::CmdLineArgsParser::New();
72  CmdLineArgsParser_Ptr->parseCmdLineArgs(argc, argv, pPathToProgramConfigFile, pPathToCaseFolder, pScope, verbose, geometryOnly, CPU_ThreadsNr); // Command line processing
73 
74  // Parsing solver, case and thread config files
75  auto ConfigData_Ptr = MF::Database::ConfigData::New(pPathToProgramConfigFile, pPathToCaseFolder, pScope, verbose);
76 
77  // End of Microflow framework initialization
78  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
80 
82  cout << "Microflow framework >>> Geometry building info: " << endl;
83 
84  auto LatticeParameters_Ptr = MF::GU::LatticeParametersD3Q19::New();
85  auto Geometry_Ptr = MF::GB::GeometryBuildFromSTL::New(ConfigData_Ptr,LatticeParameters_Ptr);
86  Geometry_Ptr->ReadGrid(verbose);
87  Geometry_Ptr->AutomaticBoundaryFind();
88  if (geometryOnly) {
89  Geometry_Ptr->WriteGeometryGridToVtiFile();
90  Geometry_Ptr->WriteGeometryGridToVDBFile();
91  cout << endl;
92  cout << "----------------------------------------------------------------------------------" << endl;
93  cout << "Geometry file has been generated ***** Goodbye *****" << endl;
94  cout << "----------------------------------------------------------------------------------" << endl;
95  exit(0);
96  }
97  Geometry_Ptr->FluidAddFromThreadFile();
98  Geometry_Ptr->SolidAddFromThreadFile();
99  Geometry_Ptr->BoundaryAddFromThreadFile();
100  Geometry_Ptr->Clean();
101 
102  // End of Microflow framework geometry building
103  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
105 
107  cout << "MFSolver_CPU >>> Case and program parameters initialization info: " << endl;
108 
109  // Program parameters initialization
110  auto ProgramParameters_Ptr = MF::Solver_CPU::ProgramParameters::New(ConfigData_Ptr); //Initialization of program parameters from parser object data
111 
112  // Case parameters initialisation
113  auto CaseParameters_Ptr = MF::Solver_CPU::CaseParameters::New(ConfigData_Ptr); //Initialization of case parameters from parser object data
114 
115  // Set up number of CPU threads to allocate computations
116  if (CPU_ThreadsNr == 0 && CaseParameters_Ptr->CPU_ThreadsNr == 0)
117  CPU_ThreadsNr = omp_get_num_procs();
118  else if (CPU_ThreadsNr == 0 && CaseParameters_Ptr->CPU_ThreadsNr != 0)
119  CPU_ThreadsNr = CaseParameters_Ptr->CPU_ThreadsNr;
120 
121  // End of case and program parameters initialisation
122  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
124 
126  cout << "MFDatabase >>> Threads building info: " << endl;
127 
128  auto ThreadArray_Ptr = MF::Database::ThreadArray::New(LatticeParameters_Ptr);
129  MF::Database::AutoThreading::ThreadPartitioning(Geometry_Ptr->m_VDBInt64GeometryGrid_Ptr, ConfigData_Ptr);
130  MF::Database::AutoThreading::GridThreading(Geometry_Ptr->m_VDBInt64GeometryGrid_Ptr, ThreadArray_Ptr);
131 
132  // End of threads building
133  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
135 
137  cout << "MFSolver_CPU >>> Threads data initialization info: " << endl;
138 
139  MF::Solver_CPU::BoundaryFunctions::Initialize(CaseParameters_Ptr,LatticeParameters_Ptr);
141  MF::Solver_CPU::FluidFunctions::Initialize(CaseParameters_Ptr,LatticeParameters_Ptr);
143  MF::Solver_CPU::Collision::Initialize(CaseParameters_Ptr,LatticeParameters_Ptr);
145 
146  // Initialisation of calculations
147  MF::LBPC::ParametersConversion::Initialize(ConfigData_Ptr,LatticeParameters_Ptr);
148  MF::LBPC::ParametersConversion::ComputeBasicParameters(CaseParameters_Ptr,Geometry_Ptr->m_VDBInt64GeometryGrid_Ptr);
149  MF::Solver_CPU::Initialization::ThreadDefaultDataInitialize(ThreadArray_Ptr,CaseParameters_Ptr);
150  MF::Solver_CPU::Initialization::ThreadDataInitialize(ThreadArray_Ptr,ConfigData_Ptr);
151  MF::Solver_CPU::Initialization::EquilibriumInitialization(ThreadArray_Ptr,CaseParameters_Ptr);
152 
153  // Prints on console extended info
154  if(verbose) {
155  // MF::Solver_CPU::ConsoleWriter::ExtendedInfo(ProgramParameters_Ptr, CaseParameters_Ptr, ConfigData_Ptr);
156  // MF::Solver_CPU::ConsoleWriter::ThreadsNodeInfo(ThreadArray_Ptr);
158  }
159 
160  // End of threads data initialisation
161  cout << "----------------------------------------------------------------------------------------------------------------------------" << endl;
163 
165  cout << "MFSolver_CPU >>> Main loop info: " << endl;
166 
167  // Calculation order compatible with a GPU code: pre-collision | propagation -> boundary conditions -> collision
168  unsigned int SimStep = 0;
169  double V_SimError;
170  double M_SimError;
171  std::string DataFileName;
172  const unsigned int ConsoleWriteStep = CaseParameters_Ptr->ConsoleWriteStep_K_W;
173  const unsigned int FileWriteStep = CaseParameters_Ptr->VTKWriteStep_VTK_W;
174  const unsigned int VTKFileMaxNumber = CaseParameters_Ptr->VTKFileMaxNumber_VTK_Max;
175 
176  // Console info print
180 
181  // Before first step
182  for (auto & Thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr) {
183  if (Thread->m_DoPreCollision && Thread->m_DoCollision) {
184  Thread->DoPreANDCollision(CPU_ThreadsNr);
185  }
186  else if (Thread->m_DoCollision) {
187  Thread->DoCollisionOnly(CPU_ThreadsNr);
188  }
189  else if (Thread->m_DoPreCollision) {
190  Thread->DoPreCollisionOnly(CPU_ThreadsNr);
191  }
192  }
193 
194  // Initial data distributions save
195  DataFileName = (ConfigData_Ptr->CaseFolder + ConfigData_Ptr->getProgramStringParam("OutputFile") + std::to_string(SimStep));
196  Geometry_Ptr->m_MFGrid_GeometryGrid_Ptr->saveAllDataToVTIFile(ThreadArray_Ptr, ConfigData_Ptr, DataFileName);
197  std::cout << std::endl;
198 
199  // Print initial statistics for 0 step
200  MF::Solver_CPU::ConsoleWriter::PrintTimeStepStatistics(V_SimError, M_SimError, SimStep, ThreadArray_Ptr, CaseParameters_Ptr);
201 
202  // Main loop
203  std::chrono::time_point<std::chrono::high_resolution_clock> TimeStart = std::chrono::high_resolution_clock::now(); // Starts time measuring.
205  V_SimError = CaseParameters_Ptr->Sc_VelocityResidueError_ErrV + 1; // Initialisation
206  M_SimError = M_SimError > CaseParameters_Ptr->MassFlowError_ErrM + 1; // Initialisation
207 
208  while ((V_SimError > CaseParameters_Ptr->Sc_VelocityResidueError_ErrV) || (M_SimError > CaseParameters_Ptr->MassFlowError_ErrM)) {
209  SimStep++;
210  for (auto & Thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr)
211  if (Thread->m_DoPropagation)
212  Thread->DoPropagation(CPU_ThreadsNr);
213 
214  if (SimStep % ConsoleWriteStep == 0)
215  MF::Solver_CPU::ConsoleWriter::PrintTimeStepStatistics(V_SimError, M_SimError, SimStep, ThreadArray_Ptr, CaseParameters_Ptr); // Prints info on console and calculates simulation error.
216 
217  if (FileWriteStep != 0 && SimStep % FileWriteStep == 0){
218  cout << std::setw(194) << std::setfill('=') << "=" << std::setfill(' ') << std::endl;
219  if(VTKFileMaxNumber > 0 && SimStep / FileWriteStep > VTKFileMaxNumber) {
220  std::string ErraseFileName = (ConfigData_Ptr->CaseFolder + ConfigData_Ptr->getProgramStringParam("OutputFile") +
221  std::to_string(SimStep - VTKFileMaxNumber * FileWriteStep) + ".vti");
222  cout<<"Errased file: ----> "<<ErraseFileName<<endl;
223  remove(ErraseFileName.c_str()); // Erase an old file.
224  }
225  DataFileName = (ConfigData_Ptr->CaseFolder + ConfigData_Ptr->getProgramStringParam("OutputFile") + std::to_string(SimStep));
226  Geometry_Ptr->m_MFGrid_GeometryGrid_Ptr->saveAllDataToVTIFile(ThreadArray_Ptr, ConfigData_Ptr, DataFileName); // Save data to .vti file.
227  cout << std::setw(194) << std::setfill('=') << "=" << std::setfill(' ') << std::endl;
228  }
229 
230  for (auto &Thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr) {
231  if (Thread->m_DoPreCollision && Thread->m_DoCollision)
232  Thread->DoPreANDCollision(CPU_ThreadsNr);
233  else if (Thread->m_DoCollision)
234  Thread->DoCollisionOnly(CPU_ThreadsNr);
235  else if (Thread->m_DoPreCollision)
236  Thread->DoPreCollisionOnly(CPU_ThreadsNr);
237  }
238 
239  }
240 
241  // Final propagation - necessary for final f_post swap after last collision.
242  for (auto & Thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr)
243  Thread->DoPropagation(CPU_ThreadsNr);
244 
245  // End of main loop --------------------------------------------------------------------------------------------------------------------------------
247 
249  auto TimeStop = std::chrono::high_resolution_clock::now(); // Stop time measuring
250 
251  // Final results save
252  cout << std::setw(194) << std::setfill('=') << "=" << std::setfill(' ') << std::endl;
253  DataFileName = (ConfigData_Ptr->CaseFolder + ConfigData_Ptr->getProgramStringParam("OutputFile") + std::to_string(SimStep));
254  Geometry_Ptr->m_MFGrid_GeometryGrid_Ptr->saveAllDataToVTIFile(ThreadArray_Ptr, ConfigData_Ptr, DataFileName);
255  cout << std::setw(194) << std::setfill('=') << "=" << std::setfill(' ') << std::endl;
256 
257  // Computations statistics
258  MF::Solver_CPU::ConsoleWriter::PrintComputationStatistics(TimeStart, TimeStop, SimStep, ThreadArray_Ptr);
259 
260  // End of postprocessing block----------------------------------------------------------------------------------------------------------------------
262 
263  cout << endl;
264  cout << "----------------------------------------------------------------------------------" << endl;
265  cout << "Microflow 3D ***** Goodbye *****" << endl;
266  cout << "----------------------------------------------------------------------------------" << endl;
267 
268  return exitStatus;
269 }
static std::shared_ptr< MF::GB::GeometryBuildFromSTL > New(const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr, const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
#define defaultPathToProgramConfigFile
Default path to program parameters.
static void GridThreading(const openvdb::Int64Grid::Ptr &VDBGrid_Ptr, std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Grid partitioning into MFThreads.
static void PrintTimeStepStatistics(double &V_SimError, double &M_SimError, const unsigned int &SimStep, const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr, const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr)
Prints on console time step statistics.
static void PrintComputationStatistics(std::chrono::time_point< std::chrono::high_resolution_clock > TimeStart, std::chrono::time_point< std::chrono::high_resolution_clock > TimeStop, unsigned int SimStep, const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Prints on console final computation statistics.
static void ThreadDataInitialize(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr, const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr)
Initialization of MFThread boundary/initial values from thread.cfg file.
int main(int argc, char **argv)
static void EquilibriumInitialization(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr, const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr)
Initialization of FEQ pre and post collision tables (equilibrium model).
static void PrintCPUInfo(const int &CPU_ThreadsNr)
Prints on console CPU usage info.
static std::shared_ptr< MF::Solver_CPU::CaseParameters > New(std::shared_ptr< MF::Database::ConfigData > ConfigData_Ptr)
static void Initialize(const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr, const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
static void SetFluidSolidNodePointerToFunc(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Sets pointers to fluid functions of MFThread.
static void ThreadsArrayInfo(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Prints on console information about all MFThreads.
static void Initialize(const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr, const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
static std::chrono::time_point< std::chrono::high_resolution_clock > m_TimePreviousStep
Definition: ConsoleWriter.h:39
static std::shared_ptr< MF::Database::ThreadArray > New(const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
MFThreadArray allocator.
Definition: ThreadArray.h:30
static void Initialize(const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr, const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
static void ThreadDefaultDataInitialize(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr, const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr)
Initialization of MFThread boundary/initial values from thread.cfg file.
static void SetCollisionPointerToFunc(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Sets pointers to proper collision functions in MFThreads.
Definition: Collision.cpp:23
static void Initialize(const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr, const std::shared_ptr< MF::GU::LatticeParametersD3Q19 > &LatticeParameters_Ptr)
Definition: Collision.h:31
static void ComputeBasicParameters(const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr, const openvdb::Int64Grid::Ptr &VDBGrid_Ptr)
Compute: Re, l_ch_LB, Cu, u_ch_LB, dt_phys, nu_LB.
static void PrintGridStatistics(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Prints on console basic grid statistics.
static std::shared_ptr< MF::Solver_CPU::ProgramParameters > New(const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr)
static std::shared_ptr< MF::Database::ConfigData > New(const char *pPathToProgramConfigFile, const char *pPathToCaseFolder, const char *pScope, bool verbose)
Definition: ConfigData.h:28
static void PrintComputationParameters(const std::shared_ptr< MF::Solver_CPU::CaseParameters > &CaseParameters_Ptr)
Prints on console basic solution parameters.
static void SetBoundaryNodePointerToFunc(const std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Sets the pointer to the function that performs calculations for the edge node (Thread.h -> its_pBoundaryFunction).
#define defaultScope
Default scope in config files.
static std::shared_ptr< MF::Parser::CmdLineArgsParser > New()
static void ThreadPartitioning(const openvdb::Int64Grid::Ptr &VDBGrid_Ptr, const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr)
MFThreads partitioning.
static std::shared_ptr< MF::GU::LatticeParametersD3Q19 > New()