File: LatticeMaster.hpp

package info (click to toggle)
esys-particle 2.3.4%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 13,036 kB
  • ctags: 10,805
  • sloc: cpp: 80,009; python: 5,872; makefile: 1,243; sh: 313; perl: 225
file content (413 lines) | stat: -rw-r--r-- 14,695 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
/////////////////////////////////////////////////////////////
//                                                         //
// Copyright (c) 2003-2014 by The University of Queensland //
// Centre for Geoscience Computing                         //
// http://earth.uq.edu.au/centre-geoscience-computing      //
//                                                         //
// Primary Business: Brisbane, Queensland, Australia       //
// Licensed under the Open Software License version 3.0    //
// http://www.apache.org/licenses/LICENSE-2.0          //
//                                                         //
/////////////////////////////////////////////////////////////

// --- Project includes ---
#include "Parallel/GetRef_cmd.h"
#include "Parallel/GeometryReader.h"

// --- STL includes ---
#include <map>
#include <set>

using namespace esys::lsm;

/*!
  read model geometry from file

  \param fileName the name of the input file
*/
template <class TmplParticle>
void  CLatticeMaster::readGeometry(const std::string &fileName)
{
  console.Debug()
    << "begin CLatticeMaster::readGeometry: fileName="
    << fileName << "\n";

  // setup geometry reader and get geometry info from header file
  GeometryReader geoReader(fileName);
  GeometryInfo geoInfo = geoReader.getGeometryInfo();
  	
  // check if geometry info has been set previously
  if(m_bbx_has_been_set){ 
    // check if old & new geometry are compatible
    if(!m_geo_info.isCompatible(geoInfo)){
	std::cerr << "Geometry info read from file is incompatible with previously set geometry (bounding box, circular boundaries) - Model may not run properly!" << std::endl; 
    }
    // set only the geometry version, the other geometry info remains unchanged
    m_geo_info.setLsmGeoVersion(geoInfo.getLsmGeoVersion());
  } else {
    m_geo_info=geoInfo; // set full geometry meta-info

    // set model spatial domain -> sets geometry info & initializes neighbor table in workers
    if(m_geo_info.hasAnyPeriodicDimensions()){
	setSpatialDomain(m_geo_info.getBBoxCorners()[0],m_geo_info.getBBoxCorners()[1],m_geo_info.getPeriodicDimensions());
    } else {
	setSpatialDomain(m_geo_info.getBBoxCorners()[0],m_geo_info.getBBoxCorners()[1]);
    }
    m_bbx_has_been_set=true; // flag that spatial domain has been set
  }
  
  // read particles 
  GeometryReader::ParticleIterator &particleIt = geoReader.getParticleIterator();
  console.XDebug()<< "Number of particles: " << particleIt.getNumRemaining() << "\n";
  if (geoReader.getParticleType() != "Simple") {
    throw 
      std::runtime_error(
        (std::string("Unknown particle type ") + geoReader.getParticleType()).c_str()
      );
  }

  addParticles<GeometryReader::ParticleIterator,TmplParticle>(particleIt);

  // read connections
  GeometryReader::ConnectionIterator &connectionIt =
    geoReader.getConnectionIterator();
  console.XDebug()<< "Number of connections: " << connectionIt.getNumRemaining() << "\n";

  addConnections(connectionIt);
  console.Debug()<<"end CLatticeMaster::readGeometry\n";
}

template <typename TmplVisitor>
void CLatticeMaster::visitMeshFaceReferences(const string &meshName)
{
  throw std::runtime_error("CLatticeMaster::visitMeshFaceReferences: Not implemented.");
}

template <typename TmplVisitor>
void CLatticeMaster::visitMesh2dNodeReferences(const string &meshName, TmplVisitor &visitor)
{
  console.XDebug()<<"CLatticeMaster::visitMesh2dNodeReferences( " << meshName << ")\n";
  GetNodeRefCommand cmd(getGlobalRankAndComm(),meshName);
  // broadcast command
  cmd.broadcast();
  
  // receive data (multimap)
  std::multimap<int,int> ref_mmap;
  m_tml_global_comm.gather(ref_mmap);
  // collate into set
  std::set<int> ref_set; //== this is the set of node ids == 
  for(std::multimap<int,int>::iterator iter=ref_mmap.begin();
      iter!=ref_mmap.end();
      iter++){
    ref_set.insert(iter->second);
  }
  for (std::set<int>::const_iterator it = ref_set.begin(); it != ref_set.end(); it++)
  {
    visitor.visitNodeRef(*it);
  }
  console.XDebug()<<"end CLatticeMaster::visitMesh2dNodeReferences()\n";
}

