NeoPZ
TPZBuildSBFem.cpp
Go to the documentation of this file.
1 //
2 // TPZBuildSBFem.cpp
3 // PZ
4 //
5 // Created by Philippe Devloo on 06/01/17.
6 //
7 //
8 
9 #include "TPZBuildSBFem.h"
10 #include "TPZSBFemVolume.h"
11 #include "TPZSBFemElementGroup.h"
12 #include "pzcompel.h"
13 #include "tpzgeoblend.h"
14 #include "TPZGeoLinear.h"
15 
16 #include "tpzgeoelrefpattern.h"
17 
18 #ifdef LOG4CXX
19 static LoggerPtr logger(Logger::getLogger("pz.mesh.tpzbuildsbfem"));
20 #endif
21 
24 {
25  TPZVec<int64_t> elindices(fGMesh->NElements());
26  int64_t nel = elindices.size();
27  for (int64_t el=0; el<nel; el++) {
28  elindices[el] = el;
29  }
30  StandardConfiguration(elindices);
31 }
32 
35 {
36  CreateElementCenterNodes(elementindices);
38 }
39 
42 {
43  std::map<int64_t,int64_t> nodetogroup;
44  // int maxpartition = 4;
45  int64_t count = 0;
46  for (int64_t el=0; el<scalingcenters.size(); el++) {
47  if (scalingcenters[el] == -1) {
48  continue;
49  }
50  if (nodetogroup.find(scalingcenters[el]) == nodetogroup.end()) {
51  nodetogroup[scalingcenters[el]] = count++;
52  // if (count >= maxpartition) {
53  // break;
54  // }
55  }
56  }
58  {
59  DebugStop();
60  }
61  int dim = fGMesh->Dimension();
62  fPartitionCenterNode.resize(nodetogroup.size());
63  for (std::map<int64_t,int64_t>::iterator it = nodetogroup.begin(); it != nodetogroup.end(); it++) {
64  fPartitionCenterNode[it->second] = it->first;
65  }
66  int64_t nel = fGMesh->NElements();
67  for (int64_t el=0; el < nel; el++) {
68  TPZGeoEl *gel = fGMesh->Element(el);
69  if (gel->Dimension() != dim && scalingcenters[el] != -1) {
70  DebugStop();
71  }
72  else if(gel->Dimension() != dim)
73  {
74  continue;
75  }
76  if (scalingcenters[el] == -1) {
77  continue;
78  }
79  if (nodetogroup.find(scalingcenters[el]) == nodetogroup.end()) {
80  DebugStop();
81  }
82  int64_t partition = nodetogroup[scalingcenters[el]];
83  // if(partition < maxpartition)
84  {
85  fElementPartition[el] = partition;
86  }
87  }
89 
90 }
91 
92 
94 void TPZBuildSBFem::AddPartition(TPZVec<int64_t> &elindices, int64_t centernodeindex)
95 {
96  int64_t npart = fPartitionCenterNode.size();
98  if (fGMesh->NodeVec().NElements() <= centernodeindex) {
99  DebugStop();
100  }
101  fPartitionCenterNode[npart] = centernodeindex;
102  int64_t nel = elindices.size();
103  for (int64_t el=0; el<nel; el++) {
104  int64_t elindex = elindices[el];
105  if (fElementPartition[elindex] != -1) {
106  DebugStop();
107  }
108  fElementPartition[elindex] = npart;
109  }
110 }
111 
114 {
115  // create the lower dimensional mesh
116  std::set<int> matids;
117  int dim = cmesh.Dimension();
118  TPZGeoMesh *gmesh = cmesh.Reference();
119  int64_t nel = gmesh->NElements();
120  for (int64_t el=0; el<nel; el++) {
121  TPZGeoEl *gel = gmesh->Element(el);
122  if (!gel) {
123  continue;
124  }
125  if (gel->Dimension() < dim) {
126  matids.insert(gel->MaterialId());
127  }
128  }
129  // create the boundary elements
131  cmesh.AutoBuild(matids);
132  // at this point all elements of lower dimension have been created
134  CreateElementGroups(cmesh);
135 
136 }
137 
140 {
141  // create the lower dimensional mesh
142  std::set<int> matids;
143  int dim = cmesh.Dimension();
144  TPZGeoMesh *gmesh = cmesh.Reference();
145  int64_t nel = gmesh->NElements();
146  for (int64_t el=0; el<nel; el++) {
147  TPZGeoEl *gel = gmesh->Element(el);
148  if (!gel) {
149  continue;
150  }
151  if (gel->Dimension() < dim) {
152  matids.insert(gel->MaterialId());
153  }
154  }
155  // create the boundary elements
157  cmesh.AutoBuild(matids);
159  CreateElementGroups(cmesh);
160 
161 }
162 
164 void TPZBuildSBFem::BuildComputationMesh(TPZCompMesh &cmesh, const std::set<int> &volmatids, const std::set<int> &boundmatids)
165 {
166  // create the boundary elements
168  cmesh.AutoBuild(boundmatids);
169  CreateVolumetricElements(cmesh,volmatids);
170  CreateElementGroups(cmesh);
171 
172 }
173 
174 
175 
178 {
179  // create a lower dimension element on each boundary
180  int dim = fGMesh->Dimension();
181 
182  int64_t nel = fGMesh->NElements();
183 
184  for (int64_t el=0; el<nel; el++) {
185  TPZGeoEl *gel = fGMesh->Element(el);
186  if (!gel) {
187  continue;
188  }
189  if (gel->Dimension() != dim) {
190  continue;
191  }
192  // the element doesnt belong to any partition, do not create a skeleton element
193  if (fElementPartition[el] == -1) {
194  continue;
195  }
196  int64_t elpartition = fElementPartition[el];
197  int nsides = gel->NSides();
198  for (int is=0; is<nsides; is++) {
199  if (gel->SideDimension(is) != dim-1) {
200  continue;
201  }
202  TPZGeoElSide thisside(gel,is);
203  // we do not create skeleton elements on the boundary of the domain without boundary condition
204  TPZGeoElSide neighbour = thisside.Neighbour();
205  if (neighbour == thisside) {
206  continue;
207  }
208  int64_t neighbourelpartition = -1;
209  // look for a neighbour with mesh dimension
210  while(neighbour != thisside && neighbour.Element()->Dimension() != dim)
211  {
212  neighbour = neighbour.Neighbour();
213  }
214  // we found one!
215  if(neighbour != thisside)
216  {
217  neighbourelpartition = fElementPartition[neighbour.Element()->Index()];
218  }
219 
220  // look for a neighbour of dimension dim-1
221  neighbour = thisside.Neighbour();
222  while (neighbour != thisside && neighbour.Element()->Dimension() != dim-1) {
223  neighbour = neighbour.Neighbour();
224  }
225  // if we didnt find a lower dimension element and the neighbouring element of same dimension belong to a different partition
226  if (thisside == neighbour && elpartition != neighbourelpartition) {
227  gel->CreateBCGeoEl(is,fSkeletonMatId);
228  }
229  }
230  }
231 
232 }
233 
236 {
238  {
239  DebugStop();
240  }
241  int dim = fGMesh->Dimension();
242  int64_t nel = elindices.size();
244  int64_t count = 0;
245  for (int64_t el=0; el<elindices.size(); el++) {
246  TPZGeoEl *gel = fGMesh->Element(elindices[el]);
247  if (gel->Dimension() != dim) {
248  continue;
249  }
250  int nsides = gel->NSides();
251  TPZManVector<REAL,3> xicenter(dim),xcenter(3);
252  gel->CenterPoint(nsides-1,xicenter);
253  gel->X(xicenter,xcenter);
254  int64_t middlenode = fGMesh->NodeVec().AllocateNewElement();
255  fGMesh->NodeVec()[middlenode].Initialize(xcenter,fGMesh);
256  fPartitionCenterNode[count] = middlenode;
257  fElementPartition[elindices[el]] = count;
258  count++;
259  }
261 }
262 
264 // the lower dimensional elements already exist (e.g. all connects have been created
266 {
267  TPZGeoMesh *gmesh = cmesh.Reference();
268  gmesh->ResetReference();
269  int dim = gmesh->Dimension();
270  cmesh.LoadReferences();
271  // all computational elements have been loaded
272  std::set<int> matids, matidstarget;
273  for (std::map<int,int>::iterator it = fMatIdTranslation.begin(); it!= fMatIdTranslation.end(); it++) {
274  int64_t mat = it->second;
275  if (cmesh.FindMaterial(mat)) {
276  matids.insert(it->first);
277  matidstarget.insert(it->second);
278  }
279  }
280  int64_t nel = gmesh->NElements();
281  for (int64_t el=0; el<nel; el++) {
282  TPZGeoEl *gel = gmesh->Element(el);
283  if (!gel || gel->HasSubElement() || gel->Reference()) {
284  continue;
285  }
286  // we create SBFemVolume elements by partitioning the volume elements
287  if (gel->Dimension() != dim) {
288  continue;
289  }
290  if (fElementPartition[el] == -1) {
291  continue;
292  }
293  if (matids.find(gel->MaterialId()) == matids.end()) {
294  continue;
295  }
296  int nsides = gel->NSides();
297  for (int is = 0; is<nsides; is++) {
298  if (gel->SideDimension(is) != dim-1) {
299  continue;
300  }
301  TPZStack<TPZCompElSide> celstack;
302  TPZGeoElSide gelside(gel,is);
303  int onlyinterpolated = true;
304  int removeduplicates = true;
305  // we identify all computational elements connected to this element side
306  gelside.EqualorHigherCompElementList2(celstack, onlyinterpolated, removeduplicates);
307  // we create a volume element based on all smaller elements linked to this side
308  int ncelstack = celstack.NElements();
309  for (int icel=0; icel<ncelstack; icel++) {
310  TPZGeoElSide subgelside = celstack[icel].Reference();
311  // we are only interested in faces
312  if (subgelside.Dimension() != dim-1) {
313  continue;
314  }
315  int nnodes = subgelside.NSideNodes();
316  TPZManVector<int64_t,8> Nodes(nnodes*2,-1);
317  int matid = fMatIdTranslation[gel->MaterialId()];
318  int64_t index;
319  for (int in=0; in<nnodes; in++) {
320  Nodes[in] = subgelside.SideNodeIndex(in);
321  }
322  int elpartition = fElementPartition[el];
323  for (int in=nnodes; in < 2*nnodes; in++) {
324  Nodes[in] = fPartitionCenterNode[elpartition];
325  }
326  if (subgelside.IsLinearMapping())
327  {
328  switch(nnodes)
329  {
330  case 2:
331  gmesh->CreateGeoElement(EQuadrilateral, Nodes, matid, index);
332  break;
333  case 4:
334  gmesh->CreateGeoElement(ECube, Nodes, matid, index);
335  break;
336  case 3:
337  gmesh->CreateGeoElement(EPrisma, Nodes, matid, index);
338  break;
339  default:
340  std::cout << "Don't understand the number of nodes per side : nnodes " << nnodes << std::endl;
341  DebugStop();
342  }
343 
344  }
345  else
346  {
347  int64_t elementid = gmesh->NElements()+1;
348  switch(nnodes)
349  {
350  case 2:
351  new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoQuad> > (Nodes, matid, *gmesh,index);
352  break;
353  case 4:
354  new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoCube> > (Nodes, matid, *gmesh,index);
355  break;
356  case 3:
357  gmesh->CreateGeoElement(EPrisma, Nodes, matid, index);
358  break;
359  default:
360  std::cout << "Don't understand the number of nodes per side : nnodes " << nnodes << std::endl;
361  DebugStop();
362  }
363  }
364  if (index >= fElementPartition.size()) {
365  fElementPartition.resize(index+1);
366  }
367  fElementPartition[index] = elpartition;
368  }
369  }
370  }
371  gmesh->BuildConnectivity();
372  cmesh.ApproxSpace().SetAllCreateFunctionsSBFem(dim);
373  cmesh.AutoBuild(matidstarget);
374 }
375 
378 {
379  TPZGeoMesh *gmesh = cmesh.Reference();
380  gmesh->ResetReference();
381  int dim = gmesh->Dimension();
382  cmesh.LoadReferences();
383  std::set<int> matids, matidstarget;
384  for (std::map<int,int>::iterator it = fMatIdTranslation.begin(); it!= fMatIdTranslation.end(); it++) {
385  int64_t mat = it->second;
386  if (cmesh.FindMaterial(mat)) {
387  matids.insert(it->first);
388  matidstarget.insert(it->second);
389  }
390  }
391  int64_t nel = gmesh->NElements();
392  for (int64_t el=0; el<nel; el++) {
393  TPZGeoEl *gel = gmesh->Element(el);
394  if (!gel || gel->HasSubElement() ) {
395  continue;
396  }
397  if (!gel->Reference()) {
398  continue;
399  }
400  if (fElementPartition[el] == -1) {
401  continue;
402  }
403  if (gel->Dimension() > dim - 1) {
404  DebugStop();
405  }
406  if (matids.find(gel->MaterialId()) == matids.end()) {
407  continue;
408  }
409  int nsides = gel->NSides();
410  int is = nsides - 1;
411  TPZStack<TPZCompElSide> celstack;
412  TPZGeoElSide gelside(gel,is);
413  int nnodes = gelside.NSideNodes();
414  TPZManVector<int64_t,8> Nodes(nnodes*2,-1);
415  int matid = fMatIdTranslation[gel->MaterialId()];
416  int64_t index;
417  for (int in=0; in<nnodes; in++) {
418  Nodes[in] = gelside.SideNodeIndex(in);
419  }
420  int elpartition = fElementPartition[el];
421  for (int in=nnodes; in < 2*nnodes; in++) {
422  Nodes[in] = fPartitionCenterNode[elpartition];
423  }
424  if (gelside.IsLinearMapping())
425  {
426  switch(nnodes)
427  {
428  case 1:
429  gmesh->CreateGeoElement(EOned, Nodes, matid, index);
430  break;
431  case 2:
432  gmesh->CreateGeoElement(EQuadrilateral, Nodes, matid, index);
433  break;
434  case 4:
435  gmesh->CreateGeoElement(ECube, Nodes, matid, index);
436  break;
437  case 3:
438  gmesh->CreateGeoElement(EPrisma, Nodes, matid, index);
439  break;
440  default:
441  std::cout << "Don't understand the number of nodes per side : nnodes " << nnodes << std::endl;
442  DebugStop();
443  }
444 
445  }
446  else
447  {
448  int64_t elementid = gmesh->NElements()+1;
449  switch(nnodes)
450  {
451  case 2:
452  new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoQuad> > (Nodes, matid, *gmesh,index);
453  break;
454  case 4:
455  new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoCube> > (Nodes, matid, *gmesh,index);
456  break;
457  case 3:
458  gmesh->CreateGeoElement(EPrisma, Nodes, matid, index);
459  break;
460  default:
461  std::cout << "Don't understand the number of nodes per side : nnodes " << nnodes << std::endl;
462  DebugStop();
463  }
464  }
465  if (index >= fElementPartition.size()) {
466  fElementPartition.resize(index+1);
467  }
468  fElementPartition[index] = elpartition;
469 
470 
471  }
472  gmesh->BuildConnectivity();
473  cmesh.ApproxSpace().SetAllCreateFunctionsSBFem(dim);
474  cmesh.AutoBuild(matidstarget);
475 }
476 
478 void TPZBuildSBFem::CreateVolumetricElements(TPZCompMesh &cmesh, const std::set<int> &matids)
479 {
480  TPZGeoMesh *gmesh = cmesh.Reference();
481  gmesh->ResetReference();
482  int dim = gmesh->Dimension();
483  cmesh.LoadReferences();
484  std::set<int> matidsorig,matidstarget;
485  for (std::map<int,int>::iterator it = fMatIdTranslation.begin(); it!= fMatIdTranslation.end(); it++) {
486  int64_t mat = it->second;
487  if(matids.find(mat) != matids.end())
488  {
489  matidsorig.insert(it->first);
490  }
491  }
492  int64_t nel = gmesh->NElements();
493  for (int64_t el=0; el<nel; el++) {
494  TPZGeoEl *gel = gmesh->Element(el);
495  if (!gel || gel->HasSubElement() || gel->Reference()) {
496  continue;
497  }
498  if (fElementPartition[el] == -1) {
499  continue;
500  }
501  if (matidsorig.find(gel->MaterialId()) == matidsorig.end()) {
502  continue;
503  }
504  int nsides = gel->NSides();
505  int geldim = gel->Dimension();
506  for (int is = 0; is<nsides; is++) {
507  if (gel->SideDimension(is) != geldim-1) {
508  continue;
509  }
510  // we only create an SBFem volume element if it is connected to a skeleton element?
511  TPZStack<TPZCompElSide> celstack;
512  TPZGeoElSide gelside(gel,is);
513  int onlyinterpolated = true;
514  int removeduplicates = true;
515  gelside.EqualorHigherCompElementList2(celstack, onlyinterpolated, removeduplicates);
516  int ncelstack = celstack.NElements();
517  for (int icel=0; icel<ncelstack; icel++) {
518  TPZGeoElSide subgelside = celstack[icel].Reference();
519  // we are only interested in faces
520  if (subgelside.Dimension() != geldim-1) {
521  continue;
522  }
523  int nnodes = subgelside.NSideNodes();
524 // if (nnodes != 2) {
525 // std::cout << "Please extend the code to higher dimensions\n";
526 // }
527  TPZManVector<int64_t,4> Nodes(nnodes*2,-1);
528  int matid = fMatIdTranslation[gel->MaterialId()];
529  int64_t index;
530  for (int in=0; in<nnodes; in++) {
531  Nodes[in] = subgelside.SideNodeIndex(in);
532  }
533  int elpartition = fElementPartition[el];
534  for (int in=nnodes; in < nnodes*2; in++) {
535  Nodes[in] = fPartitionCenterNode[elpartition];
536  }
537  MElementType targettype = ENoType;
538  switch (nnodes) {
539  case 2:
540  targettype = EQuadrilateral;
541  break;
542  case 1:
543  targettype = EOned;
544  break;
545  case 3:
546  targettype = EPrisma;
547  break;
548  case 4:
549  targettype = ECube;
550  break;
551 
552  default:
553  DebugStop();
554  break;
555  }
556  if (subgelside.IsLinearMapping())
557  {
558  gmesh->CreateGeoElement(targettype, Nodes, matid, index);
559 #ifdef LOG4CXX
560  if(logger->isDebugEnabled())
561  {
562  std::stringstream sout;
563  sout << "Created element of type " << targettype << " with nodes " << Nodes << " index " << index;
564  LOGPZ_DEBUG(logger, sout.str())
565  }
566 #endif
567  }
568  else
569  {
570  int64_t elementid = gmesh->NElements()+1;
571  TPZGeoEl *gblend = 0;
572  switch (targettype) {
573  case EOned:
574  gblend = gmesh->CreateGeoElement(targettype, Nodes, matid, index);
575  break;
576  case EQuadrilateral:
577  gblend = new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoQuad> > (Nodes, matid, *gmesh,index);
578  break;
579  case EPrisma:
580  gblend = new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoPrism> > (Nodes, matid, *gmesh,index);
581  break;
582  case ECube:
583  gblend = new TPZGeoElRefPattern< pzgeom::TPZGeoBlend<pzgeom::TPZGeoCube> > (Nodes, matid, *gmesh,index);
584  break;
585  default:
586  DebugStop();
587  break;
588  }
589 #ifdef LOG4CXX
590  if(logger->isDebugEnabled())
591  {
592  std::stringstream sout;
593  sout << "Created element of type " << targettype << " with nodes " << Nodes << " index " << index;
594  LOGPZ_DEBUG(logger, sout.str())
595  }
596 #endif
597 
598 
599  }
600  if (index >= fElementPartition.size()) {
601  fElementPartition.resize(index+1);
602  }
603  fElementPartition[index] = elpartition;
604  }
605  }
606  }
607  gmesh->BuildConnectivity();
608  cmesh.ApproxSpace().SetAllCreateFunctionsSBFem(dim);
609  cmesh.AutoBuild(matids);
610 
611 }
612 
613 
616 {
617  int64_t numgroups = fPartitionCenterNode.size();
618  int64_t groupelementindices(numgroups);
619 
620  TPZVec<int64_t> elementgroupindices(numgroups);
621 
622  for (int64_t el=0; el<numgroups; el++) {
623  int64_t index;
624  new TPZSBFemElementGroup(cmesh,index);
625  elementgroupindices[el] = index;
626  }
627 
628 
629  int64_t nel = cmesh.NElements();
630  int dim = cmesh.Dimension();
631  for (int64_t el=0; el<nel; el++) {
632  TPZCompEl *cel = cmesh.Element(el);
633  if (!cel) {
634  continue;
635  }
636  TPZSBFemVolume *sbfem = dynamic_cast<TPZSBFemVolume *>(cel);
637  if (sbfem) {
638  TPZGeoEl *gel = sbfem->Reference();
639  int64_t gelindex = gel->Index();
640  int side = -1;
641  if (gel->Type() == EQuadrilateral) {
642  side = 4;
643  }
644  else if(gel->Type() == EOned)
645  {
646  side = 0;
647  }
648  else if(gel->Type() == ECube)
649  {
650  side = 20;
651  }
652  else if(gel->Type() == EPrisma)
653  {
654  side = 15;
655  }
656  else
657  {
658  DebugStop();
659  }
660  TPZGeoElSide gelside(gel,side);
661  int geldim = gel->Dimension();
662  int nsidenodes = gel->NSideNodes(side);
663  TPZManVector<int64_t,8> cornernodes(nsidenodes);
664  for (int node = 0; node<nsidenodes; node++) {
665  cornernodes[node] = gel->SideNodeIndex(side, node);
666  }
667 
668  TPZGeoElSide neighbour = gelside.Neighbour();
669  while (neighbour != gelside) {
670  if(neighbour.Element()->Dimension() == geldim-1 && neighbour.Element()->Reference())
671  {
672  int nsidenodesneighbour = neighbour.Element()->NCornerNodes();
673  if (nsidenodesneighbour == nsidenodes)
674  {
675  TPZManVector<int64_t,8> neighnodes(nsidenodesneighbour);
676  for (int i=0; i<nsidenodesneighbour; i++) {
677  neighnodes[i] = neighbour.Element()->NodeIndex(i);
678  }
679  int numequal = 0;
680  for (int i=0; i<nsidenodesneighbour; i++) {
681  if (neighnodes[i] == cornernodes[i]) {
682  numequal++;
683  }
684  }
685  if (numequal == nsidenodesneighbour) {
686  break;
687  }
688  }
689  }
690  neighbour = neighbour.Neighbour();
691  }
692  if (neighbour == gelside) {
693  // we are not handling open sides (yet)
694  DebugStop();
695  }
696  int64_t skelindex = neighbour.Element()->Reference()->Index();
697  sbfem->SetSkeleton(skelindex);
698 
699  int64_t gelgroup = fElementPartition[gelindex];
700  if (gelgroup == -1) {
701  DebugStop();
702  }
703  int64_t celgroupindex = elementgroupindices[gelgroup];
704  TPZCompEl *celgr = cmesh.Element(celgroupindex);
705  TPZSBFemElementGroup *sbfemgr = dynamic_cast<TPZSBFemElementGroup *>(celgr);
706  if (!sbfemgr) {
707  DebugStop();
708  }
709  sbfemgr->AddElement(sbfem);
710  // sbfem->SetElementGroupIndex(celgroupindex);
711  }
712  }
713 
714  for (int64_t el=0; el<numgroups; el++) {
715  int64_t index;
716 
717  index = elementgroupindices[el];
718  TPZCompEl *cel = cmesh.Element(index);
719  TPZSBFemElementGroup *sbfemgroup = dynamic_cast<TPZSBFemElementGroup *>(cel);
720  if (!sbfemgroup) {
721  DebugStop();
722  }
723  TPZStack<TPZCompEl *, 5> subgr = sbfemgroup->GetElGroup();
724  int64_t nsub = subgr.NElements();
725  for (int64_t is=0; is<nsub; is++) {
726  TPZCompEl *cel = subgr[is];
727  TPZSBFemVolume *femvol = dynamic_cast<TPZSBFemVolume *>(cel);
728  if (!femvol) {
729  DebugStop();
730  }
731  femvol->SetElementGroupIndex(index);
732  }
733  }
734 
735 }
736 
739 {
740  int dim = fGMesh->Dimension();
741  for (int ir=0; ir<nref; ir++)
742  {
744  int64_t nel = elvec.NElements();
745  for (int64_t el=0; el<nel; el++) {
746  TPZGeoEl *gel = elvec[el];
747  if (!gel || gel->HasSubElement()) {
748  continue;
749  }
750  if (gel->Dimension() != dim-1) {
751  continue;
752  }
754  gel->Divide(subel);
755  int64_t partition = fElementPartition[el];
756  int nsub = subel.size();
757  for (int isub=0; isub<nsub; isub++) {
758  while (fElementPartition.size() <= subel[isub]->Index()) {
760  }
761  fElementPartition[subel[isub]->Index()] = partition;
762  }
763  }
764  }
765 }
766 
768 void TPZBuildSBFem::DivideSkeleton(int nref, const std::set<int> &volmatids)
769 {
770  std::set<int> exclude;
771  for (auto it = fMatIdTranslation.begin(); it != fMatIdTranslation.end(); it++) {
772  if(volmatids.find(it->second) != volmatids.end())
773  {
774  exclude.insert(it->first);
775  }
776  }
777  int dim = fGMesh->Dimension();
778  for (int ir=0; ir<nref; ir++)
779  {
781  int64_t nel = elvec.NElements();
782  for (int64_t el=0; el<nel; el++) {
783  TPZGeoEl *gel = elvec[el];
784  if (!gel || gel->HasSubElement()) {
785  continue;
786  }
787  int matid = gel->MaterialId();
788  // skip the elements with matid volmatids
789  if (exclude.find(matid) != exclude.end()) {
790  continue;
791  }
793  if (fMatIdTranslation.find(matid) == fMatIdTranslation.end()) {
794  continue;
795  }
796  if (gel->Dimension() != dim-1) {
797  continue;
798  }
800  gel->Divide(subel);
801  int64_t partition = fElementPartition[el];
802  int nsub = subel.size();
803  for (int isub=0; isub<nsub; isub++) {
804  while (fElementPartition.size() <= subel[isub]->Index()) {
806  }
807  fElementPartition[subel[isub]->Index()] = partition;
808  }
809 
810  }
811  }
812 }
virtual int64_t SideNodeIndex(int side, int nodenum) const =0
Returns the index of the nodenum node of side.
void CreateElementCenterNodes(TPZVec< int64_t > &elindices)
create a geometric node at the center of each partition
int64_t NElements() const
Number of computational elements allocated.
Definition: pzcmesh.h:169
void EqualorHigherCompElementList2(TPZStack< TPZCompElSide > &celside, int onlyinterpolated, int removeduplicates)
Will return all elements of equal or higher level than than the current element.
TPZGeoMesh * Reference() const
Returns a pointer to the geometrical mesh associated.
Definition: pzcmesh.h:209
int NSideNodes() const
virtual TPZGeoEl * CreateGeoElement(MElementType type, TPZVec< int64_t > &nodeindexes, int matid, int64_t &index) override
Creates a geometric element according to the type of the father element.
int AllocateNewElement()
Makes more room for new elements.
Definition: pzadmchunk.h:184
TPZStack< TPZCompEl *, 5 > GetElGroup()
int MaterialId() const
Returns the material index of the element.
Definition: pzgeoel.h:250
virtual TPZGeoEl * CreateGeoElement(MElementType type, TPZVec< int64_t > &cornerindexes, int matid, int64_t &index, int reftype=1)
Generic method for creating a geometric element. Putting this method centrally facilitates the modifi...
Definition: pzgmesh.cpp:1296
virtual void resize(const int64_t newsize)
Definition: pzvec.h:213
clarg::argInt nsub("-nsub", "number of substructs", 4)
Contains declaration of TPZCompEl class which defines the interface of a computational element...
virtual int NCornerNodes() const =0
Returns the number of corner nodes of the element.
void DivideSkeleton(int nref)
Divide the skeleton elements.
int64_t NElements() const
Number of elements of the mesh.
Definition: pzgmesh.h:129
Utility class which represents an element with its side. The Geometric approximation classes Geometry...
Definition: pzgeoelside.h:83
std::map< int, int > fMatIdTranslation
The volumetric elements with Mat Id will spawn SBFemVolume elements with MatId.
Definition: TPZBuildSBFem.h:25
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
TPZGeoElSide Neighbour() const
Definition: pzgeoel.h:754
void CreateVolumetricElements(TPZCompMesh &cmesh)
create geometric volumetric elements
virtual int NSides() const =0
Returns the number of connectivities of the element.
virtual void Divide(TPZVec< TPZGeoEl *> &pv)
Divides the element and puts the resulting elements in the vector.
Definition: pzgeoel.h:742
virtual int64_t NodeIndex(int i) const =0
Returns the index of the ith node the index is the location of the node in the nodevector of the mesh...
virtual int SideDimension(int side) const =0
Return the dimension of side.
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object.
Definition: pzmanvector.h:426
void LoadReferences()
Map this grid in the geometric grid.
Definition: pzcmesh.cpp:482
void BuildComputationalMeshFromSkeleton(TPZCompMesh &cmesh)
build the computational elements of the skeleton and build the volume elements directly from the skel...
virtual void CenterPoint(int side, TPZVec< REAL > &masscent) const =0
It returns the coordinates from the center of the side of the element in the element coordinate space...
bool IsLinearMapping() const
int64_t size() const
Returns the number of elements of the vector.
Definition: pzvec.h:196
TPZCompEl * Element(int64_t iel)
Definition: pzcmesh.h:185
TPZCreateApproximationSpace & ApproxSpace()
Definition: pzcmesh.h:498
void AddSkeletonElements()
create the geometric skeleton elements
Implements a generic geometric element which is refined according to a generic refinement pattern...
Definition: pzgmesh.h:35
Defines the behaviour of all geometric elements. GeometryTPZGeoEl is the common denominator for all g...
Definition: pzgeoel.h:43
void CreateVolumetricElementsFromSkeleton(TPZCompMesh &cmesh)
create geometric volumetric elements
Contains the TPZGeoBlend class which implements a blending map from curved boundaries to the interior...
TPZGeoEl * Element(int64_t iel)
Definition: pzgmesh.h:139
int64_t Index() const
Returns the index of the element within the element vector of the mesh.
Definition: pzgeoel.h:730
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
#define LOGPZ_DEBUG(A, B)
Define log for debug info.
Definition: pzlog.h:87
int Dimension() const
Returns the dimension of the simulation.
Definition: pzcmesh.h:148
virtual void AddElement(TPZCompEl *cel)
add an element to the element group
virtual MElementType Type() const =0
Returns the element type acording to pzeltype.h.
TPZMaterial * FindMaterial(int id)
Find the material with identity id.
Definition: pzcmesh.cpp:297
TPZAdmChunkVector< TPZGeoNode > & NodeVec()
Definition: pzgmesh.h:140
TPZCompEl * Reference() const
Return a pointer to the element referenced by the geometric element.
Definition: pzgeoel.h:750
virtual void AutoBuild(const std::set< int > *MaterialIDs)
Creates the computational elements, and the degree of freedom nodes.
Definition: pzcmesh.cpp:308
int fSkeletonMatId
Material Id associated with the skeleton elements.
Definition: TPZBuildSBFem.h:28
virtual TPZGeoEl * CreateBCGeoEl(int side, int bc)=0
Method which creates a geometric element on the side of an existing element.
Contains declaration of TPZGeoElRefPattern class which implements a generic geometric element which i...
void SetAllCreateFunctionsContinuous()
Create continuous approximation spaces.
void BuildComputationMesh(TPZCompMesh &cmesh)
add the sbfem elements to the computational mesh, the material should exist in cmesh ...
int64_t Index() const
Returns element index of the mesh fELementVec list.
Definition: pzcompel.h:821
static int nsidenodes[27]
Vector with the number of vertices contained in the closure of the side.
Definition: tpzcube.cpp:103
virtual int NSideNodes(int side) const =0
Returns the number of nodes for a particular side.
virtual int HasSubElement() const =0
Return 1 if the element has subelements.
TPZGeoEl * Element() const
Definition: pzgeoelside.h:162
void BuildConnectivity()
Build the connectivity of the grid.
Definition: pzgmesh.cpp:967
TPZManVector< int64_t > fElementPartition
partition to which each element belongs
Definition: TPZBuildSBFem.h:31
virtual int Dimension() const =0
Returns the dimension of the element.
void SetSkeleton(int64_t skeleton)
Data structure initialization.
int Dimension()
Get Dimension.
Definition: pzgmesh.h:291
void StandardConfiguration()
standard configuration means each element is a partition and a center node is created ...
TPZGeoEl * Reference() const
Return a pointer to the corresponding geometric element if such exists, return 0 otherwise.
Definition: pzcompel.cpp:1137
virtual void X(TPZVec< REAL > &qsi, TPZVec< REAL > &result) const =0
Return the coordinate in real space of the point coordinate in the master element space...
This class implements a geometric mesh for the pz environment. Geometry.
Definition: pzgmesh.h:48
MElementType
Define the element types.
Definition: pzeltype.h:52
int Dimension() const
the dimension associated with the element/side
Implements computational mesh. Computational Mesh.
Definition: pzcmesh.h:47
Definition: pzeltype.h:61
void AddPartition(TPZVec< int64_t > &elids, int64_t centernodeindex)
add a partition manually
void CreateElementGroups(TPZCompMesh &cmesh)
put the sbfem volumetric elements in element groups
int64_t NElements() const
Returns the number of elements of the vector.
Definition: pzvec.h:190
void SetElementGroupIndex(int64_t index)
Initialize the data structure indicating the group index.
Definition: pzeltype.h:55
void ResetReference()
Resets all load references in elements and nodes.
Definition: pzgmesh.cpp:197
Defines the interface of a computational element. Computational Element.
Definition: pzcompel.h:59
void Configure(TPZVec< int64_t > &scalingcenters)
build element groups according to the id of the scaling centers
int64_t SideNodeIndex(int nodenum) const
Returns the index of the nodenum node of side.
TPZAutoPointer< TPZGeoMesh > fGMesh
geometric mesh
Definition: TPZBuildSBFem.h:22
TPZManVector< int64_t > fPartitionCenterNode
center node id for each partition
Definition: TPZBuildSBFem.h:34
TPZAdmChunkVector< TPZGeoEl * > & ElementVec()
Methods for handling pzlists.
Definition: pzgmesh.h:138