NeoPZ
tpzpairstructmatrix.cpp
Go to the documentation of this file.
1 
6 #include "tpzpairstructmatrix.h"
7 #include "TPZTimer.h"
8 #include "pzelmat.h"
9 #include "pzcompel.h"
10 #include "pzstrmatrix.h"
11 #include "pzsubcmesh.h"
12 #include "pzanalysis.h"
13 #include "TPZMaterial.h"
14 
15 using namespace std;
16 
17 #include "pzlog.h"
18 
19 #include "pz_pthread.h"
20 
21 #ifdef USING_TBB
22 #include <tbb/tbb.h>
23 using namespace tbb;
24 #endif
25 
26 #ifdef LOG4CXX
27 static LoggerPtr logger(Logger::getLogger("pz.strmatrix.tpzpairstructmatrix"));
28 static LoggerPtr loggerel(Logger::getLogger("pz.strmatrix.element"));
29 #endif
30 
32 
33 TPZPairStructMatrix::TPZPairStructMatrix(TPZCompMesh *mesh, TPZVec<int> &permutescatter) : fStrMatrix(mesh)
34 {
35  fPermuteScatter = permutescatter;
36 #ifdef PERF_DEBUG
37  std::cout << "fNumThreads e "<< fNumThreads << " gNumThreads esta setando para " << gNumThreads << endl;
38 #endif
40 
41 }
42 
43 #ifdef USING_TBB1
44 
45 struct PipeItem_t
46 {
47  TPZCompEl* el;
50 };
51 
53 class StageOne_t : public tbb::filter
54 {
55  unsigned current_iel;
56  unsigned nelem;
58  TPZCompMesh& mesh;
59 
60  std::vector<PipeItem_t> items;
61  unsigned current_item;
62 
63  std::set<int>& fMaterialIds;
64 
65  bool ShouldCompute(int matid)
66  {
67  return fMaterialIds.size()==0 || fMaterialIds.find(matid) != fMaterialIds.end();
68  }
69 
70 public:
71 
72  StageOne_t(unsigned tokens, TPZCompMesh& _mesh, std::set<int>& materialIds) :
73  tbb::filter(/*is serial*/ true), current_iel(0),
74  nelem(_mesh.NElements()), elementvec(_mesh.ElementVec()), mesh(_mesh),
75  items(tokens), current_item(0), fMaterialIds(materialIds)
76  {}
77 
78  unsigned n_tokens() {return items.size();}
79 
80  void* operator()(void*)
81  {
82  TPZCompEl* el = NULL;
83  bool found = false;
84 
85  while(current_iel < nelem)
86  {
87  el = elementvec[current_iel++];
88 
89  if (!el) continue;
90 
91  if(fMaterialIds.size() == 0) {
92  found = true;
93  break;
94  }
95 
96  //cout << "DEBUG: fMaterialIds.size() != 0 ????" << endl;
97 
98  TPZMaterial * mat = el->Material();
99  TPZSubCompMesh *submesh = dynamic_cast<TPZSubCompMesh *> (el);
100  if(!mat)
101  {
102  if(!submesh) {
103  continue;
104  }
105  else if(submesh->NeedsComputing(fMaterialIds) == false) {
106  continue;
107  }
108  }
109  else
110  {
111  int matid = mat->Id();
112  if(this->ShouldCompute(matid) == false) continue;
113  }
114  found = true;
115  break;
116  }
117 
118  if (found)
119  {
120  /* Ok, we found an item to process! */
121  PipeItem_t& item = items[current_item];
122  current_item = (current_item+1) % items.size();
123  item.el = el;
124  //cout << "Stage 1: Producing item: " << (current_iel-1) << endl;
125  return &item;
126  }
127  else
128  {
129  //cout << "Stage 1: Done" << endl;
130  return NULL; // It's over!
131  }
132  }
133 };
134 
136 class StageTwo_t: public tbb::filter
137 {
138  TPZCompMesh *mesh;
139  int mineq;
140  int maxeq;
141 
142 public:
143  StageTwo_t(TPZCompMesh* _mesh, int _mineq, int _maxeq) :
144  tbb::filter(/*is serial*/ false), mesh(_mesh), mineq(_mineq), maxeq(_maxeq)
145  {}
146 
147  void* operator()(void* item_p)
148  {
149  PipeItem_t& item = *static_cast<PipeItem_t*>(item_p);
150 
151  item.ek.Reset(mesh, TPZElementMatrix::EK);
152  item.ef.Reset(mesh, TPZElementMatrix::EF);
153 
154  item.el->CalcStiff(item.ek,item.ef);
155 
156  //cout << "Stage Two: processing item: " << item_p << endl;
157 
158  if (item.el->HasDependency())
159  {
160  // the element has dependent nodes
161  item.ek.ApplyConstraints();
162  item.ef.ApplyConstraints();
163  }
164 
165  item.ek.ComputeDestinationIndices();
166 
167  if(mineq != -1 && maxeq != -1)
168  TPZStructMatrix::FilterEquations(item.ek.fSourceIndex, item.ek.fDestinationIndex,
169  mineq, maxeq);
170 
171  return item_p;
172  }
173 };
174 
176 template<class TVar>
177 class StageThree_t: public tbb::filter
178 {
179  TPZMatrix<TVar>& fGlobMatrix1;
180  TPZFMatrix<TVar>& fGlobRhs;
181 
182 public:
183  StageThree_t(TPZMatrix<TVar>& _fGlobMatrix1, TPZFMatrix<TVar>& _fGlobRhs) :
184  tbb::filter(/*is serial*/ true), fGlobMatrix1(_fGlobMatrix1), fGlobRhs(_fGlobRhs)
185  {}
186 
187  void* operator()(void* item_p)
188  {
189  PipeItem_t& item = *static_cast<PipeItem_t*>(item_p);
190  TPZElementMatrix& ek = item.ek;
191  TPZElementMatrix& ef = item.ef;
192 
193  // Assemble the matrix
194  if(!ek.HasDependency())
195  {
196  fGlobMatrix1.AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
197  fGlobRhs.AddFel(ef.fMat,ek.fSourceIndex,ek.fDestinationIndex);
198  }
199  else
200  {
201  fGlobMatrix1.AddKel(ek.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
202  fGlobRhs.AddFel(ef.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
203  }
204 
205  return item_p;
206  }
207 };
208 
210 template<class TVar>
211 class StageFour_t: public tbb::filter
212 {
213  TPZMatrix<TVar>& fGlobMatrix2;
215 
216  void PermuteScatter(TPZVec<int64_t> &index)
217  {
218  int nel = index.NElements();
219  int iel;
220  for(iel = 0; iel<nel; iel++)
221  index[iel] = fPermuteScatter[index[iel]];
222  }
223 
224 public:
225  StageFour_t(TPZMatrix<TVar>& _fGlobMatrix2, const TPZVec<int>& _fPermuteScatter) :
226  tbb::filter(/*is serial*/ true), fGlobMatrix2(_fGlobMatrix2),
227  fPermuteScatter(_fPermuteScatter)
228  {}
229 
230  void* operator()(void* item_p)
231  {
232  PipeItem_t& item = *static_cast<PipeItem_t*>(item_p);
233  TPZElementMatrix& ek = item.ek;
234 
236 
237  // Assemble the matrix
238  if(!ek.HasDependency())
239  fGlobMatrix2.AddKel(ek.fMat, ek.fSourceIndex, ek.fDestinationIndex);
240  else
241  fGlobMatrix2.AddKel(ek.fConstrMat, ek.fSourceIndex, ek.fDestinationIndex);
242 
243  return NULL;
244  }
245 };
246 
247 #endif // USING TBB
248 
255 template<class TVar>
257 {
258 private:
259 
261  {
262  int nel = index.NElements();
263  int iel;
264  for(iel = 0; iel<nel; iel++)
265  {
266  index[iel] = fPermuteScatter[index[iel]];
267  }
268  }
269 
271  std::vector<TPZCompEl*> work_items;
272  // TODO: Try the cache_aligned_allocator for improved performance.
273  //std::vector<work_item_t<TVar>,cache_aligned_allocator<work_item_t<TVar> > > work_items;
274 
275  /* Pointers to shared data structures. */
276 
277  //TPZAutoPointer<TPZDohrAssembly<TVar> > fAssembly;
278  //TPZAutoPointer<TPZCompMesh> fMesh;
279 
280 public:
281 
284  {
285  work_items.push_back(el);
286  }
287 
288 #ifdef USING_TBB1
289 
290 protected:
291 
292  typedef spin_mutex MatrixMutex_t;
293  MatrixMutex_t Matrix1Mutex;
294  MatrixMutex_t Matrix2Mutex;
295 
296 public:
297 
299  void run_parallel_for()
300  {
301  /* TBB Parallel for. It will split the range into N sub-ranges and
302  invoke the operator() for each sub-range.*/
303  parallel_for(blocked_range<size_t>(0,work_items.size(), 1 /*IdealGrainSize*/), *this);
304  }
305 
307  void operator()(const blocked_range<size_t>& range)
308  {
309  MatrixMutex_t::scoped_lock lock;
312 
313  for(size_t i=range.begin(); i!=range.end(); ++i ) {
314 
315  TPZCompEl* el = work_items[i];
316 
317  el->CalcStiff(ek,ef);
318 
319  bool has_dependency = el->HasDependency();
320  if(has_dependency)
321  {
322  // the element has dependent nodes
323  ek.ApplyConstraints();
324  ef.ApplyConstraints();
325  }
326 
328 
329  if(mineq != -1 && maxeq != -1)
331 
332  // ThreadAssembly 1 -- Lock 1
333  lock.acquire(Matrix1Mutex);
334  if(!has_dependency)
335  {
336  first->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
337  rhs.AddFel(ef.fMat,ek.fSourceIndex,ek.fDestinationIndex);
338  }
339  else
340  {
342  rhs.AddFel(ef.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
343  }
344  lock.release();
345 
346  // ThreadAssembly 2 -- Lock 2
347  // FIXME. Precisa de um lock
348  lock.acquire(Matrix2Mutex);
350  second->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
351  lock.release();
352  }
353  }
354 
355 #endif // USING TBB
356 
358  void run_serial()
359  {
362 
363  std::vector<TPZCompEl*>::iterator it = work_items.begin();
364  for(; it != work_items.end(); it++)
365  {
366  TPZCompEl* el = *it;
367 
368  el->CalcStiff(ek,ef);
369 
370  bool has_dependency = el->HasDependency();
371  if(has_dependency)
372  {
373  // the element has dependent nodes
374  ek.ApplyConstraints();
375  ef.ApplyConstraints();
376  }
377 
378  ek.ComputeDestinationIndices();
379 
380  fStrMatrix->FilterEquations(ek.fSourceIndex,ek.fDestinationIndex);
381 
382  // ThreadAssembly 1
383  if(!has_dependency)
384  {
385  first->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
386  rhs.AddFel(ef.fMat,ek.fSourceIndex,ek.fDestinationIndex);
387  }
388  else
389  {
390  first->AddKel(ek.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
391  rhs.AddFel(ef.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
392  }
393 
394  // ThreadAssembly 2
395  PermuteScatter(ek.fDestinationIndex);
396  second->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
397  }
398  }
399 
405 
406  parallel_assemble_task_t(TPZStructMatrix *strmat, int _mineq, int _maxeq, TPZMatrix<STATE> *_first,
407  TPZMatrix<STATE> *_second, TPZFMatrix<STATE> &_rhs, TPZVec<int>& permuteScatter) :
408  first(_first), second(_second),
409  rhs(_rhs), fPermuteScatter(permuteScatter), fStrMatrix(strmat)
410  {
411  fStrMatrix->SetEquationRange(_mineq, _maxeq);
412  }
413 
414 };
415 
416 #include"arglib.h"
417 clarg::argInt tbb_pair_pipe_tokens("-tbb_pair_ntokens", "# tokens during assemble TPZPairStructMatrix (level 2) using TBB", 128);
418 
420  TPZMatrix<STATE> *second, TPZFMatrix<STATE> &rhs)
421 {
422 #ifndef USING_TBB1
423 
424  cerr << "TPZPairStructMatrix::TBBAssemble() invoked, but TBB "
425  << "was not linked. Executing SerialAssemble!" << endl;
426  return SerialAssemble(first, second, rhs);
427 
428 #else // if USING_TBB
429  int iel;
430  TPZCompMesh &mesh = *fMesh;
431  int nelem = mesh.NElements();
432  TPZAdmChunkVector<TPZCompEl *> &elementvec = mesh.ElementVec();
433 
434  // Create the pipeline
435  tbb::pipeline pipeline;
436 
437  // Create file-reading writing stage and add it to the pipeline
438  StageOne_t filter1(tbb_pair_pipe_tokens.get_value() /* Number of tokens on the fly */, mesh, fMaterialIds);
439  StageTwo_t filter2(fMesh, mineq, maxeq);
440  StageThree_t<STATE> filter3(*first, rhs);
441  StageFour_t<STATE> filter4(*second, fPermuteScatter);
442 
443  pipeline.add_filter(filter1);
444  pipeline.add_filter(filter2);
445  pipeline.add_filter(filter3);
446  pipeline.add_filter(filter4);
447 
448  // Run the pipeline
449  pipeline.run(filter1.n_tokens() /* Max tokens on the fly: TODO - Tune this parameter */ );
450 
451  pipeline.clear();
452 #endif // USING_TBB
453 }
454 
456 {
457  int iel;
458  TPZCompMesh &mesh = *fStrMatrix.Mesh();
459  int nelem = mesh.NElements();
461 
462  TPZTimer calcstiff("Computing the stiffness matrices");
463  TPZTimer assemble("Assembling the stiffness matrices");
464  TPZAdmChunkVector<TPZCompEl *> &elementvec = mesh.ElementVec();
465 
466  for(iel=0; iel < nelem; iel++) {
467  TPZCompEl *el = elementvec[iel];
468  if(!el) continue;
469  calcstiff.start();
470 
471  el->CalcStiff(ek,ef);
472 
473  calcstiff.stop();
474  assemble.start();
475 
476  if(!el->HasDependency()) {
477  ek.ComputeDestinationIndices();
478  fStrMatrix.FilterEquations(ek.fSourceIndex,ek.fDestinationIndex);
479 
480  first->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
481  rhs.AddFel(ef.fMat,ek.fSourceIndex,ek.fDestinationIndex);
482  PermuteScatter(ek.fDestinationIndex);
483  second->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
484 #ifdef LOG4CXX
485  if(loggerel->isDebugEnabled())
486  {
487  std::stringstream sout;
488  ek.fMat.Print("Element stiffness matrix",sout);
489  ef.fMat.Print("Element right hand side", sout);
490  LOGPZ_DEBUG(loggerel,sout.str())
491  }
492 #endif
493  } else {
494  // the element has dependent nodes
495  ek.ApplyConstraints();
496  ef.ApplyConstraints();
497  ek.ComputeDestinationIndices();
498  //FIXME: (Edson) - O operador é && ou ||
499  fStrMatrix.FilterEquations(ek.fSourceIndex,ek.fDestinationIndex);
500  first->AddKel(ek.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
501  rhs.AddFel(ef.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
502  PermuteScatter(ek.fDestinationIndex);
503  //FIXME: (Edson) - Não deveria utilizar ek.fConstrMat?
504  second->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
505  }
506 
507  assemble.stop();
508  }//fim for iel
509 #ifdef LOG4CXX
510  {
511  std::stringstream sout;
512  sout << "Number of equations " << first->Rows() << std::endl;
513  sout << calcstiff.processName() << " " << calcstiff << std::endl;
514  sout << assemble.processName() << " " << assemble;
515  /* stiffness.Print("Matriz de Rigidez: ",sout);
516  rhs.Print("Vetor de Carga: ",sout);*/
517  if (logger->isDebugEnabled())
518  {
519  LOGPZ_DEBUG(logger, sout.str().c_str());
520  }
521  }
522 #endif
523 
524 }
525 
527 {
528  int nel = index.NElements();
529  int iel;
530  for(iel = 0; iel<nel; iel++)
531  {
532  index[iel] = ((int64_t)fPermuteScatter[index[iel]]);
533  }
534 }
536 {
537  int nel = index.NElements();
538  int iel;
539  for(iel = 0; iel<nel; iel++)
540  {
541  index[iel] = fPermuteScatter[index[iel]];
542  }
543 }
544 
546 {
547 #ifdef PERF_DEBUG
548  std::cout << "TPZPairStructMatrix::Assemble = Assembling the system of equations with " << fNumThreads
549  << " threads (TPZPairStructMatrix::gNumThreads = " << TPZPairStructMatrix::gNumThreads << ")\n";
550 #endif
551 
554 
556  if (numthreads < 0)
557  TBBAssemble(first, second, rhs);
558  else if(numthreads > 0)
559  MultiThread_Assemble(first, second, rhs);
560  else
561  SerialAssemble(first,second,rhs);
562 }
563 
565 {
566  ThreadData threaddata(&fStrMatrix,*first,*second,rhs);
567  threaddata.fPermuteScatter = fPermuteScatter;
568  const int numthreads = fStrMatrix.GetNumThreads();
569  std::vector<pthread_t> allthreads(numthreads+1);
570  int itr;
571  for(itr=0; itr<numthreads; itr++)
572  {
573  PZ_PTHREAD_CREATE(&allthreads[itr], NULL,
574  ThreadData::ThreadWork, &threaddata, __FUNCTION__);
575  }
576 
577  // assemble the first matrix
578  PZ_PTHREAD_CREATE(&allthreads[itr], NULL,
579  ThreadData::ThreadAssembly1, &threaddata, __FUNCTION__);
580 
581  // assemble the second matrix
582  ThreadData::ThreadAssembly2(&threaddata);
583 
584  for(itr=0; itr<numthreads+1; itr++)
585  {
586  PZ_PTHREAD_JOIN(allthreads[itr], NULL, __FUNCTION__);
587  }
588 }
589 
591  TPZFMatrix<STATE> &rhs)
592 : fStrMatrix(strmat),
593 fGlobMatrix1(&mat1), fGlobMatrix2(&mat2), fGlobRhs(&rhs),fNextElement(0)
594 {
595  PZ_PTHREAD_MUTEX_INIT(&fAccessElement,NULL,"TPZPairStructMatrix::ThreadData::ThreadData()");
596 }
597 
599 {
600  PZ_PTHREAD_MUTEX_DESTROY(&fAccessElement,"TPZPairStructMatrix::ThreadData::~ThreadData()");
601 }
602 
604 {
605  ThreadData *data = (ThreadData *) datavoid;
606  // compute the next element (this method is threadsafe)
607  int iel = data->NextElement();
608  TPZCompMesh *cmesh = data->fStrMatrix->Mesh();
609  int nel = cmesh->NElements();
610  while(iel < nel)
611  {
612 
615 
616  TPZCompEl *el = cmesh->ElementVec()[iel];
617  TPZElementMatrix *ekp = ek.operator->();
618  TPZElementMatrix *efp = ef.operator->();
619  TPZElementMatrix &ekr = *ekp;
620  TPZElementMatrix &efr = *efp;
621  el->CalcStiff(ekr,efr);
622 
623 
624  if(!el->HasDependency()) {
626 
628 #ifdef LOG4CXX
629  if(loggerel->isDebugEnabled())
630  {
631  std::stringstream sout;
632  ek->fMat.Print("Element stiffness matrix",sout);
633  ef->fMat.Print("Element right hand side", sout);
634  LOGPZ_DEBUG(loggerel,sout.str())
635  }
636 #endif
637  } else {
638  // the element has dependent nodes
639  ek->ApplyConstraints();
640  ef->ApplyConstraints();
643 
644  }
645 
646 
647  // put the elementmatrices on the stack to be assembled (threadsafe)
648  data->ComputedElementMatrix(iel,ek,ef);
649  // compute the next element (this method is threadsafe)
650  iel = data->NextElement();
651  }
652  data->fAssembly1.Post();
653  data->fAssembly2.Post();
654  return 0;
655 }
656 
658 {
659  int nel = index.NElements();
660  int iel;
661  for(iel = 0; iel<nel; iel++)
662  {
663  index[iel] = fPermuteScatter[index[iel]];
664  }
665 }
667 {
668  int nel = index.NElements();
669  int iel;
670  for(iel = 0; iel<nel; iel++)
671  {
672  index[iel] = ((int64_t)fPermuteScatter[index[iel]]);
673  }
674 }
675 
676 
677 // The function which will compute the assembly
679 {
680  ThreadData *data = (ThreadData *) threaddata;
681  TPZCompMesh *cmesh = data->fStrMatrix->Mesh();
682  int nel = cmesh->NElements();
683  PZ_PTHREAD_MUTEX_LOCK(&(data->fAccessElement),"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
684  int nextel = data->fNextElement;
685  int numprocessed = data->fProcessed1.size();
686  while(nextel < nel || numprocessed)
687  {
688  std::map<int, std::pair< TPZAutoPointer<TPZElementMatrix>, TPZAutoPointer<TPZElementMatrix> > >::iterator itavail;
689  std::set<int>::iterator itprocess;
690  bool keeplooking = false;
691  if(data->fSubmitted1.size() && data->fProcessed1.size())
692  {
693  itavail = data->fSubmitted1.begin();
694  itprocess = data->fProcessed1.begin();
695  if(itavail->first == *itprocess)
696  {
697  // make sure we come back to look for one more element
698  keeplooking = true;
699  // Get a hold of the data
700  data->fProcessed1.erase(itprocess);
701  TPZAutoPointer<TPZElementMatrix> ek = itavail->second.first;
702  TPZAutoPointer<TPZElementMatrix> ef = itavail->second.second;
703  data->fSubmitted1.erase(itavail);
704 #ifdef LOG4CXX
705  int iel = *itprocess;
706  std::stringstream sout;
707  sout << "Assembling element " << iel;
708  if (logger->isDebugEnabled())
709  {
710  LOGPZ_DEBUG(logger, sout.str())
711  }
712 #endif
713  // Release the mutex
714  PZ_PTHREAD_MUTEX_UNLOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
715  // Assemble the matrix
716  if(!ek->HasDependency())
717  {
719  data->fGlobRhs->AddFel(ef->fMat,ek->fSourceIndex,ek->fDestinationIndex);
720  }
721  else
722  {
725  }
726  // acquire the mutex
727  PZ_PTHREAD_MUTEX_LOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
728  }
729  }
730  if(!keeplooking)
731  {
732  PZ_PTHREAD_MUTEX_UNLOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
733  LOGPZ_DEBUG(logger, "Going to sleep within assembly")
734  // wait for a signal
735  data->fAssembly1.Wait();
736  LOGPZ_DEBUG(logger, "Waking up for assembly")
737  PZ_PTHREAD_MUTEX_LOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
738  }
739  nextel = data->fNextElement;
740  numprocessed = data->fProcessed1.size();
741 
742  }
743  PZ_PTHREAD_MUTEX_UNLOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly1()");
744  return 0;
745 }
746 
747 // The function which will compute the assembly
749 {
750  ThreadData *data = (ThreadData *) threaddata;
751  TPZCompMesh *cmesh = data->fStrMatrix->Mesh();
752  int nel = cmesh->NElements();
753  PZ_PTHREAD_MUTEX_LOCK(&(data->fAccessElement),"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
754  int nextel = data->fNextElement;
755  int numprocessed = data->fProcessed2.size();
756  while(nextel < nel || numprocessed)
757  {
758  std::map<int, TPZAutoPointer<TPZElementMatrix> >::iterator itavail;
759  std::set<int>::iterator itprocess;
760  bool keeplooking = false;
761  if(data->fSubmitted2.size() && data->fProcessed2.size())
762  {
763  itavail = data->fSubmitted2.begin();
764  itprocess = data->fProcessed2.begin();
765  if(itavail->first == *itprocess)
766  {
767  // make sure we come back to look for one more element
768  keeplooking = true;
769  // Get a hold of the data
770  data->fProcessed2.erase(itprocess);
771  TPZAutoPointer<TPZElementMatrix> ek = itavail->second;
772  data->fSubmitted2.erase(itavail);
773 #ifdef LOG4CXX
774  int iel = *itprocess;
775  std::stringstream sout;
776  sout << "Assembling element " << iel;
777  if (logger->isDebugEnabled())
778  {
779  LOGPZ_DEBUG(logger, sout.str())
780  }
781 #endif
782  // Release the mutex
783  PZ_PTHREAD_MUTEX_UNLOCK(&(data->fAccessElement),"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
785  data->PermuteScatter(destindex);
786 
787  // Assemble the matrix
788  if(!ek->HasDependency())
789  {
790  data->fGlobMatrix2->AddKel(ek->fMat,ek->fSourceIndex,destindex);
791  }
792  else
793  {
794  data->fGlobMatrix2->AddKel(ek->fConstrMat,ek->fSourceIndex,destindex);
795  }
796  // acquire the mutex
797  PZ_PTHREAD_MUTEX_LOCK(&(data->fAccessElement),"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
798  }
799  }
800  if(!keeplooking)
801  {
802  PZ_PTHREAD_MUTEX_UNLOCK(&(data->fAccessElement),"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
803  LOGPZ_DEBUG(logger, "Going to sleep within assembly")
804  // wait for a signal
805  data->fAssembly2.Wait();
806  LOGPZ_DEBUG(logger, "Waking up for assembly")
807  PZ_PTHREAD_MUTEX_LOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
808  }
809  nextel = data->fNextElement;
810  numprocessed = data->fProcessed2.size();
811 
812  }
813  PZ_PTHREAD_MUTEX_UNLOCK(&data->fAccessElement,"TPZPairStructMatrix::ThreadData::ThreadAssembly2()");
814  return 0;
815 }
816 
818 {
819  PZ_PTHREAD_MUTEX_LOCK(&fAccessElement,"TPZPairStructMatrix::ThreadData::NextElement()");
820  int iel;
821  int nextel = fNextElement;
822  TPZCompMesh *cmesh = fStrMatrix->Mesh();
823  TPZAdmChunkVector<TPZCompEl *> &elementvec = cmesh->ElementVec();
824  int nel = elementvec.NElements();
825  for(iel=fNextElement; iel < nel; iel++)
826  {
827  TPZCompEl *el = elementvec[iel];
828  if(!el) continue;
829  TPZMaterial * mat = el->Material();
830  TPZSubCompMesh *submesh = dynamic_cast<TPZSubCompMesh *> (el);
831  if(!mat)
832  {
833  if(!submesh)
834  {
835  continue;
836  }
837  else if(submesh->NeedsComputing(fStrMatrix->MaterialIds()) == false) continue;
838  }
839  else
840  {
841  int matid = mat->Id();
842  if(this->ShouldCompute(matid) == false) continue;
843  }
844  break;
845  }
846  fNextElement = iel+1;
847  nextel = iel;
848  if(iel<nel)
849  {
850  fProcessed1.insert(iel);
851  fProcessed2.insert(iel);
852  }
853  PZ_PTHREAD_MUTEX_UNLOCK(&fAccessElement,"TPZPairStructMatrix::ThreadData::NextElement()");
854 #ifdef LOG4CXX
855  {
856  std::stringstream sout;
857  sout << __PRETTY_FUNCTION__ << " returning " << nextel << " fNextElement " << fNextElement;
858  if (logger->isDebugEnabled())
859  {
860  LOGPZ_DEBUG(logger, sout.str())
861  }
862  }
863 #endif
864  return nextel;
865 }
866 
867 // put the computed element matrices in the map
869 {
870  PZ_PTHREAD_MUTEX_LOCK(&fAccessElement,"TPZPairStructMatrix::ThreadData::ComputedElementMatrix()");
871  std::pair< TPZAutoPointer<TPZElementMatrix>, TPZAutoPointer<TPZElementMatrix> > el(ek,ef);
872  fSubmitted1[iel] = el;
873  fSubmitted2[iel] = ek;
874  fAssembly1.Post();
875  fAssembly2.Post();
876  PZ_PTHREAD_MUTEX_UNLOCK(&fAccessElement,"TPZPairStructMatrix::ThreadData::ComputedElementMatrix()");
877 }
878 
879 // Set the set of material ids which will be considered when assembling the system
880 void TPZPairStructMatrix::SetMaterialIds(const std::set<int> &materialids)
881 {
882  fStrMatrix.SetMaterialIds(materialids);
883 #ifdef LOG4CXX
884  {
885  std::set<int>::const_iterator it;
886  std::stringstream sout;
887  sout << "setting input material ids ";
888  for(it=materialids.begin(); it!= materialids.end(); it++)
889  {
890  sout << *it << " ";
891  }
892  if (logger->isDebugEnabled())
893  {
894  LOGPZ_DEBUG(logger, sout.str())
895  }
896  }
897 #endif
898 }
int64_t NElements() const
Number of computational elements allocated.
Definition: pzcmesh.h:169
#define PZ_PTHREAD_MUTEX_UNLOCK(mutex, fn)
Definition: pz_pthread.h:79
TPZSemaphore fAssembly2
Semaphore (to wake up the second assembly thread)
The timer class. Utility.
Definition: TPZTimer.h:46
Contains TPZAnalysis class which implements the sequence of actions to perform a finite element analy...
~ThreadData()
Destroy the mutex semaphores and others.
void push_work_item(TPZCompEl *el)
virtual void SetEquationRange(int64_t mineq, int64_t maxeq)
Contains definitions to LOGPZ_DEBUG, LOGPZ_INFO, LOGPZ_WARN, LOGPZ_ERROR and LOGPZ_FATAL, and the implementation of the inline InitializePZLOG(string) function using log4cxx library or not. It must to be called out of "#ifdef LOG4CXX" scope.
Implements a vector class which allows to use external storage provided by the user. Utility.
Definition: pzquad.h:16
pthread_mutex_t fAccessElement
Mutexes (to choose which element is next)
Timing class. Absolutely copied from GNU time. Take a look at
virtual TPZCompMesh * Mesh() const
Access method for the mesh pointer.
Contains the thread data for matrices divided in sub structures.
TPZPairStructMatrix(TPZCompMesh *mesh, TPZVec< int > &permutescatter)
void AddFel(TPZFMatrix< TVar > &rhs, TPZVec< int64_t > &destination)
Performs a right hand side assemblage.
Definition: pzfmatrix.cpp:209
void TBBAssemble(TPZMatrix< STATE > *first, TPZMatrix< STATE > *second, TPZFMatrix< STATE > &rhs)
static void * ThreadWork(void *threaddata)
The function which will compute the matrices.
clarg::argInt tbb_pair_pipe_tokens("-tbb_pair_ntokens", "# tokens during assemble TPZPairStructMatrix (level 2) using TBB", 128)
TPZFNMatrix< 1000, STATE > fMat
Pointer to a blocked matrix object.
Definition: pzelmat.h:41
Contains declaration of TPZCompEl class which defines the interface of a computational element...
std::set< int > fProcessed2
Elements which are being processed maintained by the second global matrix.
virtual void CalcStiff(TPZElementMatrix &ek, TPZElementMatrix &ef)
Computes the element stifness matrix and right hand side.
Definition: pzcompel.h:794
TPZMatrix< STATE > * fGlobMatrix2
Global matrix2.
ThreadData(TPZStructMatrix *strmatrix, TPZMatrix< STATE > &mat1, TPZMatrix< STATE > &mat2, TPZFMatrix< STATE > &rhs)
Initialize the mutex semaphores and others.
int64_t NElements() const
Access method to query the number of elements of the vector.
Implements a chunk vector with free store administration. Utility.
Definition: TPZStream.h:39
Contains the TPZStructMatrixOR class which responsible for a interface among Matrix and Finite Elemen...
void PermuteScatter(TPZVec< int > &index)
parallel_assemble_task_t(TPZStructMatrix *strmat, int _mineq, int _maxeq, TPZMatrix< STATE > *_first, TPZMatrix< STATE > *_second, TPZFMatrix< STATE > &_rhs, TPZVec< int > &permuteScatter)
static void * ThreadAssembly2(void *threaddata)
The function which will compute the assembly.
Iterações do laço podem ser executadas em paralelo. .
std::map< int, TPZAutoPointer< TPZElementMatrix > > fSubmitted2
List of computed element matrices (autopointers?)
TPZManVector< int64_t > fDestinationIndex
Definition: pzelmat.h:53
void ComputeDestinationIndices()
Definition: pzelmat.cpp:126
Refines geometrical mesh (all the elements) num times.
Definition: pzstrmatrix.h:35
This abstract class defines the behaviour which each derived class needs to implement.
Definition: TPZMaterial.h:39
Contains declaration of TPZElementMatrix struct which associates an element matrix with the coeficien...
#define PZ_PTHREAD_JOIN(thread, val, fn)
Definition: pz_pthread.h:34
TPZFMatrix< STATE > * fGlobRhs
Global rhs.
virtual const std::set< int > & MaterialIds()
Returns the material ids.
virtual TPZMaterial * Material() const
Identify the material object associated with the element.
Definition: pzcompel.cpp:959
#define PZ_PTHREAD_MUTEX_LOCK(mutex, fn)
Definition: pz_pthread.h:76
std::string & processName()
Gets the process name (for reporting purposes).
Definition: TPZTimer.h:168
void start()
Turns the timer on.
Definition: TPZTimer.cpp:28
Implements a group of computational elements as a mesh and an element. Computational Mesh...
Definition: pzsubcmesh.h:36
virtual void SetNumThreads(int n)
#define LOGPZ_DEBUG(A, B)
Define log for debug info.
Definition: pzlog.h:87
void parallel_for(int n, body_t &obj)
Definition: pzparallel.h:24
int64_t Rows() const
Returns number of rows.
Definition: pzmatrix.h:803
TPZVec< int > fPermuteScatter
virtual void AddKel(TPZFMatrix< TVar > &elmat, TPZVec< int64_t > &destinationindex)
Add a contribution of a stiffness matrix.
Definition: pzmatrix.cpp:506
void MultiThread_Assemble(TPZMatrix< STATE > *first, TPZMatrix< STATE > *second, TPZFMatrix< STATE > &rhs)
Contains the TPZPairStructMatrix class.
#define PZ_PTHREAD_MUTEX_DESTROY(mutex, fn)
Definition: pz_pthread.h:73
TPZVec< int > fPermuteScatter
Vector which defines the permutation of all equations to internal equations.
TPZManVector< int64_t > fSourceIndex
Definition: pzelmat.h:53
void PermuteScatter(TPZVec< int > &index)
TPZMatrix< STATE > * fGlobMatrix1
Global matrix1.
Full matrix class. Matrix.
Definition: pzfmatrix.h:32
std::vector< TPZCompEl * > work_items
TPZStructMatrix fStrMatrix
void PermuteScatter(TPZVec< int > &index)
bool NeedsComputing(const std::set< int > &matids) override
Verifies if any element needs to be computed corresponding to the material ids.
std::set< int > fProcessed1
Elements which are being processed maintained by the first global matrix.
void SerialAssemble(TPZMatrix< STATE > *first, TPZMatrix< STATE > *second, TPZFMatrix< STATE > &rhs)
This class associates an element matrix with the coeficients of its contribution in the global stiffn...
Definition: pzelmat.h:30
TPZFNMatrix< 1000, STATE > fConstrMat
Pointer to the constrained matrix object.
Definition: pzelmat.h:48
void ApplyConstraints()
Apply the constraints applied to the nodes by transforming the tangent matrix and right hand side...
Definition: pzelmat.cpp:186
void Assemble(TPZMatrix< STATE > *first, TPZMatrix< STATE > *second, TPZFMatrix< STATE > &rhs)
Contains declaration of TPZSubCompMesh class which implements a group of computational elements as a ...
bool ShouldCompute(int matid)
Establish whether the element should be computed.
virtual void SetMaterialIds(const std::set< int > &materialids)
Set the set of material ids which will be considered when assembling the system.
int NextElement()
Look for an element index which needs to be computed and put it on the stack.
void SetMaterialIds(const std::set< int > &materialids)
Set the set of material ids which will be considered when assembling the system.
Implements computational mesh. Computational Mesh.
Definition: pzcmesh.h:47
const T & get_value() const
Definition: arglib.h:177
TPZAdmChunkVector< TPZCompEl * > & ElementVec()
Returns a reference to the element pointers vector.
Definition: pzcmesh.h:183
#define PZ_PTHREAD_CREATE(thread, attr, routine, args, fn)
Definition: pz_pthread.h:31
virtual int GetNumThreads() const
int Id() const
Definition: TPZMaterial.h:170
TPZSemaphore fAssembly1
Semaphore (to wake up the first assembly thread)
virtual void FilterEquations(TPZVec< int64_t > &origindex, TPZVec< int64_t > &destindex) const
Filter out the equations which are out of the range.
virtual void Print(std::ostream &out) const
Definition: pzmatrix.h:253
void stop()
Turns the timer off, and computes the elapsed time.
Definition: TPZTimer.cpp:36
int64_t NElements() const
Returns the number of elements of the vector.
Definition: pzvec.h:190
static void * ThreadAssembly1(void *threaddata)
The function which will compute the assembly.
#define PZ_PTHREAD_MUTEX_INIT(mutex, attr, fn)
Definition: pz_pthread.h:70
Defines the interface of a computational element. Computational Element.
Definition: pzcompel.h:59
TPZStructMatrix * fStrMatrix
Current structmatrix object.
virtual int HasDependency()
Returns 1 if the element has at least one dependent node. Returns 0 otherwise.
Definition: pzcompel.cpp:565
bool HasDependency()
Returns true if the element has at least one dependent node. Returns false otherwise.
Definition: pzelmat.cpp:482
std::map< int, std::pair< TPZAutoPointer< TPZElementMatrix >, TPZAutoPointer< TPZElementMatrix > > > fSubmitted1
List of computed element matrices (autopointers?)
Root matrix class (abstract). Matrix.
Definition: pzmatrix.h:60
void ComputedElementMatrix(int iel, TPZAutoPointer< TPZElementMatrix > &ek, TPZAutoPointer< TPZElementMatrix > &ef)
Put the computed element matrices in the map.
This class implements a reference counter mechanism to administer a dynamically allocated object...