template <typename TmplVisitor>
void CLatticeMaster::visitMesh2dEdgeStress(const string &meshName, TmplVisitor &visitor)
{
  console.XDebug()<<"CLatticeMaster::visitMesh2dEdgeStress( " << meshName << ")\n";
  std::multimap<int,pair<int,Vec3> > temp_mm;
  std::map<int,Vec3> data; //=== map of id, value ===

  BroadcastCommand cmd(getGlobalRankAndComm(), CMD_GETMESH2DSTRESS);
  cmd.append(meshName.c_str());
  cmd.broadcastCommand();
  cmd.broadcastBuffer();

  // get data from slaves
  m_tml_global_comm.gather(temp_mm);
  
  // add data together
  for(std::multimap<int,pair<int,Vec3> >::iterator iter=temp_mm.begin();
      iter!=temp_mm.end();
      iter++){
    if(data.find((iter->second).first)==data.end()){ // id not in data -> insert
      data.insert(iter->second);
    } else { // id is in data -> add
      data[(iter->second).first]+=(iter->second).second;
    }
  }

  for (std::map<int,Vec3>::const_iterator it = data.begin(); it != data.end(); it++)
  {
    visitor.visitRefStressPair(it->first, it->second);
  }

  cmd.wait("visitMesh2dEdgeStress");
  console.XDebug()<<"end CLatticeMaster::visitMesh2dEdgeStress()\n";  
}

template <typename TmplVisitor>
void CLatticeMaster::visitTriMeshFaceForce(
  const string &meshName,
  TmplVisitor &visitor
)
{
  console.XDebug()<<"CLatticeMaster::visitTriMeshFaceForce( " << meshName << ")\n";
  std::multimap<int,pair<int,Vec3> > temp_mm;
  std::map<int,Vec3> data; //=== map of id, value ===

  BroadcastCommand cmd(getGlobalRankAndComm(), CMD_GETTRIMESHFORCE);
  cmd.append(meshName.c_str());
  cmd.broadcastCommand();
  cmd.broadcastBuffer();

  // get data from slaves
  m_tml_global_comm.gather(temp_mm);
  
  // add data together
  for(std::multimap<int,pair<int,Vec3> >::iterator iter=temp_mm.begin();
      iter!=temp_mm.end();
      iter++){
    if(data.find((iter->second).first)==data.end()){ // id not in data -> insert
      data.insert(iter->second);
    } else { // id is in data -> add
      data[(iter->second).first]+=(iter->second).second;
    }
  }

  for (std::map<int,Vec3>::const_iterator it = data.begin(); it != data.end(); it++)
  {
    visitor.visitRefForcePair(it->first, it->second);
  }

  cmd.wait("visitTriMeshFaceStress");
  console.XDebug()<<"end CLatticeMaster::visitTriMeshFaceForce()\n";  
}

template <typename TmplVisitor, typename TmplParticle>
void CLatticeMaster::visitParticlesOfType(
  const IdVector &particleIdVector,
  TmplVisitor &visitor
)
{
  console.Debug() << "CLatticeMaster::visitParticlesOfType: enter\n";
  typedef std::multimap<int,TmplParticle> ParticleMMap;
  ParticleMMap particleMMap;

  console.Debug()
    << "CLatticeMaster::visitParticlesOfType: broadcasting command\n";
  BroadcastCommand cmd(getGlobalRankAndComm(), CMD_GETIDPARTICLEDATA);
  cmd.broadcastCommand();

  console.Debug()
    << "CLatticeMaster::visitParticlesOfType: broadcasting particle id's\n";
  m_tml_global_comm.broadcast_cont(particleIdVector);

  console.Debug()
    << "CLatticeMaster::visitParticlesOfType:"
    << " gathering particle data from workers\n";
  m_tml_global_comm.gather_packed(particleMMap);
  console.Debug()
    << "CLatticeMaster::visitParticlesOfType:"
    << " gathered " << particleMMap.size() << " particles\n";

  console.Debug()
    << "CLatticeMaster::visitParticlesOfType:"
    << " visiting particle data\n";
  for(
    typename ParticleMMap::iterator iter=particleMMap.begin();
    iter != particleMMap.end();
    iter++
  )
  {
    iter->second.visit(visitor);
  }

  cmd.wait("visitParticles");
  console.Debug() << "CLatticeMaster::visitParticlesOfType: exit\n";
}

