Microflow 3D  v1.0
AutoThreading.cpp
Go to the documentation of this file.
1 // ==============================================================================================
2 // Microflow 3D, http://www.microflow.pwr.edu.pl/
3 // Created by Roman Szafran on 18.05.19.
4 // Last modified by Roman Szafran on 21.12.2019.
5 // Copyright (c) 2019 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 
12 
13 void MF::Database::AutoThreading::GridThreading(const openvdb::Int64Grid::Ptr& VDBGrid_Ptr, std::shared_ptr<MF::Database::ThreadArray> & ThreadArray_Ptr) {
14 
15  struct nodeForAutoThreading {
16  uint64_t NodeEncodedID = 1;
17  uint32_t NodeNumber = 0;
18  };
19 
20  nodeForAutoThreading newNode;
21  auto NodeArray_Ptr = std::make_unique<std::vector<nodeForAutoThreading>>(1);
22  uint64_t nodeEID; // nodeForAutoThreading NodeID + uid-thread number+1 + ThreadCount + ComponentNr + PhaseNr.
23  unsigned char mark;
24 
25  //auto accessor = VDBGrid_Ptr->getAccessor();
26  openvdb::Coord xyz;
27  int32_t &i = xyz[0], &j = xyz[1], &h = xyz[2];
28 
29  // Counts nodes with the same nodeID
30  for (auto iter = VDBGrid_Ptr->beginValueOn(); iter; ++iter) {
31  mark = 0;
32  nodeEID = iter.getValue();
33  for (auto & it : *NodeArray_Ptr) {
34  if (it.NodeEncodedID == nodeEID) {
35  it.NodeNumber++;
36  mark++;
37  }
38  }
39  if (mark == 0) {
40  newNode.NodeNumber = 1;
41  newNode.NodeEncodedID = nodeEID;
42  NodeArray_Ptr->push_back(newNode);
43  }
44  else if (mark > 1) {
45  std::cout << "AutoThreading Error" << std::endl;
46  exit(EXIT_FAILURE);
47  }
48  }
49 
50  // Add new thread to threads array
51  for (auto & it : *NodeArray_Ptr) {
52  ThreadArray_Ptr->NewThread(it.NodeEncodedID,it.NodeNumber);
53  }
54 
55  // Add nodes coordinates to threads
56  for (auto & thread1 : *ThreadArray_Ptr->m_ThreadsTable_Ptr){
57  MF::GB::NodeID nodeTMP;
58  nodeTMP.node_id.Node.nodeType = thread1->m_NodeType;
59  nodeTMP.node_id.Node.uidThreadNr = thread1->m_uidThreadNr;
60  nodeTMP.node_id.Node.ThreadCount = thread1->m_ThreadCount;
61  nodeTMP.node_id.Node.ComponentNr = thread1->m_ComponentNr;
62  nodeTMP.node_id.Node.PhaseNr = thread1->m_PhaseNr;
63  auto iter2 = VDBGrid_Ptr->beginValueOn();
64  for (size_t node = 0; node < thread1->m_NodeArray_Ptr->size(); node++) {
65  for (auto iter = iter2; iter; ++iter) {
66  if (iter.getValue() == nodeTMP.node_id.NodeID) {
67  xyz = iter.getCoord();
68  thread1->setNodeCoordX(node, i);
69  thread1->setNodeCoordY(node, j);
70  thread1->setNodeCoordZ(node, h);
71  iter2 = iter;
72  ++iter2;
73  break;
74  }
75  }
76  }
77  }
78 
79  NodeArray_Ptr.reset();
80 
81  // Create VDB grid of pointers
82  using PointersTree = openvdb::tree::Tree4<uintptr_t, 5, 4, 3 >::Type;
83  using PointersGrid = openvdb::Grid<PointersTree>;
84 
85  // Create an empty grid with background nodeForAutoThreading 0.
86  auto PointersGrid_Ptr = PointersGrid::create(0);
87  auto accessor2 = PointersGrid_Ptr->getAccessor();
88 
89  // Set pointers in VDB grid to thread nodes
90  for (auto & thread2 : *ThreadArray_Ptr->m_ThreadsTable_Ptr){
91  for (size_t node = 0; node < thread2->m_NodeArray_Ptr->size(); node++) {
92  i = thread2->getNodeCoordX(node);
93  j = thread2->getNodeCoordY(node);
94  h = thread2->getNodeCoordZ(node);
95  auto address1 = reinterpret_cast<uintptr_t>(thread2->getNodePointer(node));
96  accessor2.setValue(xyz,address1);
97  }
98  }
99  // Propagation pointers arrangement
100  openvdb::CoordBBox its_bbox;
101  VDBGrid_Ptr->treePtr()->evalActiveVoxelBoundingBox(its_bbox);
102  auto Nx = its_bbox.dim().x();
103  auto Ny = its_bbox.dim().y();
104  auto Nz = its_bbox.dim().z();
105  auto minX = its_bbox.min().x();
106  auto maxX = its_bbox.max().x();
107  auto minY = its_bbox.min().y();
108  auto maxY = its_bbox.max().y();
109  auto minZ = its_bbox.min().z();
110  auto maxZ = its_bbox.max().z();
111 
112  // Set nodeForAutoThreading propagation pointers.
113  for (auto & thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr) {
114  for (size_t node = 0; node < thread->m_NodeArray_Ptr->size(); node++) {
115  thread->getNodeRef(node).pMyThread_Ptr = &thread; // Thread pointer initialization
116  for (uint8_t ik = 0; ik < MFQ19_H ; ik++) {
117  auto direction = MF::GU::LatticeParametersD3Q19::SwapDirections[ik][0];
118  i = thread->getNodeCoordX(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cx[direction];
119  j = thread->getNodeCoordY(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cy[direction];
120  h = thread->getNodeCoordZ(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cz[direction];
121  auto value = accessor2.getValue(xyz);
122  if (value != 0) {
123  thread->setNodePtrInPropTable(node,ik, reinterpret_cast<Node *>(accessor2.getValue(xyz))); //Fluid nodeForAutoThreading pointer.
124  }
125  else if (thread->m_NodeType != 4 && thread->m_NodeType != 5) { //For nodes outside te boundary
126  thread->setNodePtrInPropTable(node,ik, nullptr);
127  }
128  else { //Propagation for periodic boundary nodes
129  if (i < minX)
130  i = i + Nx;
131  else if (i > maxX)
132  i = i - Nx;
133  if (j < minY)
134  j = j + Ny;
135  else if (j > maxY)
136  j = j - Ny;
137  if (h < minZ)
138  h = h + Nz;
139  else if (h > maxZ)
140  h = h - Nz;
141  value = accessor2.getValue(xyz);
142  if (value != 0) {
143  thread->setNodePtrInPropTable(node,ik, reinterpret_cast<Node *>(accessor2.getValue(xyz))); // Periodic nodeForAutoThreading pointer.
144  }
145  else {
146  std::cout << "Lack of consistence of periodic boundary " << thread->m_NodeType << " nodeForAutoThreading: " << " (" << i << "," << j << "," << h << ") " << std::endl;
147  exit(EXIT_FAILURE);
148  }
149  }
150  }
151  }
152  }
153  // Set second half nodeForAutoThreading propagation pointers.
154  for (auto & thread : *ThreadArray_Ptr->m_ThreadsTable_Ptr) {
155  for (size_t node = 0; node < thread->m_NodeArray_Ptr->size(); node++) {
156  for (uint8_t ik = 0; ik < MFQ19_H ; ik++) {
157  auto direction = MF::GU::LatticeParametersD3Q19::SwapDirections[ik][1];
158  i = thread->getNodeCoordX(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cx[direction];
159  j = thread->getNodeCoordY(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cy[direction];
160  h = thread->getNodeCoordZ(node) + MF::GU::LatticeParametersD3Q19::DirectionVectorComponent_Cz[direction];
161  auto value = accessor2.getValue(xyz);
162  if (value != 0) {
163  thread->setNodePtrInSecondPropTable(node,ik, reinterpret_cast<Node *>(accessor2.getValue(xyz))); //Fluid nodeForAutoThreading pointer.
164  }
165  else if (thread->m_NodeType != 4 && thread->m_NodeType != 5) { //For nodes outside te boundary
166  thread->setNodePtrInSecondPropTable(node, ik,nullptr);
167  }
168  else { //Propagation for periodic boundary nodes
169  if (i < minX)
170  i = i + Nx;
171  else if (i > maxX)
172  i = i - Nx;
173  if (j < minY)
174  j = j + Ny;
175  else if (j > maxY)
176  j = j - Ny;
177  if (h < minZ)
178  h = h + Nz;
179  else if (h > maxZ)
180  h = h - Nz;
181  value = accessor2.getValue(xyz);
182  if (value != 0) {
183  thread->setNodePtrInSecondPropTable(node,ik, reinterpret_cast<Node *>(accessor2.getValue(xyz))); // Periodic nodeForAutoThreading pointer.
184  }
185  else {
186  std::cout << "Lack of consistence of periodic boundary " << thread->m_NodeType << " nodeForAutoThreading: " << " (" << i << "," << j << "," << h << ") " << std::endl;
187  exit(EXIT_FAILURE);
188  }
189  }
190  }
191  }
192  }
193 }
194 
195 void MF::Database::AutoThreading::ThreadPartitioning(const openvdb::Int64Grid::Ptr &VDBGrid_Ptr, const std::shared_ptr<MF::Database::ConfigData>& ConfigData_Ptr) {
196 
197  uint32_t ThreadMaxSize {std::numeric_limits<uint32_t>::max()};
198  if (ConfigData_Ptr->getCaseIntParam("ThreadParams.MFThreadMaxSize") < std::numeric_limits<uint32_t>::max()
199  && ConfigData_Ptr->getCaseIntParam("ThreadParams.MFThreadMaxSize") != 0) {
200  ThreadMaxSize = ConfigData_Ptr->getCaseIntParam("ThreadParams.MFThreadMaxSize");
201  }
202 
203  struct nodeForAutoThreading {
204  uint64_t NodeEncodedID = 1;
205  uint64_t NodeNumber = 0;
206  };
207 
208  nodeForAutoThreading newNode;
209  auto NodeArray_Ptr = std::make_unique<std::vector<nodeForAutoThreading>>(1);
210  uint64_t nodeEID; // nodeForAutoThreading NodeID + uid-thread number+1 + ThreadCount + ComponentNr + PhaseNr.
211  MF::GB::NodeID nodeTMP;
212  unsigned char mark;
213 
214  //auto accessor = VDBGrid_Ptr->getAccessor();
215  openvdb::Coord xyz;
216  int32_t &i = xyz[0], &j = xyz[1], &h = xyz[2];
217  for (auto iter = VDBGrid_Ptr->beginValueOn(); iter; ++iter) {
218  mark = 0;
219  nodeEID = iter.getValue();
220  for (auto &it : *NodeArray_Ptr) {
221  if (it.NodeEncodedID == nodeEID) {
222  it.NodeNumber++;
223  mark++;
224  if (it.NodeNumber >= ThreadMaxSize && (uint32_t)(it.NodeNumber / ThreadMaxSize) < std::numeric_limits<uint16_t>::max()) {
225  nodeTMP.node_id.NodeID = nodeEID;
226  nodeTMP.node_id.Node.ThreadCount = (uint32_t)(it.NodeNumber / ThreadMaxSize);
227  iter.setValue(nodeTMP.node_id.NodeID);
228  } else if ((uint32_t)(it.NodeNumber / ThreadMaxSize) >= std::numeric_limits<uint16_t>::max()){ // Only 65535 MFThreads of the same type are allowed.
229  std::cout << "AutoThreading Error. Too many parts of MFThread: " << nodeEID << std::endl;
230  exit(EXIT_FAILURE);
231  }
232  }
233  }
234  if (mark == 0) {
235  newNode.NodeNumber = 1;
236  newNode.NodeEncodedID = nodeEID;
237  NodeArray_Ptr->push_back(newNode);
238 
239  } else if (mark > 1) {
240  std::cout << "AutoThreading Error" << std::endl;
241  exit(EXIT_FAILURE);
242  }
243  }
244  NodeArray_Ptr.reset();
245 }
246 
struct MF::GB::NodeID::@0::@1 Node
static void GridThreading(const openvdb::Int64Grid::Ptr &VDBGrid_Ptr, std::shared_ptr< MF::Database::ThreadArray > &ThreadArray_Ptr)
Grid partitioning into MFThreads.
A class that allows to determine the proper NodeID from combined nodeType, uidThreadNr, ThreadCount, ComponentNr and PhaseNr.
Definition: NodeID.h:18
static constexpr int8_t DirectionVectorComponent_Cx[MFQ27]
The x direction vector component of all D3Q19 lattice directions plus additional nodes of the Q27 lat...
static constexpr int8_t DirectionVectorComponent_Cy[MFQ27]
The y direction vector component of all D3Q19 lattice directions plus additional nodes of the Q27 lat...
static constexpr int8_t DirectionVectorComponent_Cz[MFQ27]
The z direction vector component of all D3Q19 lattice directions plus additional nodes of the Q27 lat...
uint64_t NodeID
Definition: NodeID.h:29
union MF::GB::NodeID::@0 node_id
#define MFQ19_H
Number of elements (linked directions) in propagation table for one node.
static void ThreadPartitioning(const openvdb::Int64Grid::Ptr &VDBGrid_Ptr, const std::shared_ptr< MF::Database::ConfigData > &ConfigData_Ptr)
MFThreads partitioning.
static constexpr uint8_t SwapDirections[MFQ19_H][2]
Indexes of swap directions of f(i) in D3Q19.