NeoPZ
pzstrmatrixtbb.cpp
Go to the documentation of this file.
1 
3 
8 #ifdef USING_TBB
9 
10 #include "pzstrmatrixtbb.h"
11 
12 #include "pzvec.h"
13 #include "pzfmatrix.h"
14 #include "pzmanvector.h"
15 #include "pzadmchunk.h"
16 #include "pzcmesh.h"
17 #include "pzgmesh.h"
18 #include "pzelmat.h"
19 #include "pzcompel.h"
20 #include "pzintel.h"
21 #include "pzsubcmesh.h"
22 #include "pzanalysis.h"
23 #include "pzsfulmat.h"
24 
25 #include "pzgnode.h"
26 #include "TPZTimer.h"
27 #include "TPZThreadTools.h"
28 
29 
30 #include "pzcheckconsistency.h"
31 #include "TPZMaterial.h"
32 
33 #include "pzlog.h"
34 
35 #include "pz_pthread.h"
36 
37 #ifdef LOG4CXX
38 static LoggerPtr logger(Logger::getLogger("pz.strmatrix.TPZStructMatrixTBB"));
39 static LoggerPtr loggerel(Logger::getLogger("pz.strmatrix.element"));
40 static LoggerPtr loggerel2(Logger::getLogger("pz.strmatrix.elementinterface"));
41 static LoggerPtr loggerelmat(Logger::getLogger("pz.strmatrix.elementmat"));
42 static LoggerPtr loggerCheck(Logger::getLogger("pz.strmatrix.checkconsistency"));
43 #endif
44 
45 #ifdef CHECKCONSISTENCY
46 static TPZCheckConsistency stiffconsist("ElementStiff");
47 #endif
48 
49 
50 #include "run_stats_table.h"
51 
52 
53 static RunStatsTable stat_ass_graph_tbb("-ass_graph_tbb", "Run statistics table for the graph creation, coloring and tbb::flow::graph TPZStructMatrixTBB.");
54 
55 TPZStructMatrixTBB::TPZStructMatrixTBB() : TPZStructMatrixBase() {
56  this->SetNumThreads(0);
57 #ifdef USING_TBB
58  this->fFlowGraph = NULL;
59 #endif
60 }
61 
62 TPZStructMatrixTBB::TPZStructMatrixTBB(TPZCompMesh *mesh, bool onlyrhs) : TPZStructMatrixBase(mesh) {
63  this->SetNumThreads(0);
64  if (mesh)
65  fEquationFilter = mesh->NEquations();
66 #ifdef USING_TBB
67  this->fFlowGraph = new TPZFlowGraph(this,onlyrhs);
68 #endif
69 }
70 
71 TPZStructMatrixTBB::TPZStructMatrixTBB(TPZAutoPointer<TPZCompMesh> cmesh, bool onlyrhs) : TPZStructMatrixBase(cmesh) {
72  this->SetNumThreads(0);
73 #ifdef USING_TBB
74  this->fFlowGraph = new TPZFlowGraph(this, onlyrhs);
75 #endif
76 }
77 
78 TPZStructMatrixTBB::TPZStructMatrixTBB(const TPZStructMatrixTBB &copy) : TPZStructMatrixBase(copy)
79 {
80 #ifdef USING_TBB
81  fFlowGraph = new TPZFlowGraph(*copy.fFlowGraph);
82 #endif
83 }
84 
85 
86 
87 TPZStructMatrixTBB::~TPZStructMatrixTBB()
88 {
89 #ifdef USING_TBB
90  if (fFlowGraph) {
91  delete fFlowGraph;
92  }
93 #endif
94 }
95 
96 TPZMatrix<STATE> *TPZStructMatrixTBB::Create() {
97  std::cout << "TPZStructMatrixTBB::Create should never be called\n";
98  return 0;
99 }
100 
101 TPZStructMatrixTBB *TPZStructMatrixTBB::Clone() {
102  return new TPZStructMatrixTBB(*this);
103 
104 }
105 
106 static RunStatsTable ass_stiff("-ass_stiff", "Assemble Stiffness");
107 static RunStatsTable ass_rhs("-ass_rhs", "Assemble Stiffness");
108 
109 void TPZStructMatrixTBB::Assemble(TPZMatrix<STATE> & stiffness, TPZFMatrix<STATE> & rhs,TPZAutoPointer<TPZGuiInterface> guiInterface){
110  ass_stiff.start();
111  if (fEquationFilter.IsActive()) {
112  int64_t neqcondense = fEquationFilter.NActiveEquations();
113 #ifdef PZDEBUG
114  if (stiffness.Rows() != neqcondense) {
115  DebugStop();
116  }
117 #endif
118  TPZFMatrix<STATE> rhsloc(neqcondense,rhs.Cols(),0.);
119  this->MultiThread_Assemble(stiffness,rhsloc,guiInterface);
120  fEquationFilter.Scatter(rhsloc, rhs);
121  }
122  else
123  {
124  this->MultiThread_Assemble(stiffness,rhs,guiInterface);
125 
126  }
127  ass_stiff.stop();
128 }
129 
130 void TPZStructMatrixTBB::Assemble(TPZFMatrix<STATE> & rhs,TPZAutoPointer<TPZGuiInterface> guiInterface){
131  ass_rhs.start();
133  {
134  int64_t neqcondense = fEquationFilter.NActiveEquations();
135  int64_t neqexpand = fEquationFilter.NEqExpand();
136  if(rhs.Rows() != neqexpand || Norm(rhs) != 0.)
137  {
138  DebugStop();
139  }
140  TPZFMatrix<STATE> rhsloc(neqcondense,1,0.);
141  this->MultiThread_Assemble(rhsloc,guiInterface);
142  fEquationFilter.Scatter(rhsloc,rhs);
143  }
144  else
145  {
146  this->MultiThread_Assemble(rhs,guiInterface);
147  }
148  ass_rhs.stop();
149 }
150 
151 TPZMatrix<STATE> * TPZStructMatrixTBB::CreateAssemble(TPZFMatrix<STATE> &rhs, TPZAutoPointer<TPZGuiInterface> guiInterface)
152 {
153  TPZMatrix<STATE> *stiff = Create();
154 
155  int64_t cols = MAX(1, rhs.Cols());
156  rhs.Redim(fEquationFilter.NEqExpand(),cols);
157 
158  Assemble(*stiff,rhs,guiInterface);
159 
160 #ifdef LOG4CXX2
161  if(loggerel->isDebugEnabled())
162  {
163  std::stringstream sout;
164  stiff->Print("Stiffness matrix",sout);
165  rhs.Print("Right hand side", sout);
166  LOGPZ_DEBUG(loggerel,sout.str())
167  }
168 #endif
169  return stiff;
170 
171 }
172 
173 void TPZStructMatrixTBB::MultiThread_Assemble(TPZMatrix<STATE> & mat, TPZFMatrix<STATE> & rhs, TPZAutoPointer<TPZGuiInterface> guiInterface)
174 {
175 #ifdef USING_TBB
176  this->fFlowGraph->ExecuteGraph(&rhs, &mat);
177 #else
178  std::cout << "To use the tbb flow graph assemble please compile the NeoPZ with USING_TBB." << std::endl;
179  DebugStop();
180 #endif
181 }
182 
183 
184 void TPZStructMatrixTBB::MultiThread_Assemble(TPZFMatrix<STATE> & rhs,TPZAutoPointer<TPZGuiInterface> guiInterface)
185 {
186 #ifdef USING_TBB
187  this->fFlowGraph->ExecuteGraph(&rhs);
188 #else
189  std::cout << "To use the tbb flow graph assemble please compile the NeoPZ with USING_TBB." << std::endl;
190  DebugStop();
191 #endif
192 }
193 
194 
195 
196 static bool CanAssemble(TPZStack<int64_t> &connectlist, TPZVec<int64_t> &elContribute)
197 {
198  for (int i = 0 ; i < connectlist.NElements() ; i++)
199  {
200  if (elContribute[connectlist[i]] >= 0){
201  return false;
202  }
203  }
204  return true;
205 }
206 
207 static void AssembleColor(int el,TPZStack<int64_t> &connectlist, TPZVec<int64_t> &elContribute)
208 {
209  for (int i = 0 ; i < connectlist.NElements() ; i++)
210  {
211  elContribute[connectlist[i]] = el;
212  }
213 }
214 
215 static int WhoBlockedMe(TPZStack<int64_t> &connectlist, TPZVec<int64_t> &elContribute, TPZVec<int64_t> &elSeqinv)
216 {
217  int el = -1;
218  for (int i = 0 ; i < connectlist.NElements() ; i++)
219  {
220  int elBlocked = elContribute[connectlist[i]];
221  if (elBlocked == -1) continue;
222  int elBlockedIndex = elSeqinv[elBlocked];
223  if (el == -1) el = elBlockedIndex;
224  if (elBlockedIndex < el) el = elBlockedIndex;
225  }
226  return el;
227 }
228 
229 static void RemoveEl(int el,TPZCompMesh *cmesh,TPZVec<int64_t> &elContribute,int64_t elSequence)
230 {
231  TPZCompEl *cel = cmesh->ElementVec()[el];
232  if(!cel) DebugStop();
233  TPZStack<int64_t> connectlist;
234  cel->BuildConnectList(connectlist);
235  for (int i = 0 ; i < connectlist.NElements() ; i++)
236  {
237  int conindex = connectlist[i];
238  if (elContribute[conindex] != elSequence){
239  DebugStop();
240  }
241  elContribute[conindex] = -1;
242  }
243 }
244 
245 static int MinPassIndex(TPZStack<int64_t> &connectlist,TPZVec<int64_t> &elContribute, TPZVec<int64_t> &passIndex)
246 {
247  int minPassIndex = -1;
248  for (int i = 0 ; i < connectlist.NElements() ; i++)
249  {
250  int elcont = elContribute[connectlist[i]];
251  int passindex = -1;
252  if (elcont != -1){
253  passindex = passIndex[elcont];
254  if (minPassIndex == -1) minPassIndex = passindex;
255  }
256  if (minPassIndex < passindex) minPassIndex = passindex;
257  }
258  return minPassIndex;
259 }
260 
261 #ifdef USING_TBB
262 void TPZStructMatrixTBB::TPZFlowGraph::ElementColoring()
263 {
264 
265  const int64_t nnodes = fCMesh->NConnects();
266  const int64_t nel = fCMesh->ElementVec().NElements();
267 
268  TPZManVector<int64_t> elContribute(nnodes,-1), passIndex(nel,-1);
269 
270  fFirstElColor.Push(0);
271  felSequenceColor.Resize(nel);
272  felSequenceColor.Fill(-1);
273  felSequenceColorInv.Resize(nel, -1);
274  felSequenceColorInv.Fill(-1);
275  fnextBlocked.Resize(nel);
276  fnextBlocked.Fill(-1);
277  int nelProcessed = 0;
278  int currentEl = 0;
279  int currentPassIndex = 0;
280  while (nelProcessed < fElementOrder.NElements()){
281 
282  int64_t elindex = fElementOrder[currentEl];
283 
284  if(felSequenceColorInv[elindex] == -1)
285  {
286  TPZCompEl *cel = fCMesh->ElementVec()[elindex];
287 
288 
289  if(!cel) continue;
290  TPZStack<int64_t> connectlist;
291  cel->BuildConnectList(connectlist);
292 // std::cout << "elcontribute " << elContribute << std::endl;
293 // std::cout << "connectlist " << connectlist << std::endl;
294  int minPass = MinPassIndex(connectlist,elContribute,passIndex);
295  if (minPass == -1){
296  passIndex[elindex] = currentPassIndex;
297  AssembleColor(elindex,connectlist,elContribute);
298  felSequenceColor[nelProcessed] = elindex;
299  felSequenceColorInv[elindex] = nelProcessed;
300  nelProcessed++;
301  }
302  else if (minPass == currentPassIndex){
303  }
304  else if (minPass < currentPassIndex){
305  while (!CanAssemble(connectlist,elContribute)){
306  const int el = WhoBlockedMe(connectlist,elContribute, felSequenceColorInv);
307  if (fnextBlocked[el] == -1) fnextBlocked[el] = nelProcessed;
308  int locindex = felSequenceColor[el];
309  RemoveEl(locindex,fCMesh,elContribute,locindex);
310 // std::cout << "elcontribute " << elContribute << std::endl;
311  }
312  passIndex[elindex] = currentPassIndex;
313  AssembleColor(elindex,connectlist,elContribute);
314  felSequenceColor[nelProcessed] = elindex;
315  felSequenceColorInv[elindex] = nelProcessed;
316  nelProcessed++;
317  }
318  else{
319  DebugStop();
320  }
321  }
322  currentEl++;
323  if (currentEl == fElementOrder.NElements()){
324  fFirstElColor.Push(nelProcessed);
325  currentEl = 0;
326  currentPassIndex++;
327  }
328  }
329 
330 #ifdef PZDEBUG
331  std::ofstream toto("../ColorMeshDebug.txt");
332  toto << "elSequence\n" << fElementOrder << std::endl;
333  toto << "elSequenceColor\n" << felSequenceColor << std::endl;
334  toto << "elSequenceColorInv\n" << felSequenceColorInv << std::endl;
335  toto << "elBlocked\n" << fnextBlocked << std::endl;
336  toto << "elContribute\n" << elContribute << std::endl;
337  toto << "fFirstElColor " << fFirstElColor << std::endl;
338  toto << "passIndex\n" << passIndex << std::endl;
339  toto.close();
340 #endif
341 }
342 
343 TPZStructMatrixTBB::TPZFlowGraph::TPZFlowGraph(TPZStructMatrixTBB *strmat, bool onlyrhs)
344 : fCMesh(strmat->Mesh()), fStruct(strmat), fGlobMatrix(0), fGlobRhs(0), fOnlyRhs(onlyrhs)
345 {
346  this->OrderElements();
347  this->ElementColoring();
348  if (fOnlyRhs) {
349  this->CreateGraphRhs();
350  }
351  else
352  {
353  this->CreateGraph();
354  }
355 }
356 
357 TPZStructMatrixTBB::TPZFlowGraph::~TPZFlowGraph()
358 {
359 }
360 
361 void TPZStructMatrixTBB::TPZFlowGraph::OrderElements()
362 {
363  int numelconnected = 0;
364  int nconnect = fCMesh->ConnectVec().NElements();
365  int ic;
366 // firstelconnect contains the first element index in the elconnect vector
367  TPZVec<int> firstelconnect(nconnect+1);
368  firstelconnect[0] = 0;
369  for(ic=0; ic<nconnect; ic++) {
370  numelconnected += fCMesh->ConnectVec()[ic].NElConnected();
371  firstelconnect[ic+1] = firstelconnect[ic]+fCMesh->ConnectVec()[ic].NElConnected();
372  }
373 // cout << "numelconnected " << numelconnected << endl;
374 // cout << "firstelconnect ";
375 // for(ic=0; ic<nconnect; ic++) cout << firstelconnect[ic] << ' ';
376  TPZVec<int> elconnect(numelconnected,-1);
377  int el;
378  TPZCompEl *cel;
379  for(el=0; el<fCMesh->ElementVec().NElements(); el++) {
380  cel = fCMesh->ElementVec()[el];
381  if(!cel) continue;
382  TPZStack<int64_t> connectlist;
383  cel->BuildConnectList(connectlist);
384  int nc = connectlist.NElements();
385  int ic;
386  for(ic=0; ic<nc; ic++) {
387  int cindex = connectlist[ic];
388  elconnect[firstelconnect[cindex]] = el;
389  firstelconnect[cindex]++;
390  }
391  }
392 // for(ic=0; ic<numelconnected; ic++) cout << elconnect[ic] << endl;
393  firstelconnect[0] = 0;
394 
395  for(ic=0; ic<nconnect; ic++) {
396  firstelconnect[ic+1] = firstelconnect[ic]+fCMesh->ConnectVec()[ic].NElConnected();
397  }
398 
399  fElementOrder.Resize(fCMesh->ElementVec().NElements(),-1);
400  fElementOrder.Fill(-1);
401  TPZVec<int> nodeorder(fCMesh->ConnectVec().NElements(),-1);
402  firstelconnect[0] = 0;
403  for(ic=0; ic<nconnect; ic++) {
404  int seqnum = fCMesh->ConnectVec()[ic].SequenceNumber();
405  if(seqnum >= 0) nodeorder[seqnum] = ic;
406  }
407 // cout << "nodeorder ";
408  /* for(ic=0; ic<fMesh->ConnectVec().NElements(); ic++) cout << nodeorder[ic] << ' ';
409  cout << endl;
410  cout.flush();*/
411 
412  int seq;
413  int elsequence = 0;
414  TPZVec<int> elorderinv(fCMesh->ElementVec().NElements(),-1);
415  for(seq=0; seq<nconnect; seq++) {
416  ic = nodeorder[seq];
417  if(ic == -1) continue;
418  int firstind = firstelconnect[ic];
419  int lastind = firstelconnect[ic+1];
420  int ind;
421  for(ind=firstind; ind<lastind; ind++) {
422  el = elconnect[ind];
423  if(el == -1) {
424  continue;
425  }
426  if(elorderinv[el]==-1) elorderinv[el] = elsequence++;
427  }
428  }
429  elsequence = 0;
430  for(seq=0;seq<fCMesh->ElementVec().NElements();seq++) {
431  if(elorderinv[seq] == -1) continue;
432  fElementOrder[elorderinv[seq]] = seq;
433  }
434 
435  for(seq=0;seq<fCMesh->ElementVec().NElements();seq++) {
436  if(fElementOrder[seq]==-1) break;
437  }
438 
439  fElementOrder.Resize(seq);
440 }
441 
442 TPZStructMatrixTBB::TPZFlowGraph::TPZFlowGraph(TPZFlowGraph const &copy)
443 : fCMesh(copy.fStruct->Mesh()), fStruct(copy.fStruct), fGlobMatrix(0), fGlobRhs(0), fOnlyRhs(copy.fOnlyRhs), fFirstElColor(copy.fFirstElColor)
444 {
445  this->fnextBlocked = copy.fnextBlocked;
446  this->felSequenceColor = copy.felSequenceColor;
447  this->felSequenceColorInv = copy.felSequenceColorInv;
448  this->fElementOrder = copy.fElementOrder;
449  if (fOnlyRhs) {
450  this->CreateGraphRhs();
451  }
452  else
453  {
454  this->CreateGraph();
455  }
456 }
457 
458 void TPZStructMatrixTBB::TPZFlowGraph::CreateGraphRhs()
459 {
460  // create nodes for successive sum of rhs
461  int64_t numcolors = fFirstElColor.size()-1;
462  fNodeDest.resize(numcolors);
463  fNodeDest.Fill(-1);
464  int twoexp = 0;
466  TPZStack<int64_t> numreceive;
467  std::set<int64_t> received;
468  int index = 0;
469  while (numcolors>1) {
470  int64_t num = 0;
471  twoexp++;
472  int64_t halfnumcolors = (numcolors / 2) + numcolors%2;
473  for (int64_t i=halfnumcolors; i< numcolors; i++) {
474  int64_t nr=0;
475  if (received.find(i-halfnumcolors) == received.end()) {
476  nr++;
477  received.insert(i-halfnumcolors);
478  fNodeDest[i-halfnumcolors] = sumcolors.size();
479  }
480  if (received.find(i) == received.end()) {
481  nr++;
482  received.insert(i);
483  fNodeDest[i] = sumcolors.size();
484  }
485  std::pair<int64_t, int64_t> temp(i-halfnumcolors,i);
486  sumcolors.Push(temp);
487  numreceive.Push(nr);
488  }
489  numcolors = halfnumcolors;
490  }
491  numcolors = fFirstElColor.size()-1;
492  fNodes.resize(sumcolors.size());
493  // create the nodes and the links between them
494  // the first nodes that mentions an index receives the rhs
495  for (int64_t i=0; i<sumcolors.size(); i++) {
496  TSumTwoColors block(sumcolors[i].first,sumcolors[i].second,&fRhsFat);
497  fNodes[i] = new tbb::flow::continue_node<tbb::flow::continue_msg>(fGraph,numreceive[i],block);
498  }
499  for (int64_t i = sumcolors.size()-1; i>0; i--) {
500  int rhsindex = sumcolors[i].first;
501  for (int64_t j=i-1; j>=0; j++) {
502  if (sumcolors[j].first == rhsindex || sumcolors[j].second == rhsindex) {
503  tbb::flow::make_edge(*fNodes[i], *fNodes[j]);
504  break;
505  }
506  }
507  }
508  int64_t neq = fCMesh->NEquations();
509  fRhsFat.Redim(neq, numcolors);
510 
511 }
512 
513 
514 
515 void TPZStructMatrixTBB::TPZFlowGraph::CreateGraph()
516 {
517  int64_t nelem = fCMesh->NElements();
518  int64_t nconnects = fCMesh->NConnects();
519  int64_t numberOfElements=felSequenceColor.NElements();
520 
521  TPZVec<int64_t> elementloaded(nconnects,-1);
522 
523  fNodes.resize(numberOfElements);
524  fElMatPointers.Resize(numberOfElements);
525  for (int64_t iel=0; iel<numberOfElements; iel++) {
526  TPZAssembleTask body(iel,this);
527  fNodes[iel] = new tbb::flow::continue_node<tbb::flow::continue_msg>(fGraph,1,body);
528  }
529 
530 
531  for (int64_t graphindex = 0; graphindex<numberOfElements; graphindex++) {
532  int64_t el = felSequenceColor[graphindex];
533  TPZCompEl *cel = fCMesh->Element(el);
534  if (!cel) {
535  continue;
536  }
537  TPZStack<int64_t> connects;
538  cel->BuildConnectList(connects);
539  std::set<int64_t> fromwhere;
540  for (int ic=0; ic<connects.size(); ic++) {
541  int64_t c = connects[ic];
542  if (elementloaded[c] != -1) {
543  int64_t elorig = elementloaded[c];
544 // in order to compute only once
545  if (fromwhere.find(elorig) == fromwhere.end()) {
546 #ifdef LOG4CXX
547  if (logger->isDebugEnabled()) {
548  std::stringstream sout;
549  sout << "Adding edge from " << elorig << " to " << graphindex;
550  LOGPZ_DEBUG(logger, sout.str())
551  }
552 #endif
553 
554  make_edge(*fNodes[elorig], *fNodes[graphindex]);
555  }
556  fromwhere.insert(elorig);
557  }
558  }
559 
560  for (int ic=0; ic<connects.size(); ic++) {
561  int64_t c = connects[ic];
562  elementloaded[c] = graphindex;
563  }
564  }
565 
566 }
567 
568 
569 void TPZStructMatrixTBB::TPZFlowGraph::ExecuteGraph(TPZFMatrix<STATE> *rhs, TPZMatrix<STATE> *matrix)
570 {
571  if (fOnlyRhs && matrix != 0) {
572  DebugStop();
573  }
574  this->fGlobMatrix = matrix;
575  this->fGlobRhs = rhs;
576 
577 
578  TPZCalcTask calcTasks(this);
579  parallel_for(tbb::blocked_range<int64_t>(0, felSequenceColor.size()), calcTasks );
580 
581  fGraph.wait_for_all();
582 }
583 
584 void TPZStructMatrixTBB::TPZFlowGraph::ExecuteGraph(TPZFMatrix<STATE> *rhs)
585 {
586  if (!fOnlyRhs) {
587  DebugStop();
588  }
589  this->fGlobRhs = rhs;
590  this->fGlobMatrix = 0;
591  int64_t numcolors = fFirstElColor.size()-1;
592  fGlobRhs->Redim(this->fGlobRhs->Rows(), numcolors);
593 
594  TAssembleOneColor onecolor(this);
595  parallel_for(tbb::blocked_range<int64_t>(0, fFirstElColor.size()-1), onecolor );
596 
597  fGraph.wait_for_all();
598  int64_t nr = fRhsFat.Rows();
599  for (int64_t r=0; r<nr; r++) {
600  (*fGlobRhs)(r,0) = fRhsFat(r,0);
601  }
602 }
603 
604 void TPZStructMatrixTBB::TPZFlowGraph::TAssembleOneColor::operator()(const tbb::blocked_range<int64_t> &range) const
605 {
606  for(int64_t color = range.begin(); color != range.end(); ++color)
607  {
608  TComputeElementRange elrange(fFlowGraph,color);
609  int64_t firstel = fFlowGraph->fFirstElColor[color];
610  int64_t lastel = fFlowGraph->fFirstElColor[color+1];
611  parallel_for(tbb::blocked_range<int64_t>(firstel,lastel),elrange);
612  // trigger the sum node
613  int64_t node = fFlowGraph->fNodeDest[color];
614  (fFlowGraph->fNodes)[node]->try_put(tbb::flow::continue_msg());
615 
616  }
617 }
618 
619 void TPZStructMatrixTBB::TPZFlowGraph::TComputeElementRange::operator()(const tbb::blocked_range<int64_t> &range) const
620 {
621  TPZCompMesh *cmesh = fFlowGraph->fCMesh;
622  TPZAutoPointer<TPZGuiInterface> guiInterface = fFlowGraph->fGuiInterface;
624 
625  for (int64_t iel=range.begin(); iel != range.end(); iel++)
626  {
627 #ifdef LOG4CXX
628  if (logger->isDebugEnabled()) {
629  std::stringstream sout;
630  sout << "Computing element " << iel;
631  LOGPZ_DEBUG(logger, sout.str())
632  }
633 #endif
634 #ifdef LOG4CXX
635  std::stringstream sout;
636  sout << "Element " << iel << " elapsed time ";
637  TPZTimer timeforel(sout.str());
638  timeforel.start();
639 #endif
640 
641  int element = fFlowGraph->felSequenceColor[iel];
642 
643  if (element >= 0){
644 
645  TPZCompEl *el = cmesh->ElementVec()[element];
646 
647  if(!el) return;
648 
649  el->CalcResidual(ef);
650 
651  if(!el->HasDependency()) {
652 
653  ef.ComputeDestinationIndices();
654  fFlowGraph->fStruct->FilterEquations(ef.fSourceIndex,ef.fDestinationIndex);
655  } else
656  {
657  ef.ApplyConstraints();
658  ef.ComputeDestinationIndices();
659  fFlowGraph->fStruct->FilterEquations(ef.fSourceIndex,ef.fDestinationIndex);
660  }
661 
662  }
663 
664  int64_t nrows = fFlowGraph->fGlobRhs->Rows();
665  TPZFMatrix<STATE> locrhs(nrows,1,&fFlowGraph->fRhsFat(0, fColor),nrows);
666 
667  if(!ef.HasDependency()) {
668 
669  locrhs.AddFel(ef.fMat,ef.fSourceIndex,ef.fDestinationIndex);
670  } else
671  {
672  locrhs.AddFel(ef.fConstrMat,ef.fSourceIndex,ef.fDestinationIndex);
673  }
674 
675  } // outsided if
676 
677 
678 }
679 
680 
681 tbb::flow::continue_msg TPZStructMatrixTBB::TPZFlowGraph::TPZAssembleTask::operator()(const tbb::flow::continue_msg &msg)
682 {
683 #ifdef LOG4CXX
684  if (logger->isDebugEnabled())
685  {
686  std::stringstream sout;
687  sout << __PRETTY_FUNCTION__ << " Element " << this->fIel;
688  LOGPZ_DEBUG(logger, sout.str())
689  }
690 #endif
691  TPZElementMatrix *Ek = fElMat->fEk;
692  TPZElementMatrix *Ef = fElMat->fEf;
693 #ifdef PZDEBUG
694  if (!Ef) {
695  DebugStop();
696  }
697 #endif
698 
699  if(fOrigin->fGlobMatrix) {
700 // assemble the matrix
701  if(!Ek->HasDependency()) {
702  fOrigin->fGlobMatrix->AddKel(Ek->fMat,Ek->fSourceIndex,Ek->fDestinationIndex);
703  fOrigin->fGlobRhs->AddFel(Ef->fMat,Ek->fSourceIndex,Ek->fDestinationIndex);
704  } else {
705  fOrigin->fGlobMatrix->AddKel(Ek->fConstrMat,Ek->fSourceIndex,Ek->fDestinationIndex);
706  fOrigin->fGlobRhs->AddFel(Ef->fConstrMat,Ek->fSourceIndex,Ek->fDestinationIndex);
707  }
708  } else {
709  if(!Ef->HasDependency()) {
710  fOrigin->fGlobRhs->AddFel(Ef->fMat,Ef->fSourceIndex,Ef->fDestinationIndex);
711  } else {
712  fOrigin->fGlobRhs->AddFel(Ef->fConstrMat,Ef->fSourceIndex,Ef->fDestinationIndex);
713  }
714  }
715  if (Ek) {
716  delete Ek;
717  fElMat->fEk = 0;
718  }
719  delete Ef;
720  fElMat->fEf = 0;
721 
722  return tbb::flow::continue_msg();
723 }
724 
725 void TPZStructMatrixTBB::TPZFlowGraph::TPZCalcTask::operator()(const tbb::blocked_range<int64_t>& range) const
726 {
727  TPZCompMesh *cMesh = fFlowGraph->fCMesh;
728 
729  TPZVec<int64_t> &elSequenceColor = fFlowGraph->felSequenceColor;
730 
731  for(int iel = range.begin(); iel != range.end(); ++iel) {
732 
733  int element = elSequenceColor[iel];
734 
735  if (element < 0)
736  {
737  DebugStop();
738  }
739 
740  TPZAssembleTask Assemble = tbb::flow::copy_body<TPZAssembleTask,tbb::flow::continue_node<tbb::flow::continue_msg> >(*fFlowGraph->fNodes[element]);
741  if (Assemble.fIel != element) {
742  DebugStop();
743  }
744  if (fFlowGraph->fGlobMatrix)
745  {
746  (Assemble.fElMat->fEk) = new TPZElementMatrix(cMesh,TPZElementMatrix::EK);
747  }
748  Assemble.fElMat->fEf = new TPZElementMatrix(cMesh,TPZElementMatrix::EF);
749 
750  TPZElementMatrix *ek = (Assemble.fElMat->fEk);
751  TPZElementMatrix *ef = (Assemble.fElMat->fEf);
752 
753  TPZCompEl *el = cMesh->ElementVec()[element];
754 
755  if(!el) continue;
756 
757  if (fFlowGraph->fGlobMatrix)
758  el->CalcStiff(*ek,*ef);
759  else
760  el->CalcResidual(*ef);
761 
762  if(!el->HasDependency()) {
763 
764  if (fFlowGraph->fGlobMatrix) {
766  fFlowGraph->fStruct->FilterEquations(ek->fSourceIndex,ek->fDestinationIndex);
767  } else {
769  fFlowGraph->fStruct->FilterEquations(ef->fSourceIndex,ef->fDestinationIndex);
770  }
771 
772  } else {
773 // the element has dependent nodes
774  if (fFlowGraph->fGlobMatrix) {
775  ek->ApplyConstraints();
776  ef->ApplyConstraints();
778  fFlowGraph->fStruct->FilterEquations(ek->fSourceIndex,ek->fDestinationIndex);
779  } else {
780  ef->ApplyConstraints();
782  fFlowGraph->fStruct->FilterEquations(ef->fSourceIndex,ef->fDestinationIndex);
783  }
784  }
785 
786 #ifdef LOG4CXX
787  if (logger->isDebugEnabled())
788  {
789  std::stringstream sout;
790  sout << __PRETTY_FUNCTION__ << " Element " << element;
791  LOGPZ_DEBUG(logger, sout.str())
792  }
793 #endif
794  (fFlowGraph->fNodes)[element]->try_put(tbb::flow::continue_msg());
795 
796  }
797 } // operator()
798 
799 #endif
800 
801 int TPZStructMatrixTBB::ClassId() const{
802  return Hash("TPZStructMatrixTBB") ^ TPZStructMatrixBase::ClassId() << 1;
803 }
804 
805 void TPZStructMatrixTBB::Read(TPZStream& buf, void* context) {
806  TPZStructMatrixBase::Read(buf, context);
807 #ifdef USING_TBB
808  fFlowGraph = dynamic_cast<TPZFlowGraph *>(TPZPersistenceManager::GetInstance(&buf));
809 #endif
810 }
811 
812 void TPZStructMatrixTBB::Write(TPZStream& buf, int withclassid) const {
813  TPZStructMatrixBase::Write(buf, withclassid);
814  DebugStop();
815 #ifdef USING_TBB
816 // TPZPersistenceManager::WritePointer(fFlowGraph, &buf);
817 #endif
818 }
819 
820 //void TPZStructMatrixTBB::TPZFlowNode::operator()(tbb::flow::continue_msg) const
821 //{
822 // TPZCompMesh *cmesh = myGraph->fStruct->Mesh();
823 // TPZAutoPointer<TPZGuiInterface> guiInterface = myGraph->fGuiInterface;
824 // TPZElementMatrix ek(cmesh, TPZElementMatrix::EK);
825 // TPZElementMatrix ef(cmesh, TPZElementMatrix::EF);
826 //#ifdef LOG4CXX
827 // if (logger->isDebugEnabled()) {
828 // std::stringstream sout;
829 // sout << "Computing element " << iel;
830 // LOGPZ_DEBUG(logger, sout.str())
831 // }
832 //#endif
833 //#ifdef LOG4CXX
834 // std::stringstream sout;
835 // sout << "Element " << iel << " elapsed time ";
836 // TPZTimer timeforel(sout.str());
837 // timeforel.start();
838 //#endif
839 //
840 // int element = myGraph->felSequenceColor[iel];
841 //
842 // if (element >= 0){
843 //
844 // TPZCompEl *el = cmesh->ElementVec()[element];
845 //
846 // if(!el) return;
847 //
848 // if (myGraph->fGlobMatrix)
849 // el->CalcStiff(ek,ef);
850 // else
851 // el->CalcResidual(ef);
852 //
853 // if(!el->HasDependency()) {
854 //
855 // if (myGraph->fGlobMatrix) {
856 // ek.ComputeDestinationIndices();
857 // myGraph->fStruct->FilterEquations(ek.fSourceIndex,ek.fDestinationIndex);
858 // } else {
859 // ef.ComputeDestinationIndices();
860 // myGraph->fStruct->FilterEquations(ef.fSourceIndex,ef.fDestinationIndex);
861 // }
862 //
863 // } else {
864 // // the element has dependent nodes
865 // if (myGraph->fGlobMatrix) {
866 // ek.ApplyConstraints();
867 // ef.ApplyConstraints();
868 // ek.ComputeDestinationIndices();
869 // myGraph->fStruct->FilterEquations(ek.fSourceIndex,ek.fDestinationIndex);
870 // } else {
871 // ef.ApplyConstraints();
872 // ef.ComputeDestinationIndices();
873 // myGraph->fStruct->FilterEquations(ef.fSourceIndex,ef.fDestinationIndex);
874 // }
875 //
876 // }
877 //
878 //
879 // if(myGraph->fGlobMatrix) {
880 // // assemble the matrix
881 // if(!ek.HasDependency()) {
882 // myGraph->fGlobMatrix->AddKel(ek.fMat,ek.fSourceIndex,ek.fDestinationIndex);
883 // myGraph->fGlobRhs->AddFel(ef.fMat,ek.fSourceIndex,ek.fDestinationIndex);
884 // } else {
885 // myGraph->fGlobMatrix->AddKel(ek.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
886 // myGraph->fGlobRhs->AddFel(ef.fConstrMat,ek.fSourceIndex,ek.fDestinationIndex);
887 // }
888 // } else {
889 // if(!ef.HasDependency()) {
890 // myGraph->fGlobRhs->AddFel(ef.fMat,ef.fSourceIndex,ef.fDestinationIndex);
891 // } else {
892 // myGraph->fGlobRhs->AddFel(ef.fConstrMat,ef.fSourceIndex,ef.fDestinationIndex);
893 // }
894 // }
895 //
896 // } // outsided if
897 //
898 //#ifdef LOG4CXX
899 // timeforel.stop();
900 // if (logger->isDebugEnabled())
901 // {
902 // std::stringstream sout;
903 // sout << timeforel.processName() << timeforel;
904 // LOGPZ_DEBUG(logger, sout.str())
905 // }
906 //#endif
907 //
908 //}
909 
911 #endif
static RunStatsTable ass_stiff("-ass_stiff", "Assemble Stiffness")
Contains a class to record running statistics on CSV tables.
The timer class. Utility.
Definition: TPZTimer.h:46
static int MinPassIndex(TPZStack< int64_t > &connectlist, TPZVec< int > &elContribute, TPZVec< int > &passIndex)
static void RemoveEl(int el, TPZCompMesh *cmesh, TPZVec< int > &elContribute, int elSequence)
Contains TPZAnalysis class which implements the sequence of actions to perform a finite element analy...
void Scatter(const TPZFMatrix< TVar > &vsmall, TPZFMatrix< TVar > &vexpand) const
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.
TPZEquationFilter fEquationFilter
Object which will determine which equations will be assembled.
Timing class. Absolutely copied from GNU time. Take a look at
virtual void BuildConnectList(std::set< int64_t > &indepconnectlist, std::set< int64_t > &depconnectlist)
Builds the list of all connectivities related to the element including the connects pointed to by dep...
Definition: pzcompel.cpp:435
Contains declaration of TPZGeoNode class which defines a geometrical node.
int64_t NEquations()
This computes the number of equations associated with non-restrained nodes.
Definition: pzcmesh.cpp:721
void AddFel(TPZFMatrix< TVar > &rhs, TPZVec< int64_t > &destination)
Performs a right hand side assemblage.
Definition: pzfmatrix.cpp:209
static bool CanAssemble(TPZStack< int64_t > &connectlist, TPZVec< int > &elContribute)
Contains declaration of TPZCompEl class which defines the interface of a computational element...
Templated vector implementation.
Contains the TPZStructMatrixTBB class which responsible for a interface among Matrix and Finite Eleme...
virtual void CalcStiff(TPZElementMatrix &ek, TPZElementMatrix &ef)
Computes the element stifness matrix and right hand side.
Definition: pzcompel.h:794
Declarates the TPZBlock<REAL>class which implements block matrices.
#define MAX(a, b)
Gets maxime value between a and b.
Definition: pzreal.h:81
int ClassId() const override
Define the class id associated with the class.
static TPZSavable * GetInstance(const int64_t &objId)
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object.
Definition: pzmanvector.h:426
TPZManVector< int64_t > fDestinationIndex
Definition: pzelmat.h:53
void ComputeDestinationIndices()
Definition: pzelmat.cpp:126
TPZSkylMatrix< REAL > matrix
Definition: numatst.cpp:255
static RunStatsTable stat_ass_graph_tbb("-ass_graph_tbb", "Run statistics table for the graph creation, coloring and tbb::flow::graph TPZStructMatrixTBBFlow.")
Contains declaration of TPZElementMatrix struct which associates an element matrix with the coeficien...
static void AssembleColor(int el, TPZStack< int64_t > &connectlist, TPZVec< int > &elContribute)
int64_t size() const
Returns the number of elements of the vector.
Definition: pzvec.h:196
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object reallocating the necessary storage, copying the existing objects to the new...
Definition: pzvec.h:373
Contains declaration of TPZMesh class which defines a geometrical mesh and contains a corresponding l...
void Push(const T object)
Pushes a copy of the object on the stack.
Definition: pzstack.h:80
int64_t NActiveEquations() const
Retorna o numero de equacoes ativas do sistema.
void start()
Turns the timer on.
Definition: TPZTimer.cpp:28
TVar Norm(const TPZFMatrix< TVar > &A)
Returns the norm of the matrix A.
Contains TPZMatrixclass which implements full matrix (using column major representation).
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
TPZCompMesh * Mesh() const override
Access method for the mesh pointer.
virtual void SetNumThreads(int n)
#define LOGPZ_DEBUG(A, B)
Define log for debug info.
Definition: pzlog.h:87
Free store vector implementation.
void parallel_for(int n, body_t &obj)
Definition: pzparallel.h:24
int64_t Rows() const
Returns number of rows.
Definition: pzmatrix.h:803
virtual void Assemble(TPZMatrix< STATE > &mat, TPZFMatrix< STATE > &rhs, TPZAutoPointer< TPZGuiInterface > guiInterface) override
Assemble the global system of equations into the matrix which has already been created.
void Write(TPZStream &buf, int withclassid) const override
Writes this object to the TPZStream buffer. Include the classid if withclassid = true.
int64_t NEqExpand() const
Retorna o numero de equacoes do sistema original.
Implements an interface to check the consistency of two implementations. Utility. ...
TPZManVector< int64_t > fSourceIndex
Definition: pzelmat.h:53
Contains declaration of TPZCompMesh class which is a repository for computational elements...
int Redim(const int64_t newRows, const int64_t newCols) override
Redimension a matrix and ZERO your elements.
Definition: pzfmatrix.h:616
int32_t Hash(std::string str)
Definition: TPZHash.cpp:10
This class associates an element matrix with the coeficients of its contribution in the global stiffn...
Definition: pzelmat.h:30
static RunStatsTable ass_rhs("-ass_rhs", "Assemble Stiffness")
void ApplyConstraints()
Apply the constraints applied to the nodes by transforming the tangent matrix and right hand side...
Definition: pzelmat.cpp:186
Contains declaration of TPZSubCompMesh class which implements a group of computational elements as a ...
virtual void CalcResidual(TPZElementMatrix &ef)
Computes the element right hand side.
Definition: pzcompel.cpp:610
Implements computational mesh. Computational Mesh.
Definition: pzcmesh.h:47
TPZAdmChunkVector< TPZCompEl * > & ElementVec()
Returns a reference to the element pointers vector.
Definition: pzcmesh.h:183
Contains declaration of TPZInterpolatedElement class which implements computational element of the in...
virtual TPZMatrix< STATE > * Create() override
int64_t Cols() const
Returns number of cols.
Definition: pzmatrix.h:809
virtual void Print(std::ostream &out) const
Definition: pzmatrix.h:253
Defines the interface for saving and reading data. Persistency.
Definition: TPZStream.h:50
int64_t NElements() const
Returns the number of elements of the vector.
Definition: pzvec.h:190
static int WhoBlockedMe(TPZStack< int64_t > &connectlist, TPZVec< int > &elContribute, TPZVec< int > &elSeqinv)
Defines the interface of a computational element. Computational Element.
Definition: pzcompel.h:59
virtual int HasDependency()
Returns 1 if the element has at least one dependent node. Returns 0 otherwise.
Definition: pzcompel.cpp:565
void Read(TPZStream &buf, void *context) override
read objects from the stream
Implements an interface to register a class id and a restore function. Persistence.
Definition: TPZSavable.h:150
Contains TPZSFMatrix class which implements a symmetric full matrix.