template <typename TmplVisitor>
void CLatticeMaster::visitParticles(
  const IdVector &particleIdVector,
  TmplVisitor &visitor
)
{
  console.Debug() << "CLatticeMaster::visitParticles: enter\n";

  if (m_particle_type == "Basic")
  {
    visitParticlesOfType<TmplVisitor,CParticle>(particleIdVector, visitor);
  }
  else if (m_particle_type == "Rot")
  {
    visitParticlesOfType<TmplVisitor,CRotParticle>(particleIdVector, visitor);
  }
  else if (m_particle_type == "RotVi")
  {
    visitParticlesOfType<TmplVisitor,CRotParticleVi>(particleIdVector, visitor);
  }
  else if (m_particle_type == "RotTherm")
  {
    visitParticlesOfType<TmplVisitor,CRotThermParticle>(particleIdVector, visitor);
  }
  else
  {
    throw
      std::runtime_error(
        std::string("Unknown particle type: ") + m_particle_type
      );
  }
  console.Debug() << "CLatticeMaster::visitParticles: exit\n";
}

template <class TmplIterator, class TmplParticle>
void CLatticeMaster::addParticles(TmplIterator &particleIt)
{
  CMPIBarrier barrier(m_global_comm);
  CMPILCmdBuffer cmd_buffer(m_global_comm,m_global_rank);

  // cast storage pointer to correct type 
  vector<TmplParticle> particleVector;
  console.XDebug()
    << "CLatticeMaster::addParticles:"
    << " Reserving vector memory for particles.\n";

  // Determine the directions for calculating the minimum and maximum extents of particles.
  // Indexes for valid directions x, y, z are 0, 1, 2.  If a dimension is irrelevant for the 
  // purpose of finding particle extents (because it is periodic or does not factor into 
  // a 2D calculation), its index is 3.  The indexes are sorted ascending to minimize the 
  // number of tests needed to process each particle in particlesMinMax(...).
  esys::lsm::IntVector periodicity(3);
  if (m_geo_info.hasAnyPeriodicDimensions())
    periodicity = m_geo_info.getPeriodicDimensions();
  for (int i=0; i<3; i++)
    m_particle_dimensions[i] = periodicity[i]==0 ? i : 3;
  if (m_geo_info.is2d())
    m_particle_dimensions[2]=3;
  int periodicTotal = periodicity[0] + periodicity[1] + periodicity[2];
  if (periodicTotal==1 || periodicTotal==2)
    std::sort(m_particle_dimensions.begin(), m_particle_dimensions.end());

  const int numBroadcastParticles = 50000;
  particleVector.reserve(numBroadcastParticles);
  console.XDebug()
    << "CLatticeMaster::addParticles:"
    << " Beginning add-particle loop..." << "\n";
  for (int i = 0; particleIt.hasNext(); i++) {
    const TmplParticle particle(particleIt.next());

    // Update the minimum and maximum extents of the particles as each is read in.
    particlesMinMax(particle);
    
    particleVector.push_back(particle);
    if (((i+1) % 5000) == 0) {
      console.XDebug()
        << "CLatticeMaster::addParticles:"
        << "Adding particle with id "
        << particleVector.rbegin()->getID() << "\n";
    }

    if (((i+1) % numBroadcastParticles) == 0)
    {
      console.XDebug() << "CLatticeMaster::addParticles:"
        << " Broadcasting receive cmd...." << "\n";
      cmd_buffer.broadcast(CMD_RECEIVEPARTICLES);
      console.XDebug()
        << "CLatticeMaster::addParticles: Broadcasting particles...." << "\n";
      m_tml_global_comm.broadcast_cont_packed(particleVector);
      barrier.wait("CLatticeMaster::addParticles: Post particle broadcast.");
      barrier.wait("CLatticeMaster::addParticles: Post Command.");
      particleVector.clear();
      particleVector.reserve(numBroadcastParticles);
    }
  }
  console.XDebug()
    << "CLatticeMaster::addParticles: Done add-particle loop..." << "\n";
  console.XDebug()
    << "CLatticeMaster::addParticles: Broadcasting final particle-receive cmd"
    << "\n";
  cmd_buffer.broadcast(CMD_RECEIVEPARTICLES);
  console.XDebug() << "CLatticeMaster::addParticles:"
    << " Broadcasting final set of particles...\n";
  m_tml_global_comm.broadcast_cont_packed(particleVector);
  barrier.wait("Post final particle broadcast.");
  barrier.wait("Post final particle-broadcast command.");
  // -- build ntable
  console.XDebug()
    << "CLatticeMaster::addParticles: "
    << "Building ntable (searchNeighbours)...\n";
  searchNeighbors(true);
  console.XDebug()
    << "CLatticeMaster::addParticles: exit\n";

}

