NeoPZ
TPZMHMeshControl.cpp
Go to the documentation of this file.
1 //
2 // TPZMHMeshControl.cpp
3 // PZ
4 //
5 // Created by Philippe Devloo on 5/3/14.
6 //
7 //
8 
9 #include "TPZMHMeshControl.h"
10 #include "TPZRefPattern.h"
11 #include "pzl2projection.h"
12 #include "TPZNullMaterial.h"
13 #include "TPZLagrangeMultiplier.h"
14 #include "TPZCompElLagrange.h"
15 #include "pzbndcond.h"
16 #include "pzmat1dlin.h"
17 #include "TPZInterfaceEl.h"
18 #include "pzmultiphysicscompel.h"
22 #include "pzsubcmesh.h"
23 #include "TPZRefPatternTools.h"
24 #include "pzlog.h"
25 
26 #include <iostream>
27 #include <sstream>
28 #include <iterator>
29 #include <numeric>
30 
31 #ifdef LOG4CXX
32 static LoggerPtr logger(Logger::getLogger("pz.mhmeshcontrol"));
33 #endif
34 
35 // toto
36 
37 
38 TPZMHMeshControl::TPZMHMeshControl(TPZAutoPointer<TPZGeoMesh> gmesh, TPZVec<int64_t> &geotomhm) : fGMesh(gmesh), fProblemType(EScalar), fNState(1), fGeoToMHMDomain(geotomhm), fMHMtoSubCMesh(), fGlobalSystemSize(-1), fGlobalSystemWithLocalCondensationSize(-1), fNumeq(-1)
39 {
40  if(!gmesh) DebugStop();
41 #ifdef PZDEBUG
42  if (geotomhm.size() != fGMesh->NElements()) {
43  DebugStop();
44  }
45 #endif
46  fpOrderInternal = 2;
47  fpOrderSkeleton = 1;
48 
49  int64_t nc = geotomhm.size();
50  for (int64_t c=0; c<nc; c++) {
51  fMHMtoSubCMesh[geotomhm[c] ] = -1;
52  }
53 #ifdef LOG4CXX
54  if (logger->isDebugEnabled()) {
55  std::stringstream sout;
56  sout << "Coarse element indexes ";
57  for (std::map<int64_t,int64_t>::iterator it=fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
58  sout << *it << " ";
59  }
60  LOGPZ_DEBUG(logger, sout.str())
61  }
62 #endif
66 }
67 
69 void TPZMHMeshControl::DefinePartition(TPZVec<int64_t> &partitionindex, std::map<int64_t,std::pair<int64_t,int64_t> > &skeleton)
70 {
71 #ifdef PZDEBUG
72  if (partitionindex.size() != partitionindex.size()) {
73  DebugStop();
74  }
75 #endif
76  fGeoToMHMDomain = partitionindex;
77  fInterfaces = skeleton;
78  fMHMtoSubCMesh.clear();
79  int64_t nc = partitionindex.size();
80  for (int64_t c=0; c<nc; c++) {
81  fMHMtoSubCMesh[partitionindex[c] ] = -1;
82  }
83 #ifdef LOG4CXX
84  if (logger->isDebugEnabled()) {
85  std::stringstream sout;
86  sout << "Coarse element indexes ";
87  for (std::map<int64_t,int64_t>::iterator it=fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
88  sout << *it << " ";
89  }
90  LOGPZ_DEBUG(logger, sout.str())
91  }
92 #endif
93 }
94 
96 // This method calculates the skeleton indexes
98 
99  TPZGeoMesh *gmesh = this->fGMesh.operator->();
100 
101  // Creates skeleton elements
102  std::map<int64_t, std::pair<int64_t, int64_t>> skeleton;
103 
104  int dim = gmesh->Dimension();
105 
106  const int64_t nel = gmesh->NElements();
107  for (int64_t iel = 0; iel < nel; iel++) {
108 
109  TPZGeoEl *gel = gmesh->Element(iel);
110 
111  if (gel->HasSubElement()) continue;
112  if (gel->Dimension() == dim-1)
113  {
114  TPZGeoElSide gelside(gel,gel->NSides()-1);
115  TPZGeoElSide neighbour = gelside.Neighbour();
116  if(neighbour.Element()->Dimension() != dim) DebugStop();
117  int partition = partitionindex[neighbour.Element()->Index()];
118  int64_t neighindex = neighbour.Element()->Index();
119  auto val = std::pair<int64_t,int64_t>(partition,gel->Index());
120  skeleton[gel->Index()] = val;
121  continue;
122  }
123 
124  // Iterates through the sides of the element
125  int nsides = gel->NSides();
126 
127  for (int iside = 0; iside < nsides; iside++) {
128 
129  TPZGeoElSide gelside(gel, iside);
130 
131  // Filters boundary sides
132  if (gelside.Dimension() != dim - 1) continue;
133 
134  TPZGeoElSide neighbour = gelside.Neighbour();
135 
136  // Filters neighbour sides that belong to volume elements
137  if (neighbour.Element()->Dimension() != dim) continue;
138 
139  int64_t thisId = gel->Index();
140  int64_t neighId = neighbour.Element()->Index();
141 
142  // This lambda checks if a skeleton has already been created over gelside
143  auto hasSkeletonNeighbour = [&]() -> bool {
144  neighbour = gelside.Neighbour();
145  while (neighbour != gelside) {
146  int neighbourMatId = neighbour.Element()->MaterialId();
147  if (neighbourMatId == fSkeletonMatId) {
148  return true;
149  }
150  neighbour = neighbour.Neighbour();
151  }
152  return false;
153  };
154 
155  int64_t thisGroup = partitionindex[thisId];
156  int64_t neighGroup = partitionindex[neighId];
157 
158  if (thisGroup != neighGroup) {
159  if (!hasSkeletonNeighbour()) {
160  TPZGeoElBC bc(gelside, fSkeletonMatId);
161  std::pair<int64_t, int64_t> adjacentGroupIndexes(thisGroup, neighGroup);
162  int64_t bc_index = bc.CreatedElement()->Index();
163  if(bc_index == neighGroup)
164  {
165  // you are unwillingly creating a boundary skeleton
166  DebugStop();
167  }
168  skeleton.insert({bc.CreatedElement()->Index(), adjacentGroupIndexes});
169  }
170  }
171  }
172  }
173 
174  DefinePartition(partitionindex, skeleton);
175 }
176 
180  fNumeq(-1) {
181 
182 
183 #ifdef LOG4CXX
184  if (logger->isDebugEnabled()) {
185  std::stringstream sout;
186  sout << "Coarse element indexes ";
187  for (std::map<int64_t,int64_t>::iterator it=fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
188  sout << *it << " ";
189  }
190  LOGPZ_DEBUG(logger, sout.str())
191  }
192 #endif
193  fCMesh = new TPZCompMesh(fGMesh);
196 }
197 
199 
200  this->operator=(copy);
201 }
202 
204 
205  fGMesh = new TPZGeoMesh(*cp.fGMesh.operator->());
207  fNState = cp.fNState;
214  fCMesh = cp.fCMesh;
223  fHybridize = cp.fHybridize;
227  fNumeq = cp.fNumeq;
228  return *this;
229 }
230 
232 {
234  int64_t nel = fCMesh->NElements();
235  for (int64_t el = 0; el<nel ; el++) {
236  TPZCompEl *cel = fCMesh->Element(el);
237  if(!cel) continue;
238  TPZSubCompMesh *subcmesh = dynamic_cast<TPZSubCompMesh *>(cel);
239  if (!subcmesh) {
240  continue;
241  }
242  delete cel;
243  }
244  for (int64_t el = 0; el<nel ; el++) {
245  TPZCompEl *cel = fCMesh->Element(el);
246  if(!cel) continue;
247  TPZGeoEl *gel = cel->Reference();
248  if (!gel) {
249  continue;
250  }
251  cel->LoadElementReference();
252  delete cel;
253  }
254 }
255 
256 
259 {
260  int64_t ncoarse = coarseindices.size();
261  int64_t nel = fGMesh->NElements();
262  fGeoToMHMDomain.Resize(nel);
263  for (int64_t el=0; el<nel; el++) {
264  fGeoToMHMDomain[el] = -1;
265  }
266  for (int64_t el=0; el<ncoarse; el++) {
267  fGeoToMHMDomain[coarseindices[el]] = coarseindices[el];
268  TPZGeoEl *gel = fGMesh->Element(coarseindices[el]);
269  if (gel) {
270  fMHMtoSubCMesh[gel->Index()] = -1;
271  }
272  }
273  // set the MHM domain index for all elements
274  // look for a father element that has a MHM domain index
275  // adopt the domain index of the ancester
276  for (int64_t el=0; el<nel; el++) {
277  TPZGeoEl *gel = fGMesh->Element(el);
278  if (!gel || fGeoToMHMDomain[el] != -1) {
279  continue;
280  }
281  int domain = -1;
282  TPZGeoEl *father = gel->Father();
283  while (father) {
284  int64_t index = father->Index();
285  if (fGeoToMHMDomain[index] != -1) {
286  fGeoToMHMDomain[el] = fGeoToMHMDomain[index];
287  break;
288  }
289  father = father->Father();
290  }
291  }
293 #ifdef LOG4CXX
294  if (logger->isDebugEnabled()) {
295  std::stringstream sout;
296  sout << "Subdomain indices " << fGeoToMHMDomain << std::endl;
297  sout << "Recognized domains ";
298  for (auto it = fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
299  sout << it->first << ' ';
300  }
301  LOGPZ_DEBUG(logger, sout.str())
302  }
303 #endif
304 }
305 
306 
309 {
310  if (fInterfaces.size()) {
311  DebugStop();
312  }
313 
314  if(fSkeletonMatId < 0) DebugStop();
315 
316  TPZCompMesh *cmesh = CriaMalhaTemporaria();
317 
318  int64_t nel = fGMesh->NElements();
319  int dimension = fGMesh->Dimension();
320  int ninterf;
321 
322  for(int64_t iel = 0; iel<nel; iel++)
323  {
324  TPZGeoEl * gel = fGMesh->ElementVec()[iel];
325  if(!gel) continue;
326 
327  ninterf = gel->NumInterfaces();
328  if(ninterf > 1) DebugStop();
329  if (ninterf==1)
330  {
331  TPZCompEl *cel = gel->Reference();
332  TPZInterfaceElement *intface = dynamic_cast<TPZInterfaceElement *>(cel);
333  if (!intface) {
334  DebugStop();
335  }
336  int interfacematid = fSkeletonMatId;
337  TPZCompEl *left = intface->LeftElement();
338  TPZCompEl *right = intface->RightElement();
339  int64_t leftind = left->Reference()->Index();
340  int64_t rightind = right->Reference()->Index();
341  if (left->Reference()->Dimension() == dimension-1) {
342  // the boundary element is the skeleton element
343  fInterfaces[leftind]=std::make_pair(rightind, leftind);
344  continue;
345  }
346  if (right->Reference()->Dimension() == dimension-1) {
347  // the boundary element is the skeleton element
348  fInterfaces[rightind]=std::make_pair(leftind, rightind);
349  continue;
350  }
351  fInterfaces[iel] = std::make_pair(leftind, rightind);
352  gel->SetMaterialId(interfacematid);
353  // in order to prevent the element from being deleted
354  gel->DecrementNumInterfaces();
355  }
356  }
357 
359  delete cmesh;
360 
361 // BuildWrapMesh(fGMesh->Dimension());
362 // BuildWrapMesh(fGMesh->Dimension()-1);
363 
365 #ifdef LOG4CXX
366  if (logger->isDebugEnabled()) {
367  std::stringstream sout;
368  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it = fInterfaces.begin();
369  while (it != fInterfaces.end()) {
370  int leftdim = fGMesh->ElementVec()[it->second.first]->Dimension();
371  int rightdim = fGMesh->ElementVec()[it->second.second]->Dimension();
372  sout << "Interface index " << it->first << " Left Element " << it->second.first << "/" << leftdim
373  << " Right Element " << it->second.second << "/" << rightdim << std::endl;
374  it++;
375  }
376  sout << "Geometric mesh after creating the skeleton\n";
377  fGMesh->Print(sout);
378  LOGPZ_DEBUG(logger, sout.str())
379  }
380 #endif
381 }
382 
385 {
386  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it;
387  for (int divide=0; divide<ndivide; divide++)
388  {
389  std::map<int64_t, std::pair<int64_t,int64_t> > mapdivided;
390  for (it=fInterfaces.begin(); it!=fInterfaces.end(); it++) {
391  int64_t elindex = it->first;
392 // if (elindex == it->second.second) {
393 // mapdivided[elindex] = it->second;
394 // continue;
395 // }
396  TPZGeoEl *gel = fGMesh->Element(elindex);
398  gel->SetRefPattern(refpat);
400  gel->Divide(subels);
401  int64_t nsub = subels.size();
402  for (int is=0; is<nsub; is++) {
403  if (subels[is]->Index() >= fGeoToMHMDomain.size()) {
404  fGeoToMHMDomain.Resize(subels[is]->Index()+1000, -1);
405  }
406  fGeoToMHMDomain[subels[is]->Index()] = fGeoToMHMDomain[elindex];
407  mapdivided[subels[is]->Index()] = it->second;
408  // for boundary elements, the second element is the interface element
409  if(elindex == it->second.second)
410  {
411  mapdivided[subels[is]->Index()].second = subels[is]->Index();
412  }
413  }
414  }
415  fInterfaces = mapdivided;
416  }
420 
421  std::cout<<"WrapMatId created \n";
422  std::cout << "fSkeletonWrapMatId "<<fSkeletonWrapMatId<<std::endl;
423  std::cout << "fBoundaryWrapMatId "<<fBoundaryWrapMatId<<std::endl;
424  //std::cout << "fHdivWrapMatId "<<fHDivWrapMatid<<std::endl;
425 }
426 
429 {
430  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it;
431  bool hasdivided = true;
432  while (hasdivided)
433  {
434  hasdivided = false;
435  // mapdivided will contain the new fInterface structure
436  std::map<int64_t, std::pair<int64_t,int64_t> > mapdivided;
437  for (it=fInterfaces.begin(); it!=fInterfaces.end(); it++) {
438  int64_t elindex = it->first;
439  // if the following condition is not satisfied then the interface is not a boundary
440 // if (elindex != it->second.second) {
441 // mapdivided[it->first] = it->second;
442 // continue;
443 // }
444  TPZGeoEl *gel = fGMesh->Element(elindex);
445  // if the geometric element associated with the interface was not divided
446  // then the interface will not be divided either
447  if(!gel->HasSubElement())
448  {
449  mapdivided[it->first] = it->second;
450  continue;
451  }
452  hasdivided = true;
454  gel->Divide(subels);
455  int64_t nsub = subels.size();
456  for (int is=0; is<nsub; is++) {
457  if (subels[is]->Index() >= fGeoToMHMDomain.size()) {
458  fGeoToMHMDomain.Resize(subels[is]->Index()+1000, -1);
459  }
460  fGeoToMHMDomain[subels[is]->Index()] = fGeoToMHMDomain[elindex];
461  mapdivided[subels[is]->Index()] = it->second;
462  // for boundary elements, the second element is the interface element
463  // update the interface data structure
464  if(elindex == it->second.second)
465  {
466  mapdivided[subels[is]->Index()].second = subels[is]->Index();
467  }
468  }
469  }
470  fInterfaces = mapdivided;
471  }
475 }
476 
478 {
481  int dim = fGMesh->Dimension();
482  std::set<int> matids, bcids;
483  TPZGeoMesh &gmesh = fGMesh;
484  int64_t nel = gmesh.NElements();
485  for (int64_t el=0; el<nel; el++) {
486  TPZGeoEl *gel = gmesh.ElementVec()[el];
487  if (!gel) {
488  continue;
489  }
490  if (gel->Dimension() != dim || fMHMtoSubCMesh.find(el) == fMHMtoSubCMesh.end()) {
491  continue;
492  }
493  int materialid = gel->MaterialId();
494  matids.insert(materialid);
495  int ns = gel->NSides();
496  for (int is=0; is<ns; is++) {
497  if (gel->SideDimension(is) != dim-1) {
498  continue;
499  }
500  TPZGeoElSide gelside(gel,is);
501  TPZGeoElSide neighbour = gelside.Neighbour();
502  while (neighbour != gelside) {
503  if (neighbour.Element()->Dimension() == dim-1) {
504  bcids.insert(neighbour.Element()->MaterialId());
505  }
506  neighbour = neighbour.Neighbour();
507  }
508  }
509  }
510 
511  TPZCompMesh *cmesh = new TPZCompMesh(fGMesh);
512  cmesh->SetDimModel(dim);
513  TPZManVector<STATE,1> sol(1,0.);
514  int nstate = 1;
515  std::set<int>::iterator it = matids.begin();
516  TPZMaterial *meshmat = 0;
517  while (it != matids.end()) {
518  TPZL2Projection *material = new TPZL2Projection(*it,dim,nstate,sol);
519  cmesh->InsertMaterialObject(material);
520  if (!meshmat) {
521  meshmat = material;
522  }
523  it++;
524 
525  }
526 
527  if (!meshmat) {
528  DebugStop();
529  }
530 
531  it = bcids.begin();
532  while (it != bcids.end()) {
534  TPZFMatrix<STATE> val1(2,2,0.), val2(2,1,0.);
535 
536  TPZMaterial * BCondD1 = meshmat->CreateBC(meshmat, *it,0, val1, val2);
537  cmesh->InsertMaterialObject(BCondD1);
538 
539  it++;
540  }
541 
543  TPZCreateApproximationSpace &create = cmesh->ApproxSpace();
544 
545  for (int64_t el=0; el<nel; el++) {
546  TPZGeoEl *gel = gmesh.ElementVec()[el];
547  if (!gel) {
548  continue;
549  }
550  if (gel->Dimension() != dim || fMHMtoSubCMesh.find(el) == fMHMtoSubCMesh.end()) {
551  continue;
552  }
553  int64_t index;
554  create.CreateCompEl(gel, *cmesh, index);
555  int ns = gel->NSides();
556  for (int is=0; is<ns; is++) {
557  if (gel->SideDimension(is) != dim-1) {
558  continue;
559  }
560  TPZGeoElSide gelside(gel,is);
561  TPZGeoElSide neighbour = gelside.Neighbour();
562  while (neighbour != gelside) {
563  if (neighbour.Element()->Dimension() == dim-1) {
564  int matid = neighbour.Element()->MaterialId();
565  if (bcids.find(matid) != bcids.end()) {
566  create.CreateCompEl(neighbour.Element(), *cmesh, index);
567  }
568  }
569  neighbour = neighbour.Neighbour();
570  }
571  }
572  }
573 
575  cmesh->ExpandSolution();
576  return cmesh;
577 }
578 
580 void TPZMHMeshControl::BuildComputationalMesh(bool usersubstructure)
581 {
582  int nstate = fNState;
583  int dim = fGMesh->Dimension();
584  fCMesh->SetDimModel(dim);
587  // AddBoundaryElements();
588  CreateSkeleton();
590 // AddBoundaryInterfaceElements();
595  this->TransferToMultiphysics();
596  }
597 
598 
599 #ifdef LOG4CXX
600  if (logger->isDebugEnabled()) {
601  std::stringstream sout;
602  sout << "*********** BEFORE SUBSTRUCTURING *************\n";
603  fCMesh->Print(sout);
604  int64_t nel = fCMesh->NElements();
605  for (int64_t el=0; el<nel; el++) {
606  TPZCompEl *cel = fCMesh->Element(el);
607  if(!cel) continue;
608  sout << "el index " << el << " subdomain " << WhichSubdomain(cel) << std::endl;
609  }
610  LOGPZ_DEBUG(logger, sout.str())
611  }
612 #endif
613 
616  if(usersubstructure==true){
617  this->SubStructure();
618  }
619  fNumeq = fCMesh->NEquations();
620 }
621 
624 {
626 
629 
630  //Criar elementos computacionais malha MHM
631 
632  TPZGeoEl *gel = NULL;
633  TPZGeoEl *gsubel = NULL;
634  TPZCompMesh *cmesh = fCMesh.operator->();
635  fConnectToSubDomainIdentifier[cmesh].Expand(10000);
636 
637  int64_t nel = fGMesh->NElements();
638  for (auto itMHM = fMHMtoSubCMesh.begin(); itMHM != fMHMtoSubCMesh.end(); itMHM++)
639  {
641  bool LagrangeCreated = false;
642  for (int64_t el=0; el< nel; el++)
643  {
644  TPZGeoEl *gel = fGMesh->Element(el);
645  if (!gel || gel->HasSubElement() || fGeoToMHMDomain[el] != itMHM->first) {
646  continue;
647  }
648  int64_t index;
649  // create the flux element
650  fCMesh->CreateCompEl(gel, index);
651  TPZCompEl *cel = fCMesh->Element(index);
653  SetSubdomain(cel, itMHM->first);
654  // we need to create a lagrange multiplier element in order to delay decomposition of an equation
655  if (!LagrangeCreated)
656  {
657  LagrangeCreated = true;
658  TPZCompEl *cel = fCMesh->ElementVec()[index];
659  int64_t cindex = cel->ConnectIndex(0);
660  int nshape(1), nvar(1), order(1);
661  int lagrangelevel = 0;
662  if (this->fLagrangeAveragePressure) {
663  lagrangelevel = 1;
664  }
665  else
666  {
667  lagrangelevel = 3;
668  }
669  fCMesh->ConnectVec()[cindex].SetLagrangeMultiplier(lagrangelevel);
670  if (fProblemType == EElasticity2D) {
671  cindex = cel->ConnectIndex(2);
672  fCMesh->ConnectVec()[cindex].SetLagrangeMultiplier(lagrangelevel);
673  }
674  if (fProblemType == EElasticity3D) {
675  cindex = cel->ConnectIndex(6);
676  fCMesh->ConnectVec()[cindex].SetLagrangeMultiplier(lagrangelevel);
677  }
678  }
679  }
680  }
682 }
683 
686 {
687  // comment this line or not to switch the type of skeleton elements
688  int meshdim = fCMesh->Dimension();
689  fCMesh->SetDimModel(meshdim);
690 // fCMesh->ApproxSpace().SetAllCreateFunctionsDiscontinuous();
692  int order = fpOrderSkeleton;
693  if (order < 0) {
694  order = 0;
695  }
696  fCMesh->SetDefaultOrder(order);
697  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it = fInterfaces.begin();
698  while (it != fInterfaces.end()) {
699  int64_t elindex = it->first;
700  // skip the boundary elements
701 // if (elindex == it->second.second) {
702 // it++;
703 // continue;
704 // }
705  TPZGeoEl *gel = fGMesh->ElementVec()[elindex];
706  int64_t index;
707  // create a discontinuous element to model the flux
708  fCMesh->CreateCompEl(gel, index);
709  TPZCompEl *cel = fCMesh->ElementVec()[index];
710  int Side = gel->NSides()-1;
711  TPZInterpolationSpace *intel = dynamic_cast<TPZInterpolationSpace *>(cel);
712  int nc = cel->NConnects();
713  for (int ic=0; ic<nc; ic++) {
714  int lagrangelevel = 0;
715  if (this->fLagrangeAveragePressure) {
716  lagrangelevel = 2;
717  }
718  else
719  {
720  lagrangelevel = 2;
721  }
722  cel->Connect(ic).SetLagrangeMultiplier(lagrangelevel);
723  }
724  SetSubdomain(cel, -1);
725 
726  if (elindex == it->second.second) {
727  // set the side orientation of the boundary elements
728  intel->SetSideOrient(Side, 1);
729  SetSubdomain(cel, it->second.first);
730  }
731  else
732  {
733  if (it->second.first < it->second.second) {
734  // set the flux orientation depending on the relative value of the element ids
735  intel->SetSideOrient(Side, 1);
736  }
737  else
738  {
739  intel->SetSideOrient(Side, -1);
740  }
741  SetSubdomain(cel, -1);
742  }
743  gel->ResetReference();
744  it++;
745  }
746  fCMesh->SetDimModel(meshdim);
747 }
748 
751 {
753  int dim = fGMesh->Dimension();
754  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it;
756  for (it=fInterfaces.begin(); it != fInterfaces.end(); it++) {
757  // index of the skeleton element
758  int64_t elindex = it->first;
759  // left and right indexes in the coarse mesh
760  int64_t leftelindex = it->second.first;
761  int64_t rightelindex = it->second.second;
762  // skip boundary elements
763  int matid = 0, matidleft = 0, matidright = 0;
764 
765  // second condition indicates a boundary element
766  if (leftelindex < rightelindex || rightelindex == elindex)
767  {
768  matidleft = fLagrangeMatIdLeft;
769  matidright = fLagrangeMatIdRight;
770  }
771  else
772  {
773  matidleft = fLagrangeMatIdRight;
774  matidright = fLagrangeMatIdLeft;
775  }
776  int numlado = 2;
777  if (rightelindex == elindex) {
778  numlado = 1;
779  }
780 
781  TPZGeoEl *gel = fGMesh->ElementVec()[elindex];
782  TPZGeoElSide gelside(gel,gel->NSides()-1);
783  TPZCompElSide celskeleton = gelside.Reference();
784  // the skeleton element must exist
785  if(!celskeleton.Element()) DebugStop();
786  TPZGeoElSide neighbour = gelside.Neighbour();
787  while(neighbour != gelside)
788  {
789  int neighmatid = neighbour.Element()->MaterialId();
790  if(neighmatid == fSkeletonWrapMatId || neighmatid == fBoundaryWrapMatId)
791  {
792  break;
793  }
794  neighbour = neighbour.Neighbour();
795  }
796  if (neighbour == gelside) {
797  DebugStop();
798  }
799  TPZStack<TPZGeoElSide> gelstack;
800  gelstack.Push(neighbour);
801  while (gelstack.size())
802  {
803  TPZGeoElSide smallGeoElSide = gelstack.Pop();
804  // the smaller elements returned by GetSubElements include element/sides of lower dimension
805  if (smallGeoElSide.Dimension() != gel->Dimension()) {
806  continue;
807  }
808  // look for the neighbours of smallGeoElSide for elements which are of dimension of the fGMesh
809  // and which beint64_t to the subdomains
810  TPZGeoElSide neighbour = smallGeoElSide.Neighbour();
811  while (neighbour != smallGeoElSide)
812  {
813  if (neighbour.Element()->Dimension() != fGMesh->Dimension()) {
814  neighbour = neighbour.Neighbour();
815  continue;
816  }
817  TPZCompElSide csmall = neighbour.Reference();
818  if (csmall)
819  {
820  int matid = -1;
821  if(WhichSubdomain(csmall.Element()) == leftelindex) {
822  matid = matidleft;
823  }
824  else if(WhichSubdomain(csmall.Element()) == rightelindex)
825  {
826  matid = matidright;
827  }
828  if (matid == -1) {
829  DebugStop();
830  }
831  // create an interface between the finer element and the MHM flux
832  int64_t index;
833  TPZGeoEl *gelnew = smallGeoElSide.Element()->CreateBCGeoEl(smallGeoElSide.Side(), matid);
834  new TPZInterfaceElement(fCMesh, gelnew , index, csmall, celskeleton);
835 #ifdef LOG4CXX
836  if (logger->isDebugEnabled()) {
837  std::stringstream sout;
838  sout << "New interface left " << smallGeoElSide.Element()->Index() << " right " << gel->Index() << " matid " << matid;
839  sout << " interface index " << gelnew->Reference()->Index() << " beint64_ts to subdomain " << WhichSubdomain(gelnew->Reference());
840  LOGPZ_DEBUG(logger, sout.str())
841  }
842 #endif
843  }
844  neighbour = neighbour.Neighbour();
845  }
846 
847  smallGeoElSide.GetSubElements2(gelstack);
848  }
849  }
850 }
851 
852 
854 bool TPZMHMeshControl::IsSibling(int64_t son, int64_t father)
855 {
856  TPZGeoEl *gel = fGMesh->ElementVec()[son];
857  while (gel && gel->Index() != father) {
858  gel = gel->Father();
859  }
860  if (gel) {
861  return true;
862  }
863  else
864  {
865  return false;
866  }
867 }
868 
870 void TPZMHMeshControl::PrintDiagnostics(std::ostream &out)
871 {
872  int nelgroups = this->fMHMtoSubCMesh.size();
873  out << __PRETTY_FUNCTION__ << " Number of coarse elements " << nelgroups << std::endl;
874 
875  for (std::map<int64_t,int64_t>::iterator it = fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
876  PrintSubdomain(it->first, out);
877  }
878  PrintBoundaryInfo(out);
879 }
880 
882 void TPZMHMeshControl::PrintSubdomain(int64_t elindex, std::ostream &out)
883 {
884  int64_t nel = fCMesh->NElements();
885  std::set<int64_t> celindices;
886  std::multimap<int64_t,int64_t> interfaces;
887  TPZStack<TPZCompElSide> boundaries;
888  for (int64_t el=0; el<nel; el++) {
889  TPZCompEl *cel = fCMesh->ElementVec()[el];
890  TPZGeoEl *gel = cel->Reference();
891  if (!gel) {
892  continue;
893  }
894  int64_t gelindex = gel->Index();
895  if(fGeoToMHMDomain[gelindex] == elindex)
896  {
897  celindices.insert(el);
898  // verify whether their neighbours are in the subdomain
899  AddElementBoundaries(elindex, el, boundaries);
900  }
901  TPZInterfaceElement *iface = dynamic_cast<TPZInterfaceElement *>(cel);
902  if (iface) {
903  TPZCompEl *left = iface->LeftElement();
904  TPZGeoEl *gleft = left->Reference();
905  if (IsSibling(gleft->Index(), elindex)) {
906  interfaces.insert(std::make_pair(left->Index(),el));
907  }
908  }
909  }
910  out << "Diagnostics for subdomain formed by element seed " << elindex << std::endl;
911  out << "Number of computational elements contained in the group " << celindices.size() << std::endl;
912  out << "Comp Element indices ";
913  for (std::set<int64_t>::iterator i=celindices.begin(); i != celindices.end(); i++) {
914  out << *i << " ";
915  }
916  out << std::endl;
917  out << "Number of boundary interfaces " << interfaces.size() << std::endl;
918  for (std::multimap<int64_t, int64_t>::iterator i = interfaces.begin(); i != interfaces.end(); i++) {
919  int64_t el = i->second;
920  TPZCompEl *cel = fCMesh->ElementVec()[el];
921  TPZInterfaceElement *face = dynamic_cast<TPZInterfaceElement *>(cel);
922  if (!face) {
923  DebugStop();
924  }
925  out << "Comp Element index " << face->LeftElement()->Index() << " side " << face->LeftElementSide().Side() << " skeleton element " << face->RightElement()->Index() << " interface index "
926  << face->Index() << " face material id " << face->Reference()->MaterialId() << std::endl;
927  }
928  out << "Number of elements on the sides of elseed " << boundaries.size() << std::endl;
929  for (int64_t i=0; i<boundaries.size(); i++) {
930  out << "Comp Element index " << boundaries[i].Element()->Index() << " side " << boundaries[i].Side() << std::endl;
931  }
932  out << "Geom Element indices ";
933  for (std::set<int64_t>::iterator i=celindices.begin(); i != celindices.end(); i++) {
934  out << fCMesh->ElementVec()[*i]->Reference()->Index() << " ";
935  }
936  out << std::endl;
937  out << "Number of boundary interfaces " << interfaces.size() << std::endl;
938  for (std::multimap<int64_t, int64_t>::iterator i = interfaces.begin(); i != interfaces.end(); i++) {
939  int64_t el = i->second;
940  TPZCompEl *cel = fCMesh->ElementVec()[el];
941  TPZInterfaceElement *face = dynamic_cast<TPZInterfaceElement *>(cel);
942  if (!face) {
943  DebugStop();
944  }
945  out << "Geom Element index " << face->LeftElement()->Reference()->Index() << " side " << face->LeftElementSide().Side() << " skeleton element " << face->RightElement()->Reference()->Index() << " interface index "
946  << face->Index() << " face material id " << face->Reference()->MaterialId() << std::endl;
947  }
948  out << "Number of elements on the sides of elseed " << boundaries.size() << std::endl;
949  for (int64_t i=0; i<boundaries.size(); i++) {
950  out << "Geom Element index " << boundaries[i].Element()->Reference()->Index() << " side " << boundaries[i].Side() << std::endl;
951  }
952 }
953 
955 void TPZMHMeshControl::AddElementBoundaries(int64_t elseed, int64_t compelindex, TPZStack<TPZCompElSide> &result)
956 {
957  TPZCompEl *cel = fCMesh->ElementVec()[compelindex];
958  TPZGeoEl *gel = cel->Reference();
959  int ns = gel->NSides();
960  int dim = gel->Dimension();
961  for (int is=0; is<ns; is++) {
962  if (gel->SideDimension(is) != dim-1) {
963  continue;
964  }
965  TPZGeoElSide gelside(gel,is);
966  TPZGeoElSide father(gelside);
967  while (father && father.Element()->Index() != elseed) {
968  father = father.Father2();
969  }
970  // if the elseed is not a father aint64_t the boundary, the element is not on the boundary
971  if (!father || father.Dimension() != dim-1) {
972  continue;
973  }
974  TPZCompElSide celside(cel,is);
975 
976  result.Push(celside);
977  }
978 }
979 
982 {
984  int dim = fGMesh->Dimension();
985  std::set<int> notincluded;
986  notincluded.insert(fSkeletonMatId);
987  notincluded.insert(fLagrangeMatIdLeft);
988  notincluded.insert(fLagrangeMatIdRight);
989  int64_t nel = fGMesh->NElements();
990  for (int64_t el=0; el<nel; el++) {
991  TPZGeoEl *gel = fGMesh->ElementVec()[el];
992  if (!gel || gel->Dimension() == dim || gel->HasSubElement()) {
993  continue;
994  }
995  int matid = gel->MaterialId();
996  if (notincluded.find(matid) != notincluded.end()) {
997  continue;
998  }
999  int64_t index;
1000  fCMesh->CreateCompEl(gel, index);
1001  gel->ResetReference();
1002  }
1003 }
1004 
1007 {
1009  int dim = fGMesh->Dimension();
1010  std::set<int> notincluded;
1011  notincluded.insert(fSkeletonMatId);
1012  notincluded.insert(fLagrangeMatIdLeft);
1013  notincluded.insert(fLagrangeMatIdRight);
1014  int64_t nel = fCMesh->NElements();
1015  for (int64_t el=0; el<nel; el++) {
1016  TPZCompEl *cel = fCMesh->ElementVec()[el];
1017  if (!cel) {
1018  continue;
1019  }
1020  TPZGeoEl *gel = cel->Reference();
1021  if (!gel || gel->Dimension() == dim || gel->HasSubElement()) {
1022  continue;
1023  }
1024  int matid = gel->MaterialId();
1025  if (notincluded.find(matid) != notincluded.end()) {
1026  continue;
1027  }
1028  if (gel->Dimension() != dim-1) {
1029  DebugStop();
1030  }
1031  TPZStack<TPZCompElSide> celstack;
1032  TPZGeoElSide gelside(gel,gel->NSides()-1);
1033  TPZCompElSide celside = gelside.Reference();
1034  gelside.EqualorHigherCompElementList2(celstack, 1, 0);
1035  int64_t nst = celstack.size();
1036  for (int64_t i=0; i<nst; i++) {
1037  TPZCompElSide cs = celstack[i];
1038  TPZGeoElSide gs = cs.Reference();
1039  if (gs == gelside) {
1040  continue;
1041  }
1042  int64_t index;
1043  TPZGeoEl *gelnew = gs.Element()->CreateBCGeoEl(gs.Side(), matid);
1044  new TPZInterfaceElement(fCMesh, gelnew , index, cs, celside);
1045 
1046  }
1047  }
1048 }
1049 
1052 {
1053  out << "Output for the structure of the boundary elements\n";
1054  std::set<int> MHMmatids;
1055  MHMmatids.insert(fLagrangeMatIdLeft);
1056  MHMmatids.insert(fLagrangeMatIdRight);
1057  MHMmatids.insert(fSkeletonMatId);
1058  int dim = fGMesh->Dimension();
1059 
1060  out << "\nCOMPUTATIONAL ELEMENT INFORMATION\n";
1061 
1062  int64_t nelem = fCMesh->NElements();
1063  for (int64_t el=0; el<nelem; el++) {
1064  TPZCompEl *cel = fCMesh->ElementVec()[el];
1065  if (!cel) {
1066  continue;
1067  }
1068  TPZInterfaceElement *celf = dynamic_cast<TPZInterfaceElement *>(cel);
1069  if (celf) {
1070  continue;
1071  }
1072  TPZGeoEl *gel = cel->Reference();
1073  if (!gel || gel->Dimension() > dim-1) {
1074  continue;
1075  }
1076  int matid = gel->MaterialId();
1077  if (MHMmatids.find(matid) != MHMmatids.end()) {
1078  continue;
1079  }
1080  TPZGeoElSide gelside(gel,gel->NSides()-1);
1081  TPZStack<TPZCompElSide> celstack;
1082  gelside.EqualLevelCompElementList(celstack, 0, 0);
1083  out << "Comp Boundary Element Index " << el << " matid " << matid << std::endl;
1084  for (int64_t i=0; i< celstack.NElements(); i++) {
1085  TPZCompElSide cels = celstack[i];
1086  TPZGeoElSide gels = cels.Reference();
1087  TPZGeoEl *g = gels.Element();
1088  int matid = g->MaterialId();
1089  if (MHMmatids.find(matid) != MHMmatids.end()) {
1090  continue;
1091  }
1092  TPZCompEl *c = cels.Element();
1093  TPZInterfaceElement *f = dynamic_cast<TPZInterfaceElement *>(c);
1094  if (f) {
1095  TPZCompEl *left = f->LeftElement();
1096  TPZCompEl *right = f->RightElement();
1097  out << "Comp Interface leftel index " << left->Index() << " rightel index " << right->Index() << std::endl;
1098  }
1099  }
1100 
1101  }
1102 
1103  out << "\nGEOMETRIC ELEMENT INFORMATION\n";
1104  for (int64_t el=0; el<nelem; el++) {
1105  TPZCompEl *cel = fCMesh->ElementVec()[el];
1106  if (!cel) {
1107  continue;
1108  }
1109  TPZInterfaceElement *celf = dynamic_cast<TPZInterfaceElement *>(cel);
1110  if (celf) {
1111  continue;
1112  }
1113  TPZGeoEl *gel = cel->Reference();
1114  if (!gel || gel->Dimension() > dim-1) {
1115  continue;
1116  }
1117  int matid = gel->MaterialId();
1118  if (MHMmatids.find(matid) != MHMmatids.end()) {
1119  continue;
1120  }
1121  TPZGeoElSide gelside(gel,gel->NSides()-1);
1122  TPZStack<TPZCompElSide> celstack;
1123  gelside.EqualLevelCompElementList(celstack, 0, 0);
1124  out << "Geom Boundary Element Index " << gel->Index() << " matid " << matid << std::endl;
1125  for (int64_t i=0; i< celstack.NElements(); i++) {
1126  TPZCompElSide cels = celstack[i];
1127  TPZGeoElSide gels = cels.Reference();
1128  TPZGeoEl *g = gels.Element();
1129  int matid = g->MaterialId();
1130  if (MHMmatids.find(matid) != MHMmatids.end()) {
1131  continue;
1132  }
1133  TPZCompEl *c = cels.Element();
1134  TPZInterfaceElement *f = dynamic_cast<TPZInterfaceElement *>(c);
1135  if (f) {
1136  TPZCompEl *left = f->LeftElement();
1137  TPZCompEl *right = f->RightElement();
1138  out << "Geom Interface leftel index " << left->Reference()->Index() << " rightel index " << right->Reference()->Index() << std::endl;
1139  }
1140  }
1141 
1142  }
1143 }
1144 
1147 {
1149  int dim = fGMesh->Dimension();
1152  if (fProblemType == EScalar) {
1154  }
1155  else if(fProblemType == EElasticity2D)
1156  {
1158  }
1160  int64_t connectcounter = fCMesh->NConnects();
1162  std::set<int> matids;
1163  TPZGeoMesh &gmesh = fGMesh;
1164  int64_t nel = gmesh.NElements();
1165  // this code needs to be modified to create lagrange computational elements which share a connect
1166  // between each other
1167  //DebugStop();
1168  for (int64_t el=0; el<nel; el++) {
1169  TPZGeoEl *gel = gmesh.ElementVec()[el];
1170  if (!gel) {
1171  continue;
1172  }
1173  if (gel->Dimension() != dim || fMHMtoSubCMesh.find(el) == fMHMtoSubCMesh.end()) {
1174  continue;
1175  }
1176  int materialid = gel->MaterialId();
1177  matids.insert(materialid);
1178  }
1179 
1180  TPZManVector<STATE,1> sol(1,0.);
1181  int nstate = 1;
1182  std::set<int>::iterator it = matids.begin();
1183  TPZMaterial *meshmat = 0;
1184  while (it != matids.end()) {
1185  TPZNullMaterial *material = new TPZNullMaterial(*it);
1187  if (!meshmat) {
1188  meshmat = material;
1189  }
1190  it++;
1191 
1192  }
1193  if (!meshmat) {
1194  DebugStop();
1195  }
1197  for (int64_t el=0; el<nel; el++) {
1198  TPZGeoEl *gel = gmesh.ElementVec()[el];
1199  if (!gel) {
1200  continue;
1201  }
1202  if (gel->Dimension() != dim || fMHMtoSubCMesh.find(el) == fMHMtoSubCMesh.end()) {
1203  continue;
1204  }
1205  int64_t index;
1206  TPZCompElDisc *disc = new TPZCompElDisc(fCMeshLagrange,gel,index);
1207  disc->SetTotalOrderShape();
1208  disc->SetFalseUseQsiEta();
1209  int64_t cindex = disc->ConnectIndex(0);
1210 #ifdef PZDEBUG
1211  static int count = 0;
1212  if (count == 0)
1213  {
1214  TPZConnect &c = disc->Connect(0);
1215  std::cout << "Number of shape functions of discontinuous element " << c.NShape() << std::endl;
1216  count++;
1217  }
1218 #endif
1219  SetSubdomain(disc, el);
1220 
1221 // fCMeshConstantStates->CreateCompEl(gel, index);
1222  }
1225 
1227  {
1228  int64_t nel = fCMeshConstantPressure->NElements();
1229  for (int64_t el=0; el<nel; el++) {
1231  TPZCompEl *cel2 = fCMeshLagrange->Element(el);
1232  int subdomain = WhichSubdomain(cel2);
1233  SetSubdomain(cel, subdomain);
1234  }
1235  }
1236 #ifdef LOG4CXX
1237  if (logger->isDebugEnabled()) {
1238  std::stringstream sout;
1239  fCMeshLagrange->Print(sout);
1241  LOGPZ_DEBUG(logger, sout.str())
1242  }
1243 #endif
1245 }
1246 
1249 {
1251  this->fCMesh = new TPZCompMesh(fGMesh);
1252  this->fCMesh->SetDimModel(fGMesh->Dimension());
1254 
1255  // copy the material objects
1256  std::map<int,TPZMaterial *>::iterator it = fPressureFineMesh->MaterialVec().begin();
1257  while (it != fPressureFineMesh->MaterialVec().end()) {
1258  it->second->Clone(fCMesh->MaterialVec());
1259  it++;
1260  }
1261 
1262  int64_t nel = fPressureFineMesh->NElements();
1263  for (int64_t el=0; el<nel; el++) {
1264  TPZCompEl *cel = fPressureFineMesh->ElementVec()[el];
1265  if (!cel) {
1266  continue;
1267  }
1268  TPZInterfaceElement *intface = dynamic_cast<TPZInterfaceElement *>(cel);
1269  if (intface) {
1270  continue;
1271  }
1272  TPZCompElLagrange *lagr = dynamic_cast<TPZCompElLagrange *>(cel);
1273  if (lagr) {
1274  int64_t index;
1275  new TPZCompElLagrange(fCMesh,*cel,index);
1276  continue;
1277  }
1278  TPZGeoEl *gel = cel->Reference();
1279  if (!gel) {
1280  DebugStop();
1281  }
1282  int64_t index;
1283  fCMesh->CreateCompEl(gel, index);
1284  TPZCompEl *celnew = fCMesh->ElementVec()[index];
1285  TPZMultiphysicsElement *mult = dynamic_cast<TPZMultiphysicsElement *>(celnew);
1286  if (!mult) {
1287  DebugStop();
1288  }
1289  mult->AddElement(cel, 0);
1290  }
1292  nel = fCMeshLagrange->NElements();
1293  for (int64_t el=0; el<nel; el++) {
1294  TPZCompEl *cel = fCMeshLagrange->ElementVec()[el];
1295  TPZGeoEl *gel = cel->Reference();
1296  int nsides = gel->NSides();
1297  TPZGeoElSide gelside(gel,nsides-1);
1298  TPZStack<TPZCompElSide> celstack;
1299  gelside.ConnectedCompElementList(celstack, 0, 0);
1300  if (gel->Reference()) {
1301  celstack.Push(gelside.Reference());
1302  }
1303  int nstack = celstack.size();
1304  for (int ist=0; ist<nstack; ist++) {
1305  TPZCompEl *celmult = celstack[ist].Element();
1306  TPZMultiphysicsElement *mult = dynamic_cast<TPZMultiphysicsElement *>(celmult);
1307  mult->AddElement(cel, 1);
1308  }
1309  }
1313  for (int64_t el=0; el<nel; el++) {
1315  TPZGeoEl *gel = cel->Reference();
1316  int nsides = gel->NSides();
1317  TPZGeoElSide gelside(gel,nsides-1);
1318  TPZStack<TPZCompElSide> celstack;
1319  gelside.ConnectedCompElementList(celstack, 0, 0);
1320  if (gel->Reference()) {
1321  celstack.Push(gelside.Reference());
1322  }
1323  int nstack = celstack.size();
1324  for (int ist=0; ist<nstack; ist++) {
1325  TPZCompEl *celmult = celstack[ist].Element();
1326  TPZMultiphysicsElement *mult = dynamic_cast<TPZMultiphysicsElement *>(celmult);
1327  mult->AddElement(cel, 2);
1328  }
1329  }
1330 
1331  nel = fCMesh->NElements();
1332  for (int64_t el=0; el<nel; el++) {
1333  TPZCompEl *cel = fCMesh->ElementVec()[el];
1334  if (!cel) {
1335  continue;
1336  }
1337  TPZMultiphysicsElement *multel = dynamic_cast<TPZMultiphysicsElement *>(cel);
1338  if (!multel) {
1339  continue;
1340  }
1341  int nmeshes = multel->NMeshes();
1342  for (int im=nmeshes; im<3; im++) {
1343  multel->AddElement(0, im);
1344  }
1345  }
1346 
1347  //void TPZBuildMultiphysicsMesh::AddConnects(TPZVec<TPZCompMesh *> cmeshVec, TPZCompMesh *MFMesh)
1348  TPZManVector<TPZCompMesh *,3> cmeshvec(3,0);
1349  cmeshvec[0] = fPressureFineMesh.operator->();
1350  cmeshvec[1] = fCMeshLagrange.operator->();
1351  cmeshvec[2] = fCMeshConstantPressure.operator->();
1352  TPZCompMesh *cmesh = fCMesh.operator->();
1353  TPZBuildMultiphysicsMesh::AddConnects(cmeshvec,cmesh);
1354 
1355  nel = fPressureFineMesh->NElements();
1356  for (int64_t el=0; el<nel; el++) {
1357  TPZCompEl *cel = fPressureFineMesh->ElementVec()[el];
1358  if (!cel) {
1359  continue;
1360  }
1361  TPZInterfaceElement *intface = dynamic_cast<TPZInterfaceElement *>(cel);
1362  if (!intface) {
1363  continue;
1364  }
1365  // TPZMultiphysicsInterfaceElement(TPZCompMesh &mesh, TPZGeoEl *ref, int64_t &index, TPZCompElSide left, TPZCompElSide right);
1366  TPZCompElSide pressleft = intface->LeftElementSide();
1367  TPZCompElSide pressright = intface->RightElementSide();
1368  TPZGeoElSide gleft = pressleft.Reference();
1369  TPZGeoElSide gright = pressright.Reference();
1370  TPZCompElSide multleft = gleft.Reference();
1371  TPZCompElSide multright = gright.Reference();
1372  int64_t index;
1373  new TPZMultiphysicsInterfaceElement(fCMesh,intface->Reference(),index,multleft,multright);
1374 
1375  }
1376 
1377 
1379  int64_t npressconnect = fPressureFineMesh->NConnects();
1380  int64_t nlagrangeconnect = fCMeshLagrange->NConnects();
1381  // nel numero de dominios MHM, tem um connect associado a cada um e os mesmos estao no final
1382  for (int64_t el=0; el<nel; el++)
1383  {
1384  TPZCompEl *cel = this->fCMeshConstantPressure->Element(el);
1385  int64_t pressureconnect = cel->ConnectIndex(0);
1386  int64_t cindex = npressconnect+nlagrangeconnect+pressureconnect;
1387  fCMesh->ConnectVec()[cindex].SetLagrangeMultiplier(3);
1388  }
1390  //fCMesh->SaddlePermute();
1391 #ifdef LOG4CXX
1392  if (logger->isDebugEnabled()) {
1393  std::stringstream sout;
1394  fCMesh->Print(sout);
1395  LOGPZ_DEBUG(logger, sout.str())
1396  }
1397 #endif
1398 }
1399 
1400 
1403 {
1404  // for each connect index, the submesh index
1405  std::map<int64_t, int64_t > connectdest;
1406  // for each coarse geometric index, a subcompmesh
1407  std::map<int64_t, TPZSubCompMesh *> submeshes;
1408  std::map<int64_t,int64_t>::iterator it = fMHMtoSubCMesh.begin();
1409 
1410  // create the submeshes
1411  while (it != fMHMtoSubCMesh.end()) {
1412  int64_t index;
1413  TPZSubCompMesh *submesh = new TPZSubCompMesh(fCMesh,index);
1414  submeshes[it->first] = submesh;
1415  it++;
1416  }
1417  for (std::map<int64_t, TPZSubCompMesh *>::iterator it = submeshes.begin(); it != submeshes.end(); it++) {
1418  fMHMtoSubCMesh[it->first] = it->second->Index();
1419  }
1420 
1423 
1424  int64_t nel = fCMesh->NElements();
1425  for (int64_t el=0; el<nel; el++)
1426  {
1427  TPZCompEl *cel = fCMesh->Element(el);
1428  if(!cel) continue;
1429  if (dynamic_cast<TPZSubCompMesh *>(cel)) {
1430  continue;
1431  }
1432  int64_t domain = WhichSubdomain(cel);
1433 
1434  if (domain == -1) {
1435  continue;
1436  }
1437  if (submeshes.find(domain) == submeshes.end()) {
1438  DebugStop();
1439  }
1440  submeshes[domain]->TransferElement(fCMesh.operator->(), cel->Index());
1441 #ifdef LOG4CXX
1442  if (logger->isDebugEnabled()) {
1443  std::stringstream sout;
1444  sout << "Transferring element index " << cel->Index() << " geometric index ";
1445  TPZGeoEl *gel = cel->Reference();
1446  if (gel) {
1447  sout << gel->Index();
1448  }
1449  LOGPZ_DEBUG(logger, sout.str())
1450  }
1451 #endif
1452  }
1454 
1455 
1456  std::map<int64_t, TPZSubCompMesh *>::iterator itsub = submeshes.begin();
1457  while (itsub != submeshes.end()) {
1458  TPZSubCompMesh *submesh = itsub->second;
1459  int nc = submesh->NConnects();
1460  std::set<int64_t> internals;
1461  // put all connects with one element connection internal in the submesh
1462  for (int ic=0; ic<nc; ic++) {
1463  int64_t connectindex = submesh->ConnectIndex(ic);
1464  TPZConnect &c = submesh->Connect(ic);
1465  int lagrange = c.LagrangeMultiplier();
1466  if (c.NElConnected() >1) {
1467  continue;
1468  }
1469  bool makeinternal = false;
1470  // if hybridizing all internal connects can be condensed
1471  if (fHybridize) {
1472  makeinternal = true;
1473  }
1474  else if (lagrange < 3) {
1475  makeinternal = true;
1476  }
1477  int64_t internal = submesh->InternalIndex(connectindex);
1478  if (makeinternal)
1479  {
1480  internals.insert(internal);
1481  }
1482  else
1483  {
1485 #ifdef PZDEBUG
1486  std::cout << "For subdomain " << itsub->first << " connect index " << connectindex << " left external as lagrange multiplier\n";
1487 #endif
1488  }
1489  }
1490  submesh->MakeAllInternal();
1491 // for (std::set<int64_t>::iterator it = internals.begin(); it != internals.end(); it++) {
1492 // submesh->MakeInternal(*it);
1493 // }
1494  submesh->InitializeBlock();
1495  itsub++;
1496  }
1498  itsub = submeshes.begin();
1499  while (itsub != submeshes.end()) {
1500  TPZSubCompMesh *submesh = itsub->second;
1501  int numthreads = 0;
1502  int preconditioned = 0;
1503 #ifdef LOG4CXX
1504  if (logger->isDebugEnabled()) {
1505  std::stringstream sout;
1506  sout << "Newly created submesh for element " << *it << "\n";
1507  submesh->Print(sout);
1508  LOGPZ_DEBUG(logger, sout.str())
1509  }
1510 #endif
1511  TPZAutoPointer<TPZGuiInterface> guiInterface;
1512  submesh->SetAnalysisSkyline(numthreads, preconditioned, guiInterface);
1513  itsub++;
1514  }
1515 
1516  fCMesh->SaddlePermute();
1517 }
1518 
1520 void TPZMHMeshControl::Print(std::ostream &out)
1521 {
1522 
1524  if (fGMesh)
1525  {
1526  out << "******************* GEOMETRIC MESH *****************\n";
1527  fGMesh->Print(out);
1528  }
1529 
1531  // this mesh is the same as fCMesh if there are no lagrange multipliers assocated with the average pressure
1532  if (fPressureFineMesh)
1533  {
1534  out << "******************* PRESSURE MESH *****************\n";
1535  fPressureFineMesh->Print(out);
1536  }
1537 
1538 
1540  if (fCMesh)
1541  {
1542  out << "******************* COMPUTATIONAL MESH *****************\n";
1543  fCMesh->Print(out);
1544  }
1545 
1547  if (fCMeshLagrange)
1548  {
1549  out << "******************* LAGRANGE MULTIPLIER MESH *****************\n";
1550  fCMeshLagrange->Print(out);
1551  }
1552 
1555  {
1556  out << "******************* CONSTANTE PRESSURE MESH *****************\n";
1558  }
1559 
1561  out << "Skeleton Mat Id " << fSkeletonMatId << std::endl;
1562 
1564  out << "Lagrange mat id left - right " << fLagrangeMatIdLeft << " - " << fLagrangeMatIdRight << std::endl;
1565 
1567  out << "Internal polynomial order " << fpOrderInternal << std::endl;
1568 
1570  out << "Skeleton polynomial order " << fpOrderSkeleton << std::endl;
1571 
1573  {
1574  out << "Geometric element indices of the coarse mesh ";
1575  for (std::map<int64_t,int64_t>::iterator it= fMHMtoSubCMesh.begin(); it != fMHMtoSubCMesh.end(); it++) {
1576  out << it->first << " " << it->second << " ";
1577  }
1578  out << std::endl;
1579  }
1581  out << "Skeleton element indices with associated left and right coarse element indices\n";
1582  {
1583  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it;
1584  for (it = fInterfaces.begin(); it != fInterfaces.end(); it++) {
1585  out << "skel index " << it->first << " Left Right indices " << it->second.first << " " << it->second.second << std::endl;
1586  }
1587  }
1588 
1590 
1593  out << "Will generate a constant pressure mesh " << fLagrangeAveragePressure << std::endl;
1595  out << "Subdomain indices of the connects\n";
1596  for (auto it = fConnectToSubDomainIdentifier.begin(); it != fConnectToSubDomainIdentifier.end(); it++)
1597  {
1598  out << "Mesh address " << (void *) it->first;
1599  TPZManVector<int64_t> &cvec = it->second;
1600  for (int64_t i=0; i<cvec.size(); i++) {
1601  if (i && !(i%20)) {
1602  out << std::endl;
1603  }
1604  out << "(" << i << "->" << cvec[i] << ") ";
1605  }
1606  out << std::endl;
1607  }
1608 
1609 }
1610 
1613 {
1614  int matid = *fMaterialIds.begin();
1615  TPZMaterial *mat = fCMesh->FindMaterial(matid);
1616  if (!mat) {
1617  DebugStop();
1618  }
1619 
1620  TPZFNMatrix<1,STATE> xk(fNState,fNState,0.),xb(fNState,fNState,0.),xc(fNState,fNState,0.),xf(fNState,1,0.);
1621  TPZFNMatrix<4,STATE> val1(fNState,fNState,0.), val2Flux(fNState,1,0.);
1622  TPZMat1dLin *matPerif = NULL;
1623 
1625  DebugStop();
1626  }
1627  matPerif = new TPZMat1dLin(fSkeletonMatId);
1628  matPerif->SetMaterial(xk, xc, xb, xf);
1629  fCMesh->InsertMaterialObject(matPerif);
1630 
1631  if (1) {
1633  DebugStop();
1634  }
1635  matPerif = new TPZMat1dLin(fPressureSkeletonMatId);
1636  matPerif->SetMaterial(xk, xc, xb, xf);
1637  fCMesh->InsertMaterialObject(matPerif);
1638 
1640  DebugStop();
1641  }
1642  matPerif = new TPZMat1dLin(fSecondSkeletonMatId);
1643  matPerif->SetMaterial(xk, xc, xb, xf);
1644 
1645  fCMesh->InsertMaterialObject(matPerif);
1646 
1647 
1648  int LagrangeMatIdLeft = 50;
1649  int LagrangeMatIdRight = 51;
1650  int nstate = fNState;
1651  int dim = fGMesh->Dimension();
1652 
1654  DebugStop();
1655  }
1657  DebugStop();
1658  }
1661  if (fSwitchLagrangeSign) {
1662  matleft->SetMultiplier(-1.);
1663  matright->SetMultiplier(1.);
1664  }
1665  else
1666  {
1667  matleft->SetMultiplier(1.);
1668  matright->SetMultiplier(-1.);
1669  }
1670  fCMesh->InsertMaterialObject(matleft);
1671  fCMesh->InsertMaterialObject(matright);
1672  }
1673 
1674 }
1675 
1676 void TPZMHMeshControl::HybridizeSkeleton(int skeletonmatid, int pressurematid)
1677 {
1678  // comment this line or not to switch the type of skeleton elements
1679  int meshdim = fCMesh->Dimension();
1680 // fCMesh->SetDimModel(meshdim-1);
1681 // fCMesh->ApproxSpace().SetAllCreateFunctionsDiscontinuous();
1684  int order = fpOrderSkeleton;
1685  if (order < 1) {
1686  DebugStop();
1687  order = 1;
1688  }
1689  TPZCompMesh *cmesh = fCMesh.operator->();
1690  // expand the vector
1691  fConnectToSubDomainIdentifier[cmesh].Resize(cmesh->NConnects()+10000, -1);
1692  cmesh->SetDefaultOrder(order);
1693  int64_t nelem = fGMesh->NElements();
1695  // keep the pointers of the skeleton elements we will work
1696  TPZManVector<TPZCompEl *> skeletoncomp(nelem,0);
1697  std::map<int64_t, std::pair<int64_t,int64_t> >::iterator it;
1698  // loop over the skeleton elements
1699  for (it=fInterfaces.begin(); it != fInterfaces.end(); it++) {
1700  int64_t elindex = it->first;
1701  // skip the boundary interfaces
1702  if (it->first == it->second.second) {
1703  continue;
1704  }
1705  TPZGeoEl *gel = fGMesh->ElementVec()[elindex];
1706  // skip the boundary elements
1707  if (gel->MaterialId() < 0) {
1708  continue;
1709  }
1710  TPZCompEl *cel = gel->Reference();
1711  if (!cel) {
1712  DebugStop();
1713  }
1714  skeletoncomp[elindex] = cel;
1715  }
1717  for (it=fInterfaces.begin(); it != fInterfaces.end(); it++) {
1718  int64_t elindex = it->first;
1719  // skip the boundary elements
1720  if (elindex == it->second.second) {
1721  continue;
1722  }
1723  TPZGeoEl *gel = fGMesh->ElementVec()[elindex];
1724  TPZCompEl *celskeleton = skeletoncomp[elindex];
1725  // skip the boundary elements
1726  if (gel->MaterialId() < 0) {
1727  DebugStop();
1728  continue;
1729  }
1730  int64_t index1,index2;
1731  TPZManVector<TPZGeoEl *,4> GelVec(3);
1732  GelVec[0] = gel;
1733  TPZGeoElSide gelside(gel,gel->NSides()-1);
1734  // create geometric elements aint64_t the skeleton element
1735  TPZGeoElBC gbc1(gelside,fSecondSkeletonMatId);
1736  TPZGeoElBC gbc2(gelside,fPressureSkeletonMatId);
1737  GelVec[1] = gbc1.CreatedElement();
1738  GelVec[2] = gbc2.CreatedElement();
1739 
1742  // create a discontinuous element to model the flux
1743  // index1 is the new flux element
1744  fCMesh->CreateCompEl(GelVec[1], index1);
1745  GelVec[1]->ResetReference();
1746  // index 2 is the new pressure element
1749  fCMesh->CreateCompEl(GelVec[2], index2);
1750  GelVec[2]->ResetReference();
1751 
1752  SetSubdomain(fCMesh->Element(index1), -1);
1753  SetSubdomain(fCMesh->Element(index2), -1);
1754 
1755  // swap the elements. The skeleton element is now a pressure element
1756  // the former skeleton element is now a newly created geometric element
1757  celskeleton->SetReference(GelVec[2]->Index());
1758  fCMesh->Element(index2)->SetReference(gel->Index());
1759  GelVec[2]->SetMaterialId(fSkeletonMatId);
1761 
1762 
1763  }
1764  // the flux elements and pressure elements have been created, now generate the interface elements
1765  // the existing interface elements will be adjusted
1766  // two new interfaces need to be created
1768  for(it=fInterfaces.begin(); it != fInterfaces.end(); it++) {
1769  int64_t elindex = it->first;
1770  // skip the boundary elements
1771  if (elindex == it->second.second) {
1772  continue;
1773  }
1774  TPZGeoEl *gel = fGMesh->ElementVec()[elindex];
1775  // skip the boundary elements
1776  if (gel->MaterialId() < 0) {
1777  DebugStop();
1778  continue;
1779  }
1780  // the element should be a pressure element
1781  if (!gel->Reference() || gel->MaterialId() != fPressureSkeletonMatId) {
1782  DebugStop();
1783  }
1784  // identify the pressure element
1785  TPZCompEl *celpressure = gel->Reference();
1786  TPZGeoElSide gelside(gel,gel->NSides()-1);
1787  // look for the flux elements
1788  TPZCompEl *celskeleton = 0, *celsecondskeleton = 0;
1789 
1790  // find all elements connected to the pressure element
1791  TPZGeoElSide neighbour = gelside.Neighbour();
1792  while (neighbour != gelside) {
1793  if (neighbour.Element()->MaterialId() == fSkeletonMatId) {
1794  celskeleton = neighbour.Element()->Reference();
1795  }
1796  if (neighbour.Element()->MaterialId() == fSecondSkeletonMatId) {
1797  celsecondskeleton = neighbour.Element()->Reference();
1798  }
1799  neighbour = neighbour.Neighbour();
1800  }
1801 
1802  if (!celpressure || !celskeleton || !celsecondskeleton) {
1803  DebugStop();
1804  }
1805 
1806  std::map<int64_t, std::list<TPZInterfaceElement *> > interfaces;
1807  ConnectedInterfaceElements(it->first, it->second, interfaces);
1808 
1809 #ifdef PZDEBUG
1810  {
1811  std::stringstream sout;
1812  sout << "For skeleton element gelindex " << gel->Index() << " area " << gel->SideArea(gel->NSides()-1) << " we found interfaces\n";
1813  for (std::map<int64_t, std::list<TPZInterfaceElement *> >::iterator it = interfaces.begin(); it != interfaces.end(); it++) {
1814  sout << "domain " << it->first << std::endl;
1815  for (std::list<TPZInterfaceElement *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
1816  TPZGeoEl *g = (*it2)->Reference();
1817  int ns = g->NSides();
1818  sout << "intface gelindex " << (*it2)->Reference()->Index() << " celindex " << (*it2)->Index() << " area " << g->SideArea(ns-1) << std::endl;
1819  }
1820  }
1821  LOGPZ_DEBUG(logger, sout.str())
1822  }
1823 #endif
1824 
1825  // find all interface elements (and others) connected to the pressure element
1826  for (std::map<int64_t, std::list<TPZInterfaceElement *> >::iterator it = interfaces.begin(); it != interfaces.end(); it++) {
1827  for (std::list<TPZInterfaceElement *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
1828  TPZInterfaceElement *intface = *it2;
1829  int matid = intface->Reference()->MaterialId();
1830  if (matid != fLagrangeMatIdLeft && matid != fLagrangeMatIdRight) {
1831  DebugStop();
1832  }
1833  TPZCompElSide right = intface->RightElementSide();
1834  TPZCompElSide left = intface->LeftElementSide();
1835  if (right.Element() != celskeleton) {
1836  DebugStop();
1837  }
1838  // switch the interface element with this material id to the newly created flux element
1839  if (matid == fLagrangeMatIdRight) {
1840  TPZCompElSide cside(celsecondskeleton,gel->NSides()-1);
1841  intface->SetLeftRightElements(left, cside);
1842  right = cside;
1843  }
1844 
1845  int64_t leftcindex = left.Element()->ConnectIndex(0);
1846  int subdomain = fConnectToSubDomainIdentifier[cmesh][leftcindex];
1847  if (subdomain == -1) {
1848  DebugStop();
1849  }
1850  fGeoToMHMDomain[right.Element()->Reference()->Index()] = subdomain;
1851  SetSubdomain(right.Element(), subdomain);
1852 #ifdef LOG4CXX
1853  {
1854  std::stringstream sout;
1855  sout << "Interface right flux element " << right.Element()->Index() << " has been adjusted subdomain is " << WhichSubdomain(right.Element());
1856  LOGPZ_DEBUG(logger, sout.str())
1857  }
1858 #endif
1859  }
1860  }
1861 
1862 #ifdef PZDEBUG
1863  {
1864  std::stringstream sout;
1865  sout << "For skeleton element gelindex " << gel->Index() << " area " << gel->SideArea(gel->NSides()-1) << " we found interfaces\n";
1866  for (std::map<int64_t, std::list<TPZInterfaceElement *> >::iterator it = interfaces.begin(); it != interfaces.end(); it++) {
1867  sout << "domain " << it->first << std::endl;
1868  for (std::list<TPZInterfaceElement *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
1869  sout << "intface gelindex " << (*it2)->Reference()->Index() << " celindex " << (*it2)->Index() << " subdomain " << WhichSubdomain(*it2) << std::endl;
1870  }
1871  }
1872  LOGPZ_DEBUG(logger, sout.str())
1873  }
1874 #endif
1875 
1876 
1877  // create the interfaces between the flux elements and the newly created pressure element
1878  TPZCompElSide leftflux(celskeleton,gel->NSides()-1);
1879  TPZCompElSide rightflux(celsecondskeleton,gel->NSides()-1);
1880  TPZCompElSide pressure(celpressure,gel->NSides()-1);
1881  TPZGeoElBC gbc3(gelside,fLagrangeMatIdRight);
1882  TPZGeoElBC gbc4(gelside,fLagrangeMatIdLeft);
1883  int64_t index3, index4;
1884  TPZInterfaceElement *intfaceleft = new TPZInterfaceElement(fCMesh,gbc3.CreatedElement(),index3);
1885  TPZInterfaceElement *intfaceright = new TPZInterfaceElement(fCMesh,gbc4.CreatedElement(),index4);
1886  intfaceleft->SetLeftRightElements(leftflux, pressure);
1887  intfaceright->SetLeftRightElements(rightflux, pressure);
1888 #ifdef PZDEBUG
1889  {
1890  std::stringstream sout;
1891  sout << "Interfaces created by hybridization interface left subdomain el index " << intfaceleft->Index() << " dom " << WhichSubdomain(intfaceleft) <<
1892  " el index " << intfaceright->Index() << " interface right subdomain " << WhichSubdomain(intfaceright);
1893  LOGPZ_DEBUG(logger, sout.str())
1894  }
1895 #endif
1896  // adjust the lagrange level of the flux and pressure connects
1897  // pressure element
1898  int nc = celpressure->NConnects();
1899  for (int ic=0; ic<nc; ic++) {
1900  int lagrangelevel = 4;
1901  celpressure->Connect(ic).SetLagrangeMultiplier(lagrangelevel);
1902  }
1903  // skeleton element
1904  nc = celskeleton->NConnects();
1905  for (int ic=0; ic<nc; ic++) {
1906  int lagrangelevel = 2;
1907  celskeleton->Connect(ic).SetLagrangeMultiplier(lagrangelevel);
1908  }
1909  nc = celsecondskeleton->NConnects();
1910  for (int ic=0; ic<nc; ic++) {
1911  int lagrangelevel = 2;
1912  celsecondskeleton->Connect(ic).SetLagrangeMultiplier(lagrangelevel);
1913  }
1914  }
1916  fCMesh->SetDimModel(meshdim);
1917  fConnectToSubDomainIdentifier[fCMesh.operator->()].Resize(fCMesh->NConnects(), -1);
1918 
1919  // the new geometric elements are not internal
1921 }
1922 
1925 void TPZMHMeshControl::SetSubdomain(TPZCompEl *cel, int64_t subdomain)
1926 {
1927  int ncon = cel->NConnects();
1928  for (int ic=0; ic<ncon; ic++) {
1929  int64_t cindex = cel->ConnectIndex(ic);
1930  SetSubdomain(cel->Mesh(), cindex, subdomain);
1931  }
1932  TPZGeoEl *gel = cel->Reference();
1933  int64_t index = gel->Index();
1934 
1935  if (index >= fGeoToMHMDomain.size()) {
1936  fGeoToMHMDomain.Resize(index+1, -1);
1937  fGeoToMHMDomain[index] = subdomain;
1938  }
1939 }
1940 
1942 void TPZMHMeshControl::SetSubdomain(TPZCompMesh *cmesh, int64_t cindex, int64_t subdomain)
1943 {
1944  // cmesh indicates the atomic mesh. It can be a flux mesh or pressure mesh
1945  if (cindex >= fConnectToSubDomainIdentifier[cmesh].size()) {
1946  fConnectToSubDomainIdentifier[cmesh].Resize(cindex+1, -1);
1947  }
1948  fConnectToSubDomainIdentifier[cmesh][cindex] = subdomain;
1949 
1950 }
1951 
1953 // this method calls debugstop if the element beint64_ts to two subdomains
1955 {
1956  int ncon = cel->NConnects();
1957  std::set<int64_t> domains;
1958  TPZCompMesh *cmesh = cel->Mesh();
1960  for (int ic=0; ic<ncon; ic++)
1961  {
1962  int64_t cindex = cel->ConnectIndex(ic);
1963  if (cvec[cindex] != -1) {
1964  domains.insert(cvec[cindex]);
1965  }
1966  }
1967  // if the element has connects in two different subdomains then something is wrong
1968  if (domains.size() > 1) {
1969  for (int ic=0; ic<ncon; ic++) {
1970  int64_t cindex = cel->ConnectIndex(ic);
1971  std::cout << cindex << "|" << cvec[cindex] << " ";
1972  }
1973  std::cout << std::endl;
1974  DebugStop();
1975  }
1976  if (domains.size() ==0) {
1977  return -1;
1978  }
1979  int64_t domain = *domains.begin();
1980  return domain;
1981 }
1982 
1984 // the subdomain indices of the connects to the multi physics mesh
1986 {
1987  int nmeshes = meshvec.size();
1988  int64_t totalconnects = 0;
1989  for (int im=0; im<nmeshes; im++) {
1990  if (fConnectToSubDomainIdentifier.find(meshvec[im]) == fConnectToSubDomainIdentifier.end()) {
1991  DebugStop();
1992  }
1993  totalconnects += fConnectToSubDomainIdentifier[meshvec[im]].size();
1994  }
1995  fConnectToSubDomainIdentifier[multiphysicsmesh].Resize(totalconnects);
1996  TPZManVector<int64_t> &mfvec = fConnectToSubDomainIdentifier[multiphysicsmesh];
1997  int64_t count = 0;
1998  for (int im=0; im<nmeshes; im++) {
2000  int64_t nc = cvec.size();
2001  for (int64_t ic=0; ic<nc; ic++) {
2002  mfvec[count++] = cvec[ic];
2003  }
2004  }
2005 }
2006 
2007 
2008 
2009 bool IsAncestor(TPZGeoEl *son, TPZGeoEl *father)
2010 {
2011  TPZGeoEl *check = son;
2012  while (check && check != father) {
2013  check = check->Father();
2014  }
2015  if (check==father) {
2016  return true;
2017  }
2018 
2019  return false;
2020 }
2022 // the computational mesh is determined by the element pointed to by the geometric element
2023 // skeleton index of the geometric element which defines the skeleton
2024 // leftright indices of the left and right geometric elements which define the domains
2025 // ellist : two elements : list of elements connected to the left and right indices respectively
2026 // ellist : one element : skeleton is a boundary list contains the compelsides linked to the skeleton on the interior of the mech
2027 void TPZMHMeshControl::ConnectedElements(int64_t skeleton, std::pair<int64_t,int64_t> &leftright, std::map<int64_t, std::list<TPZCompElSide> > &ellist)
2028 {
2029  TPZGeoEl *gelskeleton = fGMesh->Element(skeleton);
2030  int meshdim = fGMesh->Dimension();
2031  if (gelskeleton->Dimension() != meshdim-1) {
2032  DebugStop();
2033  }
2034  TPZGeoElSide gelside(gelskeleton,gelskeleton->NSides()-1);
2035  TPZGeoElSide neighbour(gelside.Neighbour());
2036  while (neighbour != gelside) {
2037  if (neighbour.Element()->MaterialId() == fSkeletonWrapMatId || neighbour.Element()->MaterialId() == fBoundaryWrapMatId) {
2038  break;
2039  }
2040  neighbour = neighbour.Neighbour();
2041  }
2042  if(neighbour == gelside)
2043  {
2044  std::cout << "For element " << gelskeleton->Index() << " with mat id " << gelskeleton->MaterialId() << " no skeleton found\n";
2045  neighbour = gelside.Neighbour();
2046  while(neighbour != gelside)
2047  {
2048  std::cout << "Neighbour matid " << neighbour.Element()->MaterialId() << std::endl;
2049  neighbour = neighbour.Neighbour();
2050  }
2051  DebugStop();
2052  }
2053  TPZGeoElSide skeletonwrap = neighbour;
2054  TPZStack<TPZGeoElSide> wrapstack;
2055  wrapstack.Push(skeletonwrap);
2056  while(wrapstack.size())
2057  {
2058  skeletonwrap = wrapstack.Pop();
2059  neighbour = skeletonwrap.Neighbour();
2060  while (neighbour != skeletonwrap)
2061  {
2062  if (neighbour.Element()->Dimension() == meshdim && neighbour.Element()->Reference()) {
2063  if (fGeoToMHMDomain[neighbour.Element()->Index()] == leftright.first)
2064  {
2065  ellist[leftright.first].push_back(neighbour.Reference());
2066  }
2067  if (skeleton != leftright.second && fGeoToMHMDomain[neighbour.Element()->Index()] == leftright.second)
2068  {
2069  ellist[leftright.second].push_back(neighbour.Reference());
2070  }
2071  }
2072  neighbour = neighbour.Neighbour();
2073  }
2074  if (skeletonwrap.HasSubElement()) {
2075  int nsub = skeletonwrap.Element()->NSubElements();
2076  for (int isub = 0; isub < nsub; isub++) {
2077  TPZGeoEl *subel = skeletonwrap.Element()->SubElement(isub);
2078  TPZGeoElSide subelside(subel,subel->NSides()-1);
2079  wrapstack.Push(subelside);
2080  }
2081  }
2082  }
2083  // a skeleton element with no computational elements is a bug
2084  if (ellist.size() == 0) {
2085  DebugStop();
2086  }
2087  // if the skeleton is boundary and if there are more than one subdomain, it is a bug
2088  if (skeleton == leftright.second && ellist.size() != 1) {
2089  DebugStop();
2090  }
2091  // if the skeleton is not boundary then there must be exactly two subdomains connected
2092  if(skeleton != leftright.second && ellist.size() != 2)
2093  {
2094  DebugStop();
2095  }
2096 }
2097 
2099 // the computational mesh is determined by the element pointed to by the geometric element
2100 void TPZMHMeshControl::ConnectedInterfaceElements(int64_t skeleton, std::pair<int64_t,int64_t> &leftright, std::map<int64_t, std::list<TPZInterfaceElement *> > &intfaces)
2101 {
2102  std::map<int64_t, std::list<TPZCompElSide> > ellist;
2103  ConnectedElements(skeleton, leftright, ellist);
2104  // neighbour to each element there is an interface element
2105  for (std::map<int64_t, std::list<TPZCompElSide> >::iterator it = ellist.begin(); it != ellist.end(); it++) {
2106  std::list<TPZCompElSide> &loclist = it->second;
2107  for (std::list<TPZCompElSide>::iterator it2 = loclist.begin(); it2 != loclist.end(); it2++) {
2108  TPZCompElSide celside = *it2;
2109  TPZGeoElSide gelside = celside.Reference();
2110  TPZGeoElSide neighbour = gelside.Neighbour();
2111  while (neighbour != gelside) {
2112  TPZCompElSide celneigh = neighbour.Reference();
2113  if (celneigh) {
2114  TPZInterfaceElement *intface = dynamic_cast<TPZInterfaceElement *>(celneigh.Element());
2115  if (intface && (intface->LeftElementSide() == celside || intface->RightElementSide() == celside)) {
2116  intfaces[it->first].push_back(intface);
2117  break;
2118  }
2119  }
2120  neighbour = neighbour.Neighbour();
2121  }
2122  if (neighbour == gelside) {
2123  DebugStop();
2124  }
2125  }
2126  }
2127 }
2128 
2131 {
2132  // all the elements should be neighbour of a wrap element
2133  int64_t nel = fGMesh->NElements();
2134 
2135 // int meshdim = fGMesh->Dimension();
2136 // first create the neighbours of boundary elements (works for dim = fGMesh->Dimension()-2)
2137  for (int64_t el=0; el<nel; el++) {
2138  TPZGeoEl *gel = fGMesh->Element(el);
2139  if (!gel || gel->Dimension() != dim) {
2140  continue;
2141  }
2142  int ns = gel->NSides();
2143  for (int is=0; is<ns; is++) {
2144  if (gel->SideDimension(is) != dim-1) {
2145  continue;
2146  }
2147  TPZGeoElSide gelside(gel,is);
2148  TPZGeoElSide neighbour = gelside.Neighbour();
2149  while (neighbour != gelside) {
2150  if (neighbour.Element()->MaterialId() == fBoundaryWrapMatId) {
2151  int wrapmat = HasWrapNeighbour(gelside);
2152  if (wrapmat && wrapmat != fBoundaryWrapMatId) {
2153  DebugStop();
2154  }
2155  else
2156  {
2157  CreateWrap(gelside,fBoundaryWrapMatId);
2158  }
2159  }
2160  neighbour = neighbour.Neighbour();
2161  }
2162  }
2163  }
2164  // create the wrap elements around the skeleton elements
2165  for (int64_t el=0; el<nel; el++) {
2166  TPZGeoEl *gel = fGMesh->Element(el);
2167  if (!gel || gel->Dimension() != dim) {
2168  continue;
2169  }
2170  int ns = gel->NSides();
2171  for (int is=0; is<ns; is++) {
2172  if (gel->SideDimension(is) != dim-1) {
2173  continue;
2174  }
2175  TPZGeoElSide gelside(gel,is);
2176  TPZGeoElSide neighbour = gelside.Neighbour();
2177  while (neighbour != gelside) {
2178  int neighmatid = neighbour.Element()->MaterialId();
2179  if (IsSkeletonMatid(neighmatid)) {
2180  int wrapmat = HasWrapNeighbour(gelside);
2181  if (wrapmat && wrapmat != fSkeletonWrapMatId && wrapmat != fBoundaryWrapMatId) {
2182  DebugStop();
2183  }
2184  else if(!wrapmat)
2185  {
2186  CreateWrap(neighbour,fSkeletonWrapMatId);
2187  }
2188  }
2189  neighbour = neighbour.Neighbour();
2190  }
2191  }
2192  }
2193  for (int64_t el=0; el<nel; el++) {
2194  TPZGeoEl *gel = fGMesh->Element(el);
2195  if (!gel || gel->Dimension() != dim) {
2196  continue;
2197  }
2198  int ns = gel->NSides();
2199  for (int is=0; is<ns; is++) {
2200  if (gel->SideDimension(is) != dim-1) {
2201  continue;
2202  }
2203  TPZGeoElSide gelside(gel,is);
2204  if (!HasWrapNeighbour(gelside)) {
2205  CreateWrap(gelside);
2206  }
2207  }
2208  }
2209 }
2210 
2213 {
2214 
2215  int element_dimension = gelside.Dimension();
2216  std::set<int> wrapmat;
2217  wrapmat.insert(fSkeletonWrapMatId);
2218  wrapmat.insert(fBoundaryWrapMatId);
2219  wrapmat.insert(fInternalWrapMatId);
2220 #ifdef PZDEBUG
2221  {
2222  // gelside cannot have a material of type wrap
2223  if(gelside.Element()->Dimension() == element_dimension && wrapmat.find(gelside.Element()->MaterialId()) != wrapmat.end())
2224  {
2225  DebugStop();
2226  }
2227  }
2228 #endif
2229  TPZGeoElSide neighbour = gelside.Neighbour();
2230  while (neighbour != gelside) {
2231  if (neighbour.Element()->Dimension() == element_dimension && wrapmat.find(neighbour.Element()->MaterialId()) != wrapmat.end()) {
2232  return neighbour.Element()->MaterialId();
2233  }
2234  neighbour = neighbour.Neighbour();
2235  }
2236  return 0;
2237 }
2238 
2242 {
2243 #ifdef PZDEBUG
2244  TPZGeoElSide father = gelside.StrictFather();
2245  if (father && father.Dimension() == gelside.Dimension()) {
2246  DebugStop();
2247  }
2248 #endif
2249  TPZGeoElSide neighbour = gelside.Neighbour();
2250  while (neighbour != gelside) {
2251  TPZGeoElSide neighfather = neighbour.StrictFather();
2252  if (neighfather && neighfather.Dimension() == gelside.Dimension()) {
2253  std::cout << "neighfather dimension " << neighfather.Dimension() << " my dimension " << gelside.Dimension() << std::endl;
2254  DebugStop();
2255  }
2256  neighbour = neighbour.Neighbour();
2257  }
2258 }
2259 
2260 
2263 {
2264  TPZGeoElSide father = gelside.StrictFather();
2265  while(father && father.Dimension() == gelside.Dimension())
2266  {
2267  gelside = gelside.StrictFather();
2268  father = gelside.StrictFather();
2269  }
2270  int meshdim = gelside.Element()->Mesh()->Dimension();
2271 //#ifdef PZDEBUG
2272 // if (gelside.Dimension() != meshdim-1) {
2273 // DebugStop();
2274 // }
2275 //#endif
2276  int wrapmat = HasWrapNeighbour(gelside);
2277  if(wrapmat)
2278  {
2279  return wrapmat;
2280  }
2281  if (gelside.Dimension() == meshdim-1)
2282  {
2283  int hasDimNeighbour = 0;
2284  TPZGeoElSide neighbour = gelside.Neighbour();
2285  bool isBoundary = false;
2286  while (neighbour != gelside) {
2287  if (neighbour.Element()->MaterialId() <0) {
2288  isBoundary = true;
2289  }
2290  if (neighbour.Element()->Dimension() == meshdim && !isBoundary) {
2291  hasDimNeighbour = 1;
2292  }
2293  if (IsSkeletonMatid(neighbour.Element()->MaterialId())) {
2294  return fSkeletonWrapMatId;
2295  }
2296  neighbour = neighbour.Neighbour();
2297  }
2298  if (hasDimNeighbour) {
2299  return fInternalWrapMatId;
2300  }
2301  return fBoundaryWrapMatId;
2302  }
2303  else if(gelside.Dimension() == meshdim-2)
2304  {
2305  TPZGeoElSide neighbour = gelside.Neighbour();
2306  int hasBoundaryNeighbour = 0;
2307  while (neighbour != gelside) {
2308  if (IsSkeletonMatid(neighbour.Element()->MaterialId())) {
2309  return fSkeletonWrapMatId;
2310  }
2311  if (neighbour.Element()->MaterialId() == fBoundaryWrapMatId)
2312  {
2313  hasBoundaryNeighbour = 1;
2314  }
2315  neighbour = neighbour.Neighbour();
2316  }
2317  if (hasBoundaryNeighbour) {
2318  return fBoundaryWrapMatId;
2319  }
2320  return fInternalWrapMatId;
2321  }
2322  else
2323  {
2324  DebugStop();
2325  }
2326  return wrapmat;
2327 }
2328 
2331 {
2332  TPZGeoElSide father = gelside.StrictFather();
2333  while(father && father.Dimension() == gelside.Dimension())
2334  {
2335  gelside = gelside.StrictFather();
2336  father = gelside.StrictFather();
2337  }
2338 #ifdef PZDEBUG
2339 // CheckDivisionConsistency(gelside);
2340 #endif
2341  int wrapmat = HasWrapNeighbour(gelside);
2342  if(!wrapmat)
2343  {
2344  wrapmat = WrapMaterialId(gelside);
2345  TPZGeoElBC gbc(gelside, wrapmat);
2346  DivideWrap(gbc.CreatedElement());
2347  }
2348  else
2349  {
2350  TPZGeoElSide neighbour = gelside;
2351  while (neighbour != gelside) {
2352  if (neighbour.Element()->MaterialId() == wrapmat) {
2353  DivideWrap(neighbour.Element());
2354  break;
2355  }
2356  neighbour = neighbour.Neighbour();
2357  }
2358  }
2359 }
2360 
2362 void TPZMHMeshControl::CreateWrap(TPZGeoElSide gelside, int wrapmaterial)
2363 {
2364  TPZGeoElSide father = gelside.StrictFather();
2365  while(father && father.Dimension() == gelside.Dimension())
2366  {
2367  gelside = gelside.StrictFather();
2368  father = gelside.StrictFather();
2369  }
2370 #ifdef PZDEBUG
2371  if(gelside.Element()->Mesh()->Dimension() == 2)
2372  {
2373  CheckDivisionConsistency(gelside);
2374  }
2375 #endif
2376  int wrapmat = HasWrapNeighbour(gelside);
2377  if(wrapmat == 0)
2378  {
2379  wrapmat = wrapmaterial;
2380  TPZGeoElBC gbc(gelside, wrapmat);
2381  DivideWrap(gbc.CreatedElement());
2382  }
2383  else if(wrapmaterial != wrapmat)
2384  {
2385  DebugStop();
2386  }
2387  else
2388  {
2389  TPZGeoElSide neighbour = gelside;
2390  while (neighbour != gelside) {
2391  if (neighbour.Element()->MaterialId() == wrapmat) {
2392  DivideWrap(neighbour.Element());
2393  break;
2394  }
2395  neighbour = neighbour.Neighbour();
2396  }
2397  }
2398 
2399 }
2400 
2401 
2404 {
2405  TPZGeoElSide gelside(wrapelement, wrapelement->NSides()-1);
2406  TPZGeoElSide neighbour = gelside.Neighbour();
2407  while (neighbour != gelside) {
2408  if(neighbour.Element()->HasSubElement() && neighbour.NSubElements() > 1)
2409  {
2411  if (neighbour.Side() == neighbour.NSides()-1) {
2412  TPZAutoPointer<TPZRefPattern> siderefpattern = neighbour.Element()->GetRefPattern();
2413  if(!siderefpattern) DebugStop();
2414  wrapelement->SetRefPattern(siderefpattern);
2415  }
2416  else
2417  {
2418  TPZAutoPointer<TPZRefPattern> elrefpattern = neighbour.Element()->GetRefPattern();
2419  if(!elrefpattern)
2420  {
2421  std::cout << "We expect elements to have refinement patterns\n";
2422  DebugStop();
2423  }
2424  TPZAutoPointer<TPZRefPattern> siderefpattern = elrefpattern->SideRefPattern(neighbour.Side());
2425  if(!siderefpattern) DebugStop();
2426  wrapelement->SetRefPattern(siderefpattern);
2427  }
2428 
2429  wrapelement->Divide(subels);
2430 #ifdef PZDEBUG
2431  if(subels.size() == 1)
2432  {
2433  DebugStop();
2434  }
2435 #endif
2436  for (int is=0; is<subels.size(); is++) {
2437  DivideWrap(subels[is]);
2438  }
2439  break;
2440  }
2441  neighbour = neighbour.Neighbour();
2442  }
2443 }
2444 
2445 
int64_t NElements() const
Number of computational elements allocated.
Definition: pzcmesh.h:169
void CheckDivisionConsistency(TPZGeoElSide gelside)
void EqualorHigherCompElementList2(TPZStack< TPZCompElSide > &celside, int onlyinterpolated, int removeduplicates)
Will return all elements of equal or higher level than than the current element.
void AddElementBoundaries(int64_t elseed, int64_t compelindex, TPZStack< TPZCompElSide > &result)
put the element side which face the boundary on the stack
bool fLagrangeAveragePressure
flag to determine whether a lagrange multiplier is included to force zero average pressures in the su...
Material which implements a Lagrange Multiplier.
void ConnectedInterfaceElements(int64_t skeleton, std::pair< int64_t, int64_t > &leftright, std::map< int64_t, std::list< TPZInterfaceElement *> > &ellist)
identify interface elements connected to the skeleton elements
static void SetgOrder(int order)
Sets the value of the default interpolation order.
Definition: pzcompel.h:825
TPZAutoPointer< TPZCompMesh > fCMeshLagrange
computational mesh to represent the distributed flux in each subdomain
void SetAllCreateFunctionsContinuous()
Definition: pzcmesh.h:508
void IncrementElConnected()
Increment fNElConnected.
Definition: pzconnect.h:260
Implements computational element and a side. Computational Element.
Definition: pzcompel.h:632
Represents a set of shape functions associated with a computational element/side. Computational Eleme...
Definition: pzconnect.h:30
bool IsAncestor(TPZGeoEl *son, TPZGeoEl *father)
TPZAutoPointer< TPZCompMesh > fCMesh
computational MHM mesh being built by this class
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.
bool IsSibling(int64_t son, int64_t father)
verify if the element is a sibling of
Implements a vector class which allows to use external storage provided by the user. Utility.
Definition: pzquad.h:16
void CreateSkeleton()
will create the elements on the skeleton
int MaterialId() const
Returns the material index of the element.
Definition: pzgeoel.h:250
clarg::argBool bc("-bc", "binary checkpoints", false)
clarg::argInt nsub("-nsub", "number of substructs", 4)
int64_t NEquations()
This computes the number of equations associated with non-restrained nodes.
Definition: pzcmesh.cpp:721
clarg::argInt dimension("-d", "Matrices dimension M x M", 1000)
void SaddlePermute()
Put the sequence number of the pressure connects after the seq number of the flux connects...
Definition: pzcmesh.cpp:2328
TPZGeoElSide StrictFather()
returns the father/side pair which contains this/side and is strictly larger than this/side ...
TPZGeoElSide Reference() const
Reference to the geometric element.
Definition: pzcompel.cpp:748
void SetFalseUseQsiEta()
virtual void AddElement(TPZCompEl *cel, int64_t mesh)=0
int fSecondSkeletonMatId
material id associated with the skeleton elements
int fSkeletonMatId
material id associated with the skeleton elements
TPZGeoElSide Father2() const
returns the father/side pair which contains the set of points associated with this/side ...
TPZMHMeshControl & operator=(const TPZMHMeshControl &cp)
int64_t fGlobalSystemSize
number of equations when not condensing anything
void PrintBoundaryInfo(std::ostream &out)
print the indices of the boundary elements and interfaces
void BuildWrapMesh(int dim)
Create the wrap elements.
virtual void Print(std::ostream &out=std::cout) const override
Prints the submesh information on the specified device/file out.
Definition: pzsubcmesh.cpp:498
void SetLagrangeMultiplier(unsigned char mult)
Set the connect as a pressure connect or not.
Definition: pzconnect.h:236
int64_t WhichSubdomain(TPZCompEl *cel)
returns to which subdomain a given element beint64_ts
std::set< int > fMaterialIds
materials used for modeling the differential equation
virtual int64_t NMeshes()=0
void SetLeftRightElements(TPZCompElSide &left, TPZCompElSide &right)
Set neighbors.
int64_t NElements() const
Number of elements of the mesh.
Definition: pzgmesh.h:129
bool fHybridize
flag to indicate whether we create a hybridized mesh
void GetSubElements2(TPZStack< TPZGeoElSide > &subelements)
build the list of element/side pairs which compose the current set of points
Contains the TPZL2Projection class which implements an L2 projection to constant solution values...
Utility class which represents an element with its side. The Geometric approximation classes Geometry...
Definition: pzgeoelside.h:83
void DivideBoundarySkeletonElements()
divide the boundary skeleton elements
void DivideSkeletonElements(int ndivide)
divide the skeleton elements
int fpOrderInternal
interpolation order of the internal elements
void DefinePartition(TPZVec< int64_t > &partitionindex, std::map< int64_t, std::pair< int64_t, int64_t > > &skeleton)
Define the partitioning information of the MHM mesh.
int HasSubElement()
Return 1 if the element has subelements along side.
REAL val(STATE &number)
Returns value of the variable.
Definition: pzartdiff.h:23
TPZGeoElSide Neighbour() const
Definition: pzgeoel.h:754
int WrapMaterialId(TPZGeoElSide gelside)
Return the wrap material id (depends on being boundary, neighbour of skeleton or interior.
TPZGeoMesh * Mesh() const
Returns the mesh to which the element belongs.
Definition: pzgeoel.h:220
void SetMaterial(TPZFMatrix< STATE > &xkin, TPZFMatrix< STATE > &xcin, TPZFMatrix< STATE > &xbin, TPZFMatrix< STATE > &xfin)
Definition: pzmat1dlin.h:66
int fSkeletonWrapMatId
material index of the skeleton wrap
virtual int NSides() const =0
Returns the number of connectivities of the element.
std::map< TPZCompMesh *, TPZManVector< int64_t > > fConnectToSubDomainIdentifier
geometric index of the connects - subdomain where the connect will be internal
virtual void Divide(TPZVec< TPZGeoEl *> &pv)
Divides the element and puts the resulting elements in the vector.
Definition: pzgeoel.h:742
void CreateInternalElements()
will create the internal elements, one coarse element at a time
void TransferToMultiphysics()
transform the computational mesh into a multiphysics 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
virtual void LoadElementReference()
Loads the geometric element reference.
Definition: pzcompel.cpp:601
virtual bool IsSkeletonMatid(int matid)
Return true if the material id is related to a skeleton.
void CreateDisconnectedElements(bool create)
Determine if the mesh will be created with disconnected elements After the mesh is created...
static void AddConnects(TPZVec< TPZCompMesh *> &cmeshVec, TPZCompMesh *MFMesh)
It has the declaration of the TPZMultiphysicsCompEl class.
TPZAutoPointer< TPZRefPattern > SideRefPattern(int side)
void SetDefaultOrder(int order)
Definition: pzcmesh.h:403
TPZManVector< int64_t > fGeoToMHMDomain
vector of coarse domain index associated with each geometric element
int fPressureSkeletonMatId
material id associated with the skeleton elements in a hybrid context
This abstract class defines the behaviour which each derived class needs to implement.
Definition: TPZMaterial.h:39
static void CreateInterfaces(TPZCompMesh &cmesh, const std::set< int > &MaterialIDs)
Creates the interface elements.
virtual TPZGeoEl * SubElement(int is) const =0
Returns a pointer to the subelement is.
Contains the TPZBndCond class which implements a boundary condition for TPZMaterial objects...
unsigned char LagrangeMultiplier() const
Access method to return the indication whether the connect is associated with a pressure lagrange mul...
Definition: pzconnect.h:230
void SetAllCreateFunctionsHDiv(int meshdim)
Create an approximation space with HDiv elements.
TPZCompEl * CreateCompEl(TPZGeoEl *gel, int64_t &index)
Create a computational element based on the geometric element.
Definition: pzcmesh.h:462
int64_t size() const
Returns the number of elements of the vector.
Definition: pzvec.h:196
int fInternalWrapMatId
material index of the internal wrap
TPZCompEl * Element(int64_t iel)
Definition: pzcmesh.h:185
void AddBoundaryInterfaceElements()
Add the boundary interface elements to the computational mesh.
int fLagrangeMatIdLeft
material id associated with the lagrange multiplier elements
TPZCreateApproximationSpace & ApproxSpace()
Definition: pzcmesh.h:498
virtual void BuildComputationalMesh(bool usersubstructure)
Create all data structures for the computational mesh.
bool fSwitchLagrangeSign
flag to indicate whether the lagrange multipliers should switch signal
void Push(const T object)
Pushes a copy of the object on the stack.
Definition: pzstack.h:80
f
Definition: test.py:287
int DecrementNumInterfaces()
Decrement number of TPZInterfaceElement pointing to this.
Definition: pzgeoel.h:105
void PrintDiagnostics(std::ostream &out)
Print diagnostics.
void SetTotalOrderShape()
Set total order shape functions.
virtual void Print(std::ostream &out=std::cout) const
Print the information of the grid to an ostream.
Definition: pzgmesh.cpp:130
virtual void InsertPeriferalMaterialObjects()
Insert material objects that do not perform any actual computation.
Defines the behaviour of all geometric elements. GeometryTPZGeoEl is the common denominator for all g...
Definition: pzgeoel.h:43
void PrintSubdomain(int64_t elindex, std::ostream &out)
print the diagnostics for a subdomain
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
int fBoundaryWrapMatId
material index of the boundary wrap
void SetAllCreateFunctionsDiscontinuous()
Definition: pzcmesh.h:503
Implements a group of computational elements as a mesh and an element. Computational Mesh...
Definition: pzsubcmesh.h:36
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
void DivideWrap(TPZGeoEl *wrapelement)
Divide the wrap element while it has divided neighbours.
Contains declaration of TPZInterfaceElement class which computes the contribution over an interface b...
TPZCompElSide & LeftElementSide()
Returns left neighbor.
virtual void ExpandSolution()
Adapt the solution vector to new block dimensions.
Definition: pzcmesh.cpp:396
#define LOGPZ_DEBUG(A, B)
Define log for debug info.
Definition: pzlog.h:87
TPZCompMesh * Mesh() const
Return a pointer to the grid of the element.
Definition: pzcompel.cpp:288
void AddBoundaryElements()
Add the boundary elements to the computational mesh.
void DefinePartitionbyCoarseIndices(TPZVec< int64_t > &coarseindices)
Define the MHM partition by the coarse element indices.
int Dimension() const
Returns the dimension of the simulation.
Definition: pzcmesh.h:148
Contains the declaration of the TPZBuildmultiphysicsMesh class.
void SetReference(TPZGeoMesh *gmesh)
Sets the geometric reference mesh.
Definition: pzcmesh.h:727
virtual void ComputeNodElCon()
Compute the number of elements connected to each connect object.
Definition: pzcmesh.cpp:668
void SetReference(int64_t referenceindex)
Definition: pzcompel.h:164
Contains the declaration of multiphysic interface class.
int NumInterfaces()
Returns number of TPZInterfaceElement pointing to this.
Definition: pzgeoel.h:94
int64_t InternalIndex(int64_t IndexinFather)
return the index in the subcompmesh of a connect with index within the father
void CreateInterfaceElements()
will create the interface elements between the internal elements and the skeleton ...
TPZMaterial * FindMaterial(int id)
Find the material with identity id.
Definition: pzcmesh.cpp:297
TPZCompEl * Reference() const
Return a pointer to the element referenced by the geometric element.
Definition: pzgeoel.h:750
unsigned int NShape() const
Definition: pzconnect.h:151
int64_t Rows() const
Returns number of rows.
Definition: pzmatrix.h:803
virtual TPZGeoEl * CreateBCGeoEl(int side, int bc)=0
Method which creates a geometric element on the side of an existing element.
TPZAutoPointer< TPZCompMesh > fCMeshConstantPressure
computational mesh to represent the constant states
TPZAutoPointer< TPZCompMesh > fPressureFineMesh
computational mesh to contain the pressure elements
void SetAllCreateFunctionsContinuous()
Create continuous approximation spaces.
std::map< int64_t, int64_t > fMHMtoSubCMesh
indices of the geometric elements which define the skeleton mesh and their corresponding subcmesh ind...
void Print(std::ostream &out)
print the data structure
TPZCompElSide & RightElementSide()
Returns right neighbor.
int64_t NConnects() const
Number of connects allocated including free nodes.
Definition: pzcmesh.h:163
TPZAdmChunkVector< TPZConnect > & ConnectVec()
Return a reference to the connect pointers vector.
Definition: pzcmesh.h:198
int64_t Index() const
Returns element index of the mesh fELementVec list.
Definition: pzcompel.h:821
TPZAutoPointer< TPZGeoMesh > fGMesh
geometric mesh used to create the computational mesh
Contains the TPZRefPattern class which defines the topology of the current refinement pattern to a me...
virtual TPZConnect & Connect(int i) const
Returns a pointer to the ith node.
Definition: pzcompel.cpp:298
int64_t ConnectIndex(int side=0) const override
Returns the connect index from the element.
void SetDimModel(int dim)
Set de dimension of the domain of the problem.
Definition: pzcmesh.h:139
TPZGeoEl * CreatedElement()
Recovers pointer to the geometric element created.
Definition: pzgeoelbc.h:39
virtual void CreateSkeletonElements()
will create dim-1 geometric elements on the interfaces between the coarse element indices ...
virtual void SetMultiplier(STATE mult)
void CreateLagrangeMultiplierMesh()
create the lagrange multiplier mesh, one element for each subdomain
std::map< int,TPZMaterial *> & MaterialVec()
Returns a reference to the material pointers vector.
Definition: pzcmesh.h:203
void ConnectedCompElementList(TPZStack< TPZCompElSide > &elsidevec, int onlyinterpolated, int removeduplicates)
Returns all connected computational elements to the current element if onlyinterpolated == 1 only e...
virtual int64_t ConnectIndex(int i) const =0
Returns the index of the ith connectivity of the element.
Computes the contribution over an interface between two discontinuous elements. Computational Element...
virtual int HasSubElement() const =0
Return 1 if the element has subelements.
Implements the interfaces for TPZCompElDisc, TPZInterfaceElement and TPZInterpolatedElement. Computational element.
void ConnectedElements(int64_t skeleton, std::pair< int64_t, int64_t > &leftright, std::map< int64_t, std::list< TPZCompElSide > > &ellist)
identify connected elements to the skeleton elements
virtual void HybridizeSkeleton(int skeletonmatid, int pressurematid)
virtual int NConnects() const =0
Returns the number of nodes of the element.
TPZGeoEl * Element() const
Definition: pzgeoelside.h:162
Structure to help the construction of geometric elements along side of a given geometric element...
Definition: pzgeoelbc.h:21
int fNState
number of state variables
class oriented towards the creation of multiscale hybrid meshes - YES
virtual TPZBndCond * CreateBC(TPZMaterial *reference, int id, int typ, TPZFMatrix< STATE > &val1, TPZFMatrix< STATE > &val2)
Creates an object TPZBndCond derived of TPZMaterial.
virtual void SetSideOrient(int side, int sideorient)
It set the normal orientation of the element by the side. Only side that has dimension equal to my di...
Contains declaration of TPZSubCompMesh class which implements a group of computational elements as a ...
static TPZAutoPointer< TPZRefPattern > PerfectMatchRefPattern(TPZGeoEl *gel, TPZVec< int > &sidestorefine)
Returns the refpattern that matches the sides refinement intensity and midnodes coordinates with resp...
void SetSubdomain(TPZCompEl *cel, int64_t subdomain)
associates the connects of an element with a subdomain
int InsertMaterialObject(TPZMaterial *mat)
Insert a material object in the datastructure.
Definition: pzcmesh.cpp:287
static void SetTotalOrderShape(TPZCompMesh *cmesh)
Set total order shape functions for all Discontinuous elements in cmesh.
T Pop()
Retrieve an object from the stack.
Definition: pzstack.h:87
virtual void CleanUpUnconnectedNodes()
Delete the nodes which have no elements connected to them.
Definition: pzcmesh.cpp:498
virtual int Dimension() const =0
Returns the dimension of the element.
TPZCompEl * Element() const
Gives a pointer to the reference computational element.
Definition: pzcompel.h:675
Contains the TPZMat1dLin class which implements a one-dimensional linear problem. ...
TPZCompEl * CreateCompEl(TPZGeoEl *gel, TPZCompMesh &mesh, int64_t &index) const
Create a computational element using the function pointer for the topology.
int Dimension()
Get Dimension.
Definition: pzgmesh.h:291
int64_t fGlobalSystemWithLocalCondensationSize
number of equations considering local condensation
TPZGeoEl * Reference() const
Return a pointer to the corresponding geometric element if such exists, return 0 otherwise.
Definition: pzcompel.cpp:1137
TPZCompEl * LeftElement() const
Returns the left element from the element interface.
TPZCompElSide Reference() const
Returns a pointer to the elementside referenced by the geometric elementside.
virtual REAL SideArea(int side)
Returns the area from the face.
Definition: pzgeoel.cpp:1064
This class implements a geometric mesh for the pz environment. Geometry.
Definition: pzgmesh.h:48
MProblemType fProblemType
Variable defining the type of problem.
virtual int64_t ConnectIndex(int i) const override
Returns the connection index i.
Definition: pzsubcmesh.cpp:346
This class implements a stack object. Utility.
Definition: pzcheckmesh.h:14
int Dimension() const
the dimension associated with the element/side
void ResetReference()
Reset the element referenced by the geometric element to NULL.
Definition: pzgeoel.h:431
Computes the contribution over an interface between two discontinuous elements. Computational Element...
virtual void MakeAllInternal() override
Makes all mesh connections internal mesh connections.
Definition: pzsubcmesh.cpp:602
Implements computational mesh. Computational Mesh.
Definition: pzcmesh.h:47
TPZAdmChunkVector< TPZCompEl * > & ElementVec()
Returns a reference to the element pointers vector.
Definition: pzcmesh.h:183
int NElConnected() const
Returns fNElConnected.
Definition: pzconnect.h:264
int Side() const
Definition: pzgeoelside.h:169
TPZCompMesh * CriaMalhaTemporaria()
will create a computational mesh using the coarse element indexes and its interface elements ...
void SetMaterialId(int id)
Sets the material index of the element.
Definition: pzgeoel.h:395
void CreateWrap(TPZGeoElSide gelside)
CreateWrapMesh of a given material id.
virtual void SetRefPattern(TPZAutoPointer< TPZRefPattern >)
Defines the refinement pattern. It&#39;s used only in TPZGeoElRefPattern objects.
Definition: pzgeoel.cpp:1647
int Side() const
Returns the side index.
Definition: pzcompel.h:688
TPZCompEl * RightElement() const
Returns the right element from the element interface.
int fpOrderSkeleton
interpolation order of the skeleton elements
void SetAnalysisSkyline(int numThreads, int preconditioned, TPZAutoPointer< TPZGuiInterface > guiInterface)
Condense the internal equations using a skyline symetric matrix the preconditioned argument indicates...
This class implements a discontinuous element (for use with discontinuous Galerkin). Computational Element.
Definition: TPZCompElDisc.h:35
int64_t fNumeq
number of equations of the global system
void JoinSubdomains(TPZVec< TPZCompMesh *> &meshvec, TPZCompMesh *multiphysicsmesh)
Subdomains are identified by computational mesh, this method will join.
void InitializeBlock()
Resequence the block object, remove unconnected connect objects and reset the dimension of the soluti...
Definition: pzcmesh.cpp:391
Implements a one dimensional linear problem.
Definition: pzmat1dlin.h:25
std::map< int64_t, std::pair< int64_t, int64_t > > fInterfaces
indices of the skeleton elements and their left/right partition indexes
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 SetAllCreateFunctionsMultiphysicElem()
Definition: pzcmesh.h:542
virtual int NSubElements() const =0
Returns the number of subelements of the element independent of the fact whether the element has alr...
TPZGeoEl * Father() const
Computes the normal vectors needed for forming HDiv vector valued shape functions.
Definition: pzgeoel.cpp:2574
int HasWrapNeighbour(TPZGeoElSide gelside)
Verify if the element side contains a wrap neighbour.
TPZFMatrix< STATE > & Solution()
Access the solution vector.
Definition: pzcmesh.h:219
void SubStructure()
substructure the mesh
Contains the TPZRefPatternTools class which defines tools of pattern.
Non abstract class which implements full matrices with preallocated storage with (N+1) entries...
Definition: pzfmatrix.h:716
Implements an L2 projection to constant solution values.
virtual void Print(std::ostream &out=std::cout) const
Prints mesh data.
Definition: pzcmesh.cpp:236
TPZAdmChunkVector< TPZGeoEl * > & ElementVec()
Methods for handling pzlists.
Definition: pzgmesh.h:138
virtual int NConnects() const override
Returns the number of connections.
Definition: pzsubcmesh.cpp:342