template <class TmplIterator>
void CLatticeMaster::addConnections(TmplIterator &connectionIt)
{
  console.XDebug()
    << "CLatticeMaster::addConnections: enter\n";
  
  CMPIBarrier barrier(m_global_comm);
  CMPILCmdBuffer cmd_buffer(m_global_comm,m_global_rank);
  
  const int numBroadcastConnections = 100000;
  vector<int> connectionBuffer;
  connectionBuffer.reserve(numBroadcastConnections);
  int i = 0;
  for (; connectionIt.hasNext(); i++)
  {
    typename TmplIterator::value_type data = connectionIt.next();
    connectionBuffer.push_back(data.getTag());
    connectionBuffer.push_back(data.getP1Id());
    connectionBuffer.push_back(data.getP2Id());
    if ((i+1) % 50000 == 0)
    {
      console.XDebug() << "Adding connection number " << i << "\n";
    }
    if ((i+1) % numBroadcastConnections == 0)
    {
      console.XDebug() << "CLatticeMaster::addConnections:"
        << " Broadcasting receive cmd...." << "\n";
      cmd_buffer.broadcast(CMD_RECEIVECONNECTIONS);
      console.XDebug()
        << "CLatticeMaster::addConnections: Broadcasting connections...." << "\n";
      m_tml_global_comm.broadcast_cont_packed(connectionBuffer);
      barrier.wait("CLatticeMaster::addConnections: Post connection broadcast.");
      barrier.wait("CLatticeMaster::addConnections: Post Command.");
      connectionBuffer.clear();
      connectionBuffer.reserve(numBroadcastConnections);
    }
    //m_temp_conn[data.getTag()].push_back(data.getP1Id());
    //m_temp_conn[data.getTag()].push_back(data.getP2Id());
  }
  console.XDebug()
    << "CLatticeMaster::addConnections: Done add-connection loop..." << "\n";
  console.XDebug()
    << "CLatticeMaster::addConnections: Broadcasting final connection-receive cmd"
    << "\n";
  cmd_buffer.broadcast(CMD_RECEIVECONNECTIONS);
  console.XDebug() << "CLatticeMaster::addConnections:"
    << " Broadcasting final set of connections...\n";
  m_tml_global_comm.broadcast_cont_packed(connectionBuffer);
  barrier.wait("Post final connection broadcast.");
  barrier.wait("Post final connection-broadcast command.");

  console.XDebug()<< "Added " << i << " connections..." << "\n";
  // -- build ntable
  searchNeighbors(true);
  console.XDebug()
    << "CLatticeMaster::addConnections: exit\n";
}

template<typename TmplParticle>
void CLatticeMaster::particlesMinMax(const TmplParticle &particle)
{
  Vec3 position = particle.getPos();
  double radius = particle.getRad();

  for (int j=0, k=m_particle_dimensions[j]; j<3 && k<3; k=m_particle_dimensions[++j]) {
    if (m_init_min_pt[k]!=m_init_min_pt[k] || position[k]-radius<m_init_min_pt[k])
      m_init_min_pt[k] = position[k]-radius;
    if (m_init_max_pt[k]!=m_init_max_pt[k] || position[k]+radius>m_init_max_pt[k])
      m_init_max_pt[k] = position[k]+radius;
  }
}