NeoPZ
TPZHybridizeHDiv.cpp
Go to the documentation of this file.
1 //
2 // TPZHybridizeHDiv.cpp
3 // ErrorEstimate
4 //
5 // Created by Philippe Devloo on 16/05/18.
6 //
7 
8 #include "TPZHybridizeHDiv.h"
9 #include "pzconnect.h"
10 #include "pzcmesh.h"
11 #include "pzcompel.h"
12 #include "TPZMaterial.h"
13 #include "pzmat1dlin.h"
14 #include "pzmat2dlin.h"
15 #include "pzelementgroup.h"
16 #include "pzcondensedcompel.h"
17 #include "pzintel.h"
18 #include "pzgeoelbc.h"
21 #include "pzgeoelside.h"
22 #include "pztrnsform.h"
23 #include "tpzintpoints.h"
24 #include "TPZLagrangeMultiplier.h"
25 #include "TPZNullMaterial.h"
26 
28 
29 #include <algorithm>
30 
31 using namespace std;
32 
34  ComputePeriferalMaterialIds(meshvec_Hybrid);
35  ComputeNState(meshvec_Hybrid);
36 }
37 
39  if (meshvec_Hybrid.size() > 1 && meshvec_Hybrid[1]->NMaterials() > 0) {
40  fNState = meshvec_Hybrid[1]->MaterialVec().begin()->second->NStateVariables();
41  }
42 }
43 
45  int maxMatId = std::numeric_limits<int>::min();
46  for (auto &mesh : meshvec_Hybrid) {
47 
48  if(!mesh) continue;
49 
50  for (auto &mat : mesh->MaterialVec()) {
51  maxMatId = std::max(maxMatId, mat.first);
52  }
53  }
54  if(meshvec_Hybrid.size())
55  {
56 
57 
58  TPZGeoMesh *gmesh = meshvec_Hybrid[1]->Reference();
59  int64_t nel = gmesh->NElements();
60  for(int64_t el=0; el<nel; el++)
61  {
62  TPZGeoEl *gel = gmesh->Element(el);
63  if(gel) maxMatId = std::max(maxMatId,gel->MaterialId());
64  }
65  }
66  if (maxMatId == std::numeric_limits<int>::min()) {
67  maxMatId = 0;
68  }
69  fHDivWrapMatid = maxMatId + 1;
70  fLagrangeInterface = maxMatId + 2;
71  fInterfaceMatid = maxMatId + 3;
72 }
73 
75 
76 std::tuple<int64_t, int> TPZHybridizeHDiv::SplitConnects(const TPZCompElSide &left, const TPZCompElSide &right, TPZVec<TPZCompMesh *> &meshvec_Hybrid) {
77  if (fHDivWrapMatid == 0 || fLagrangeInterface == 0) {
78  std::cerr << "Using uninitialized TPZHybridizeHDiv object. You need to call ComputePeriferalMaterialIds function first!" << std::endl;
79  DebugStop();
80  }
81  TPZCompMesh *fluxmesh = meshvec_Hybrid[0];
82  //TPZCompMesh *pressuremesh = meshvec[1];
83  //TPZGeoMesh *gmesh = fluxmesh->Reference();
84  TPZGeoElSide gleft(left.Reference());
85  TPZGeoElSide gright(right.Reference());
86  TPZInterpolatedElement *intelleft = dynamic_cast<TPZInterpolatedElement *> (left.Element());
87  TPZInterpolatedElement *intelright = dynamic_cast<TPZInterpolatedElement *> (right.Element());
88  intelleft->SetSideOrient(left.Side(), 1);
89  intelright->SetSideOrient(right.Side(), 1);
90  TPZStack<TPZCompElSide> equalright;
91  TPZConnect &cleft = intelleft->SideConnect(0, left.Side());
92 
93  if (cleft.HasDependency()) {
94  // check whether the wrap of the large element was already created
95  gright.EqualLevelCompElementList(equalright,1,0);
96  // only one wrap element should exist
97 #ifdef PZDEBUG
98  if(equalright.size() > 1)
99  {
100  DebugStop();
101  }
102  if(equalright.size()==1)
103  {
104  TPZGeoEl *equalgel = equalright[0].Element()->Reference();
105  if(equalgel->Dimension() != fluxmesh->Dimension()-1)
106  {
107  DebugStop();
108  }
109  }
110 #endif
111  // reset the reference of the wrap element
112  if(equalright.size()) equalright[0].Element()->Reference()->ResetReference();
113  cleft.RemoveDepend();
114  }
115  else
116  {
117  int64_t index = fluxmesh->AllocateNewConnect(cleft);
118  TPZConnect &newcon = fluxmesh->ConnectVec()[index];
119  cleft.DecrementElConnected();
120  newcon.ResetElConnected();
121  newcon.IncrementElConnected();
122  newcon.SetSequenceNumber(fluxmesh->NConnects() - 1);
123 
124  int rightlocindex = intelright->SideConnectLocId(0, right.Side());
125  intelright->SetConnectIndex(rightlocindex, index);
126  }
127  int sideorder = cleft.Order();
128  fluxmesh->SetDefaultOrder(sideorder);
129  // create HDivBound on the sides of the elements
130  TPZCompEl *wrap1, *wrap2;
131  {
132  intelright->Reference()->ResetReference();
133  intelleft->LoadElementReference();
134  intelleft->SetPreferredOrder(sideorder);
135  TPZGeoElBC gbc(gleft, fHDivWrapMatid);
136  int64_t index;
137  wrap1 = fluxmesh->ApproxSpace().CreateCompEl(gbc.CreatedElement(), *fluxmesh, index);
138  if(cleft.Order() != sideorder)
139  {
140  DebugStop();
141  }
142  TPZInterpolatedElement *intel = dynamic_cast<TPZInterpolatedElement *> (wrap1);
143  int wrapside = gbc.CreatedElement()->NSides() - 1;
144  intel->SetSideOrient(wrapside, 1);
145  intelleft->Reference()->ResetReference();
146  wrap1->Reference()->ResetReference();
147  }
148  // if the wrap of the large element was not created...
149  if(equalright.size() == 0)
150  {
151  intelleft->Reference()->ResetReference();
152  intelright->LoadElementReference();
153  TPZConnect &cright = intelright->SideConnect(0,right.Side());
154  int rightprevorder = cright.Order();
155  intelright->SetPreferredOrder(cright.Order());
156  TPZGeoElBC gbc(gright, fHDivWrapMatid);
157  int64_t index;
158  wrap2 = fluxmesh->ApproxSpace().CreateCompEl(gbc.CreatedElement(), *fluxmesh, index);
159  if(cright.Order() != rightprevorder)
160  {
161  DebugStop();
162  }
163  TPZInterpolatedElement *intel = dynamic_cast<TPZInterpolatedElement *> (wrap2);
164  int wrapside = gbc.CreatedElement()->NSides() - 1;
165  intel->SetSideOrient(wrapside, 1);
166  intelright->Reference()->ResetReference();
167  wrap2->Reference()->ResetReference();
168  }
169  else
170  {
171  wrap2 = equalright[0].Element();
172  }
173  wrap1->LoadElementReference();
174  wrap2->LoadElementReference();
175  int64_t pressureindex;
176  int pressureorder;
177  {
178  TPZGeoElBC gbc(gleft, fLagrangeInterface);
179  pressureindex = gbc.CreatedElement()->Index();
180  pressureorder = sideorder;
181  }
182  intelleft->LoadElementReference();
183  intelright->LoadElementReference();
184  return std::make_tuple(pressureindex, pressureorder);
185 }
186 
188 // else return 0
189 
191  bool isrestrained = false;
192  {
193  TPZConnect &c = intel->SideConnect(0, side);
194  if (c.HasDependency()) {
195  isrestrained = true;
196  }
197  }
198  TPZGeoEl *gel = intel->Reference();
199  TPZGeoElSide gelside(gel, side);
200 
201  if (isrestrained == true) {
203  TPZCompElSide celside = gelside.LowerLevelCompElementList2(1);
204  if (!celside) DebugStop();
205  TPZGeoEl *neigh = celside.Element()->Reference();
207  if (neigh->Dimension() != gel->Dimension()) {
208  DebugStop();
209  }
210  return celside;
211  } else {
212  // if the connect is not restrained
213  // - there should be only one neighbour
214  // if there is more than one neighbour the element side has already been hybridized
215  // - the neighbour should be of the same dimension
216  // if the neighbour is of lower dimension it is a boundary element
217  TPZStack<TPZCompElSide> celstack;
218  gelside.EqualLevelCompElementList(celstack, 1, 0);
219  if (celstack.size() == 1) {
220  TPZGeoEl *neigh = celstack[0].Element()->Reference();
221  if (neigh->Dimension() == gel->Dimension()) {
222  return celstack[0];
223  }
224  }
225  }
226  return TPZCompElSide();
227 }
228 
229 
231 
233  InsertPeriferalMaterialObjects(meshvec_Hybrid);
234 
235  TPZCompMesh *fluxmesh = meshvec_Hybrid[0];
236  TPZGeoMesh *gmesh = fluxmesh->Reference();
237  int dim = gmesh->Dimension();
238  gmesh->ResetReference();
239  fluxmesh->LoadReferences();
240  int64_t nel = fluxmesh->NElements();
241  std::list<std::tuple<int64_t, int> > pressures;
242  for (int64_t el = 0; el < nel; el++) {
243  TPZCompEl *cel = fluxmesh->Element(el);
244  TPZInterpolatedElement *intel = dynamic_cast<TPZInterpolatedElement *> (cel);
245  if (!intel || intel->Reference()->Dimension() != dim) {
246  continue;
247  }
248  // loop over the side of dimension dim-1
249  TPZGeoEl *gel = intel->Reference();
250  for (int side = gel->NCornerNodes(); side < gel->NSides() - 1; side++) {
251  if (gel->SideDimension(side) != dim - 1) {
252  continue;
253  }
254  TPZCompElSide celside(intel, side);
255  TPZCompElSide neighcomp = RightElement(intel, side);
256  if (neighcomp) {
257  pressures.push_back(SplitConnects(celside, neighcomp, meshvec_Hybrid));
258  }
259  }
260  }
261  fluxmesh->InitializeBlock();
262  fluxmesh->ComputeNodElCon();
263 
264  TPZCompMesh *pressuremesh = meshvec_Hybrid[1];
265  gmesh->ResetReference();
266  pressuremesh->SetDimModel(gmesh->Dimension()-1);
267  for (auto pindex : pressures) {
268  int64_t elindex;
269  int order;
270  std::tie(elindex, order) = pindex;
271  TPZGeoEl *gel = gmesh->Element(elindex);
272  int64_t celindex;
273  TPZCompEl *cel = pressuremesh->ApproxSpace().CreateCompEl(gel, *pressuremesh, celindex);
274  TPZInterpolatedElement *intel = dynamic_cast<TPZInterpolatedElement *> (cel);
275  TPZCompElDisc *intelDisc = dynamic_cast<TPZCompElDisc *> (cel);
276  if (intel){
277  intel->PRefine(order);
278 // intel->SetSideOrder(gel->NSides() - 1, order);
279  } else if (intelDisc) {
280  intelDisc->SetDegree(order);
281  intelDisc->SetTrueUseQsiEta();
282  } else {
283  DebugStop();
284  }
285  int n_connects = cel->NConnects();
286  for (int i = 0; i < n_connects; ++i) {
287  cel->Connect(i).SetLagrangeMultiplier(2);
288  }
289  gel->ResetReference();
290  }
291  pressuremesh->InitializeBlock();
292  pressuremesh->SetDimModel(gmesh->Dimension());
293 }
294 
296  if (fInterfaceMatid == 0) {
297  std::cerr << "Using uninitialized TPZHybridizeHDiv object. You need to call ComputePeriferalMaterialIds function first!" << std::endl;
298  DebugStop();
299  }
300  TPZCompMesh *pressuremesh = meshvec_Hybrid[1];
301  int dim = pressuremesh->Dimension();
302  TPZVec<TPZCompEl *> celpressure(pressuremesh->NElements(), 0);
303  for (int64_t el = 0; el < pressuremesh->NElements(); el++) {
304  TPZCompEl *cel = pressuremesh->Element(el);
305  if (cel && cel->Reference() && cel->Reference()->Dimension() == dim - 1) {
306  celpressure[el] = cel;
307  }
308  }
309  cmesh_Hybrid->Reference()->ResetReference();
310  cmesh_Hybrid->LoadReferences();
311  for (auto cel : celpressure) {
312  if (!cel) continue;
313  TPZStack<TPZCompElSide> celstack;
314  TPZGeoEl *gel = cel->Reference();
315  TPZCompEl *mphysics = gel->Reference();
316  TPZGeoElSide gelside(gel, gel->NSides() - 1);
317  TPZCompElSide celside = gelside.Reference();
318  gelside.EqualLevelCompElementList(celstack, 0, 0);
319  int count = 0;
320  for (auto &celstackside : celstack) {
321  if (celstackside.Reference().Element()->Dimension() == dim - 1) {
322  TPZGeoElBC gbc(gelside, fInterfaceMatid);
323  // check if the right side has a dependency
324  TPZCompEl *celneigh = celstackside.Element();
325  if (celneigh->NConnects() != 1) {
326  DebugStop();
327  }
328  int64_t index;
329  TPZMultiphysicsInterfaceElement *intface = new TPZMultiphysicsInterfaceElement(*cmesh_Hybrid, gbc.CreatedElement(), index, celside, celstackside);
330  count++;
331  }
332  }
333  if (count == 1)
334  {
335  TPZCompElSide clarge = gelside.LowerLevelCompElementList2(false);
336  if(!clarge) DebugStop();
337  TPZGeoElSide glarge = clarge.Reference();
338  if (glarge.Element()->Dimension() == dim) {
339  TPZGeoElSide neighbour = glarge.Neighbour();
340  while(neighbour != glarge)
341  {
342  if (neighbour.Element()->Dimension() < dim) {
343  break;
344  }
345  neighbour = neighbour.Neighbour();
346  }
347  if(neighbour == glarge) DebugStop();
348  glarge = neighbour;
349  }
350  clarge = glarge.Reference();
351  if(!clarge) DebugStop();
352  TPZGeoElBC gbc(gelside, fInterfaceMatid);
353 
354  int64_t index;
355  TPZMultiphysicsInterfaceElement *intface = new TPZMultiphysicsInterfaceElement(*cmesh_Hybrid, gbc.CreatedElement(), index, celside, clarge);
356  count++;
357  }
358  if (count != 2 && count != 0) {
359  DebugStop();
360  }
361  }
362  pressuremesh->InitializeBlock();
363 }
364 
366 {
367  CreateInterfaceElements(cmesh_Hybrid, cmesh_Hybrid->MeshVector());
368 }
369 
370 TPZCompMesh * TPZHybridizeHDiv::CreateMultiphysicsMesh(TPZCompMesh *cmesh_HDiv, TPZVec<TPZCompMesh *> &meshvector_Hybrid, double Lagrange_term_multiplier /* = 1. */) {
371  TPZGeoMesh *gmesh = cmesh_HDiv->Reference();
372  TPZCompMesh *cmesh_Hybrid = new TPZCompMesh(gmesh);
373  cmesh_HDiv->CopyMaterials(*cmesh_Hybrid);
374  InsertPeriferalMaterialObjects(cmesh_Hybrid, Lagrange_term_multiplier);
376  cmesh_Hybrid->AutoBuild();
377 
378  TPZBuildMultiphysicsMesh::AddElements(meshvector_Hybrid, cmesh_Hybrid);
379  TPZBuildMultiphysicsMesh::AddConnects(meshvector_Hybrid, cmesh_Hybrid);
380  cmesh_Hybrid->LoadReferences();
381  return cmesh_Hybrid;
382 }
383 
384 TPZCompMesh * TPZHybridizeHDiv::CreateMultiphysicsMesh(TPZMultiphysicsCompMesh *cmesh_HDiv, double Lagrange_term_multiplier /* = 1. */) {
385  TPZManVector<TPZCompMesh *, 3> meshvec_Hybrid(cmesh_HDiv->MeshVector().size(), 0);
386  for (int i = 0; i < cmesh_HDiv->MeshVector().size(); i++) {
387  meshvec_Hybrid[i] = cmesh_HDiv->MeshVector()[i]->Clone();
388  }
389  InsertPeriferalMaterialObjects(meshvec_Hybrid);
390  HybridizeInternalSides(meshvec_Hybrid);
391 
392  TPZGeoMesh *gmesh = cmesh_HDiv->Reference();
393  TPZMultiphysicsCompMesh *cmesh_Hybrid = new TPZMultiphysicsCompMesh(gmesh);
394  cmesh_HDiv->CopyMaterials(*cmesh_Hybrid);
395  InsertPeriferalMaterialObjects(cmesh_Hybrid, Lagrange_term_multiplier);
396 
397  TPZManVector<int,5> active(meshvec_Hybrid.size(),1);
398  cmesh_Hybrid->BuildMultiphysicsSpace(active, meshvec_Hybrid);
399  return cmesh_Hybrid;
400 }
401 
403 void TPZHybridizeHDiv::ReCreateMultiphysicsMesh(TPZMultiphysicsCompMesh *cmesh_HDiv, double Lagrange_term_multiplier)
404 {
405  TPZManVector<TPZCompMesh *, 3> meshvec_Hybrid = cmesh_HDiv->MeshVector();
406  InsertPeriferalMaterialObjects(cmesh_HDiv, Lagrange_term_multiplier);
407  InsertPeriferalMaterialObjects(meshvec_Hybrid);
408  TPZManVector<int> active = cmesh_HDiv->GetActiveApproximationSpaces();
409  HybridizeInternalSides(meshvec_Hybrid);
410  cmesh_HDiv->BuildMultiphysicsSpace(active, meshvec_Hybrid);
411 
412 }
413 
415 // elementgroup[el] = index of the element with which the element should be grouped
416 // this method only gives effective result for hybridized hdiv meshes
418 {
419  int64_t nel = cmesh->NElements();
420  elementgroup.Resize(nel, -1);
421  elementgroup.Fill(-1);
422  int64_t nconnects = cmesh->NConnects();
423  TPZVec<int64_t> groupindex(nconnects, -1);
424  int dim = cmesh->Dimension();
425  for (TPZCompEl *cel : cmesh->ElementVec()) {
426  if (!cel || !cel->Reference() || cel->Reference()->Dimension() != dim) {
427  continue;
428  }
429  elementgroup[cel->Index()] = cel->Index();
430  TPZStack<int64_t> connectlist;
431  cel->BuildConnectList(connectlist);
432  for (auto cindex : connectlist) {
433 #ifdef PZDEBUG
434  if (groupindex[cindex] != -1) {
435  DebugStop();
436  }
437 #endif
438  groupindex[cindex] = cel->Index();
439  }
440  }
441  // std::cout << "Groups of connects " << groupindex << std::endl;
442  for (TPZCompEl *cel : cmesh->ElementVec()) {
443  if (!cel || !cel->Reference()) {
444  continue;
445  }
446  TPZStack<int64_t> connectlist;
447  cel->BuildConnectList(connectlist);
448 // std::cout << "Analysing element " << cel->Index();
449  int64_t groupfound = -1;
450  for (auto cindex : connectlist) {
451  if (groupindex[cindex] != -1) {
452  elementgroup[cel->Index()] = groupindex[cindex];
453  if(groupfound != -1 && groupfound != groupindex[cindex])
454  {
455  DebugStop();
456  }
457 // if(groupfound == -1)
458 // {
459 // std::cout << " added to " << groupindex[cindex];
460 // }
461 
462  groupfound = groupindex[cindex];
463  }
464  }
465 // std::cout << std::endl;
466  }
467 
468 }
469 
470 
471 
473 
475 
476  int64_t nel = cmesh->NElements();
477  TPZVec<int64_t> groupnumber(nel,-1);
479  AssociateElements(cmesh, groupnumber);
480  std::map<int64_t, TPZElementGroup *> groupmap;
481  // std::cout << "Groups of connects " << groupindex << std::endl;
482  for (int64_t el = 0; el<nel; el++) {
483  int64_t groupnum = groupnumber[el];
484  if(groupnum == -1) continue;
485  auto iter = groupmap.find(groupnum);
486  if (groupmap.find(groupnum) == groupmap.end()) {
487  int64_t index;
488  TPZElementGroup *elgr = new TPZElementGroup(*cmesh,index);
489  groupmap[groupnum] = elgr;
490  elgr->AddElement(cmesh->Element(el));
491  }
492  else
493  {
494  iter->second->AddElement(cmesh->Element(el));
495  }
496 // std::cout << std::endl;
497  }
498  cmesh->ComputeNodElCon();
499  nel = cmesh->NElements();
500  for (int64_t el = 0; el < nel; el++) {
501  TPZCompEl *cel = cmesh->Element(el);
502  TPZElementGroup *elgr = dynamic_cast<TPZElementGroup *> (cel);
503  if (elgr) {
505  cond->SetKeepMatrix(false);
506  }
507  }
508 }
509 
511 
513  if (fLagrangeInterface == 0 || fHDivWrapMatid == 0) {
514  std::cerr << "Using uninitialized TPZHybridizeHDiv object. You need to call ComputePeriferalMaterialIds function first!" << std::endl;
515  DebugStop();
516  }
517 
518 
519  TPZCompMesh *pressuremesh = meshvec_Hybrid[1];
520  int dim = pressuremesh->Dimension();
521 
522  if (!pressuremesh->FindMaterial(fLagrangeInterface)) {
523  auto matPerif = new TPZNullMaterial(fLagrangeInterface);
524  matPerif->SetDimension(dim-1);
525  matPerif->SetNStateVariables(fNState);
526  pressuremesh->InsertMaterialObject(matPerif);
527  }
528 
529  if(meshvec_Hybrid[0]!=NULL){
530 
531  TPZCompMesh *fluxmesh = meshvec_Hybrid[0];
532  if (!fluxmesh->FindMaterial(fHDivWrapMatid)) {
533  auto matPerif = new TPZNullMaterial(fHDivWrapMatid);
534  matPerif->SetDimension(dim-1);
535  matPerif->SetNStateVariables(fNState);
536  fluxmesh->InsertMaterialObject(matPerif);
537  }
538  }
539 }
540 
542 
543 void TPZHybridizeHDiv::InsertPeriferalMaterialObjects(TPZCompMesh *cmesh_Hybrid, double Lagrange_term_multiplier /* = 1. */) {
544  if (fLagrangeInterface == 0 || fHDivWrapMatid == 0 || fInterfaceMatid == 0) {
545  std::cerr << "Using uninitialized TPZHybridizeHDiv object. You need to call ComputePeriferalMaterialIds function first!" << std::endl;
546  DebugStop();
547  }
548  TPZFNMatrix<1, STATE> xk(fNState, fNState, 0.), xb(fNState, fNState, 0.), xc(fNState, fNState, 0.), xf(fNState, 1, 0.);
549  int dim = cmesh_Hybrid->Dimension();
550 
551  if (!cmesh_Hybrid->FindMaterial(fLagrangeInterface)) {
552  std::cout<<"LagrangeInterface MatId "<<fLagrangeInterface<<std::endl;
553  auto matPerif = new TPZNullMaterial(fLagrangeInterface);
554  matPerif->SetNStateVariables(fNState);
555  matPerif->SetDimension(dim-1);
556  cmesh_Hybrid->InsertMaterialObject(matPerif);
557  }
558  if (!cmesh_Hybrid->FindMaterial(fHDivWrapMatid)) {
559  std::cout<<"HDivWrapMatid MatId "<<fHDivWrapMatid<<std::endl;
560  auto matPerif = new TPZNullMaterial(fHDivWrapMatid);
561  matPerif->SetNStateVariables(fNState);
562  matPerif->SetDimension(dim-1);
563  cmesh_Hybrid->InsertMaterialObject(matPerif);
564  }
565  if (!cmesh_Hybrid->FindMaterial(fInterfaceMatid)) {
566 
567  std::cout<<"InterfaceMatid MatId "<<fInterfaceMatid<<std::endl;
568  TPZLagrangeMultiplier *matleft = new TPZLagrangeMultiplier(fInterfaceMatid, dim - 1, fNState);
569  matleft->SetMultiplier(Lagrange_term_multiplier);
570  cmesh_Hybrid->InsertMaterialObject(matleft);
571  }
572 }
573 
574 std::tuple<TPZCompMesh*, TPZVec<TPZCompMesh*> > TPZHybridizeHDiv::Hybridize(TPZCompMesh* cmesh_HDiv, TPZVec<TPZCompMesh*>& meshvec_HDiv, bool group_elements, double Lagrange_term_multiplier /* = 1. */) {
575  TPZManVector<TPZCompMesh *, 3> meshvec_Hybrid(meshvec_HDiv.size(), 0);
576  for (int i = 0; i < meshvec_HDiv.size(); i++) {
577  meshvec_Hybrid[i] = meshvec_HDiv[i]->Clone();
578  }
579  ComputePeriferalMaterialIds(meshvec_Hybrid);
580  ComputeNState(meshvec_Hybrid);
582  InsertPeriferalMaterialObjects(meshvec_Hybrid);
583  HybridizeInternalSides(meshvec_Hybrid);
584  TPZCompMesh *cmesh_Hybrid = CreateMultiphysicsMesh(cmesh_HDiv, meshvec_Hybrid, Lagrange_term_multiplier);
585  CreateInterfaceElements(cmesh_Hybrid, meshvec_Hybrid);
586  if (group_elements){
587  GroupandCondenseElements(cmesh_Hybrid);
588  }
589  return std::make_tuple(cmesh_Hybrid, meshvec_Hybrid);
590 }
591 
593 TPZMultiphysicsCompMesh *TPZHybridizeHDiv::Hybridize(TPZMultiphysicsCompMesh *multiphysics, bool group_elements, double Lagrange_term_multiplier)
594 {
595  ComputePeriferalMaterialIds(multiphysics->MeshVector());
596  ComputeNState(multiphysics->MeshVector());
597 // InsertPeriferalMaterialObjects(multiphysics->MeshVector());
598 // HybridizeInternalSides(multiphysics->MeshVector());
599  TPZCompMesh *cmesh = CreateMultiphysicsMesh(multiphysics);
600  TPZMultiphysicsCompMesh *result = dynamic_cast<TPZMultiphysicsCompMesh *>(cmesh);
601  CreateInterfaceElements(result);
602  if(group_elements)
603  {
604  GroupandCondenseElements(result);
605  }
606  if(!result) DebugStop();
607  return result;
608 
609 }
610 
612 void TPZHybridizeHDiv::HybridizeGivenMesh(TPZMultiphysicsCompMesh &multiphysics, bool group_elements, double Lagrange_term_multiplier)
613 {
614  ComputePeriferalMaterialIds(multiphysics.MeshVector());
615  ComputeNState(multiphysics.MeshVector());
616  ReCreateMultiphysicsMesh(&multiphysics);
617  CreateInterfaceElements(&multiphysics);
618  if (group_elements) {
619  GroupandCondenseElements(&multiphysics);
620  }
621 }
622 
623 
624 
625 static void CompareFluxes(TPZCompElSide &left, TPZCompElSide &right, std::ostream &out)
626 {
627  TPZGeoElSide gleft = left.Reference();
628  TPZGeoElSide gright = right.Reference();
629  TPZTransform<REAL> trleft = gleft.Element()->SideToSideTransform(gleft.Side(),gleft.Element()->NSides()-1);
630  TPZTransform<REAL> trright = gright.Element()->SideToSideTransform(gright.Side(),gright.Element()->NSides()-1);
631  int sidedim = gleft.Dimension();
632  int meshdim = gleft.Element()->Mesh()->Dimension();
633  TPZTransform<REAL> tr(sidedim);
634  gleft.SideTransform3(gright,tr);
635  TPZIntPoints *intpts = gleft.Element()->CreateSideIntegrationRule(gleft.Side(),5);
636  TPZManVector<REAL,3> ptleft(sidedim,0.),ptright(sidedim,0.),ptleftvol(meshdim,0),ptrightvol(meshdim,0);
637  REAL weight;
638  int npoints = intpts->NPoints();
639  for(int ip = 0; ip<npoints; ip++)
640  {
641  intpts->Point(ip,ptleft,weight);
642  tr.Apply(ptleft,ptright);
643  trleft.Apply(ptleft,ptleftvol);
644  trright.Apply(ptright,ptrightvol);
645  TPZManVector<STATE,3> fluxleft(3,0.),fluxright(3,0.);
646  left.Element()->Solution(ptleftvol,0,fluxleft);
647  right.Element()->Solution(ptrightvol,0,fluxright);
648  TPZManVector<REAL,3> normal(3,0.);
649  {
650  TPZFNMatrix<9,REAL> axes(sidedim,3),jacobian(sidedim,sidedim),jacinv(sidedim,sidedim);
651  REAL detjac;
652  gleft.Jacobian(ptleft,jacobian,axes,detjac,jacinv);
653  normal[0] = axes(0,1)*axes(1,2)-axes(0,2)*axes(1,1);
654  normal[1] = -axes(0,0)*axes(1,2)+axes(0,2)*axes(1,0);
655  normal[2] = axes(0,0)*axes(1,1)-axes(0,1)*axes(1,0);
656  }
657  STATE fluxnormalleft = 0.,fluxnormalright = 0.;
658  for(int i=0; i<3; i++)
659  {
660  fluxnormalleft += fluxleft[i]*normal[i];
661  fluxnormalright += fluxright[i]*normal[i];
662  }
663  REAL diff = fabs(fluxnormalleft-fluxnormalright);
664  if(diff > 1.e-6)
665  {
666  TPZManVector<REAL,3> leftx(3),rightx(3);
667  gleft.X(ptleft,leftx);
668  gright.X(ptright,rightx);
669  out << "Left geo element index " << gleft.Element()->Index();
670  out << " Right geo element index " << gright.Element()->Index();
671  out << " xleft " << leftx << " xright " << rightx << std::endl;
672  out << " fluxleft " << fluxleft << std::endl;
673  out << " fluxright" << fluxright << std::endl;
674  out << "normal " << normal << std::endl;
675  out << "fluxnormalleft " << fluxnormalleft << std::endl;
676  out << "fluxnormalright " << fluxnormalright << std::endl;
677  }
678  }
679  delete intpts;
680 }
681 
684 {
685  int64_t nel = fluxmesh->NElements();
686  fluxmesh->Reference()->ResetReference();
687  fluxmesh->LoadReferences();
688  int meshdim = fluxmesh->Dimension();
689  for(int64_t el = 0; el<nel; el++)
690  {
691  TPZCompEl *cel = fluxmesh->Element(el);
692  TPZInterpolatedElement *intel = dynamic_cast<TPZInterpolatedElement *>(cel);
693  if(!intel) continue;
694  TPZGeoEl *gel = cel->Reference();
695  if(gel->Dimension() != meshdim) continue;
696  int nsides = gel->NSides();
697  for(int side=0; side<nsides; side++)
698  {
699  if(gel->SideDimension(side) != meshdim-1) continue;
700  TPZStack<TPZCompElSide> celsides;
701  TPZGeoElSide gelside(gel,side);
702  gelside.EqualLevelCompElementList(celsides,1,0);
703 
704  {
705  TPZCompElSide celneigh = gelside.LowerLevelCompElementList2(1);
706  if(celneigh)
707  {
708  celsides.push_back(celneigh);
709  celneigh.Reference().EqualLevelCompElementList(celsides,1,0);
710  }
711  }
712  TPZCompElSide celneighselect;
713  int nummatch = 0;
714  for(int i=0; i<celsides.size(); i++)
715  {
716  if(celsides[i].Reference().Element()->Dimension() == meshdim)
717  {
718  celneighselect = celsides[i];
719  nummatch++;
720  }
721  }
722  if(nummatch > 1) DebugStop();
723  TPZCompElSide celside(gelside.Reference());
724  if(celneighselect)
725  {
726  CompareFluxes(celside,celneighselect,out);
727  }
728  }
729  }
730 }
int64_t NElements() const
Number of computational elements allocated.
Definition: pzcmesh.h:169
TPZGeoMesh * Reference() const
Returns a pointer to the geometrical mesh associated.
Definition: pzcmesh.h:209
Material which implements a Lagrange Multiplier.
expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ fabs
Definition: tfadfunc.h:140
virtual void SetConnectIndex(int i, int64_t connectindex) override=0
Sets the node pointer of node i to nod.
TPZCompMesh * Reference() const
Returns the currently loaded computational grid.
Definition: pzgmesh.h:167
virtual int NPoints() const =0
Returns number of points for the cubature rule related.
void IncrementElConnected()
Increment fNElConnected.
Definition: pzconnect.h:260
Implements computational element and a side. Computational Element.
Definition: pzcompel.h:632
std::tuple< TPZCompMesh *, TPZVec< TPZCompMesh * > > Hybridize(TPZCompMesh *cmesh_Multiphysics, TPZVec< TPZCompMesh *> &meshvec_HDiv, bool group_elements=true, double Lagrange_term_multiplier=1.)
clones the atomic meshes in meshvec_HDiv and creates a multiphysics hybrid mesh
Represents a set of shape functions associated with a computational element/side. Computational Eleme...
Definition: pzconnect.h:30
Contains declaration of TPZGeoElSide class which represents an element and its side, and TPZGeoElSideIndex class which represents an TPZGeoElSide index.
int MaterialId() const
Returns the material index of the element.
Definition: pzgeoel.h:250
void DecrementElConnected()
Decrement fNElConnected.
Definition: pzconnect.h:262
void CreateInterfaceElements(TPZCompMesh *cmesh_Hybrid, TPZVec< TPZCompMesh *> &meshvec_Hybrid)
Create interface elements with material id InterfaceMatid.
static void AddElements(TPZVec< TPZCompMesh *> &cmeshVec, TPZCompMesh *MFMesh)
Creating multiphysic elements into mphysics computational mesh. Method to add elements in the mesh mu...
virtual int64_t AllocateNewConnect(int nshape, int nstate, int order)
Returns an index to a new connect.
Definition: pzcmesh.h:693
TPZGeoElSide Reference() const
Reference to the geometric element.
Definition: pzcompel.cpp:748
Contains declaration of TPZCompEl class which defines the interface of a computational element...
void ComputeNState(TPZVec< TPZCompMesh *> &meshvec_Hybrid)
Contains the declaration of the TPZElementGroup class, which implements an computational element whic...
virtual int NCornerNodes() const =0
Returns the number of corner nodes of the element.
void SetLagrangeMultiplier(unsigned char mult)
Set the connect as a pressure connect or not.
Definition: pzconnect.h:236
static void CompareFluxes(TPZCompElSide &left, TPZCompElSide &right, std::ostream &out)
int64_t NElements() const
Number of elements of the mesh.
Definition: pzgmesh.h:129
TPZCompElSide LowerLevelCompElementList2(int onlyinterpolated)
return the element/side pair which contains this/side and has a computational element associated ...
Utility class which represents an element with its side. The Geometric approximation classes Geometry...
Definition: pzgeoelside.h:83
Class which groups elements to characterize dense matrices.
TPZHybridizeHDiv()=default
Contains declaration of TPZGeoElBC class, it is a structure to help the construction of geometric ele...
TPZCompMesh * CreateMultiphysicsMesh(TPZCompMesh *cmesh_HDiv, TPZVec< TPZCompMesh *> &meshvec_Hybrid, double Lagrange_term_multiplier=1.)
create a multiphysics mesh for the hybrid formulation using the materials of another mesh and the giv...
TPZGeoElSide Neighbour() const
Definition: pzgeoel.h:754
TPZGeoMesh * Mesh() const
Returns the mesh to which the element belongs.
Definition: pzgeoel.h:220
virtual int NSides() const =0
Returns the number of connectivities of the element.
virtual int SideDimension(int side) const =0
Return the dimension of side.
void SideTransform3(TPZGeoElSide neighbour, TPZTransform<> &t)
Accumulates the transformations from the current element/side to the neighbour/side.
void EqualLevelCompElementList(TPZStack< TPZCompElSide > &elsidevec, int onlyinterpolated, int removeduplicates)
Returns all connected computational elements which have equal level to the current element...
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
void SetAllCreateFunctionsMultiphysicElem()
Create an approximation space based on multiphysics elements.
static void AddConnects(TPZVec< TPZCompMesh *> &cmeshVec, TPZCompMesh *MFMesh)
TPZConnect & SideConnect(int icon, int is)
Returns a pointer to the icon th connect object along side is.
Definition: pzintel.cpp:105
void SetDefaultOrder(int order)
Definition: pzcmesh.h:403
Abstract class defining integration rules. Numerical Integration.
Definition: tpzintpoints.h:19
virtual TPZIntPoints * CreateSideIntegrationRule(int side, int order)=0
Creates an integration rule for the topology of the corresponding side and able to integrate a polyno...
int64_t size() const
Returns the number of elements of the vector.
Definition: pzvec.h:196
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object reallocating the necessary storage, copying the existing objects to the new...
Definition: pzvec.h:373
TPZCompEl * Element(int64_t iel)
Definition: pzcmesh.h:185
unsigned char Order() const
Access function to return the order associated with the connect.
Definition: pzconnect.h:217
TPZCreateApproximationSpace & ApproxSpace()
Definition: pzcmesh.h:498
TPZVec< TPZCompMesh * > & MeshVector()
Get the vector of computational meshes.
Defines the behaviour of all geometric elements. GeometryTPZGeoEl is the common denominator for all g...
Definition: pzgeoel.h:43
TPZGeoEl * Element(int64_t iel)
Definition: pzgmesh.h:139
int64_t Index() const
Returns the index of the element within the element vector of the mesh.
Definition: pzgeoel.h:730
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
virtual int SideConnectLocId(int icon, int is) const override=0
Returns the local node number of icon along is.
void SetSequenceNumber(int64_t i)
Set the sequence number for the global system of equations of the connect object. ...
Definition: pzconnect.h:165
void X(TPZVec< REAL > &loc, TPZVec< REAL > &result) const
X coordinate of a point loc of the side.
Contains declaration of TPZConnect class which represents a set of shape functions associated with a ...
int Dimension() const
Returns the dimension of the simulation.
Definition: pzcmesh.h:148
Contains the declaration of the TPZBuildmultiphysicsMesh class.
virtual void ComputeNodElCon()
Compute the number of elements connected to each connect object.
Definition: pzcmesh.cpp:668
Contains the declaration of multiphysic interface class.
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
virtual void AutoBuild(const std::set< int > *MaterialIDs)
Creates the computational elements, and the degree of freedom nodes.
Definition: pzcmesh.cpp:308
int HasDependency() const
Returns whether exist dependecy information.
Definition: pzconnect.h:292
void ComputePeriferalMaterialIds(TPZVec< TPZCompMesh *> &meshvec_Hybrid)
compute material ids for the periferal material objects
Contains the TPZMat2dLin class which implements a bi-dimensional linear problem.
int64_t NConnects() const
Number of connects allocated including free nodes.
Definition: pzcmesh.h:163
void HybridizeGivenMesh(TPZMultiphysicsCompMesh &multiphysics, bool group_elements=true, double Lagrange_term_multiplier=1.)
make a hybrid mesh from a H(div) multiphysics mesh
TPZAdmChunkVector< TPZConnect > & ConnectVec()
Return a reference to the connect pointers vector.
Definition: pzcmesh.h:198
T * begin() const
Casting operator. Returns The fStore pointer.
Definition: pzvec.h:450
Class which implements an element which condenses the internal connects.
Contains declaration of TPZCompMesh class which is a repository for computational elements...
static void GroupandCondenseElements(TPZCompMesh *cmesh_Hybrid)
group and condense the elements
virtual TPZConnect & Connect(int i) const
Returns a pointer to the ith node.
Definition: pzcompel.cpp:298
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 SetMultiplier(STATE mult)
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
void HybridizeInternalSides(TPZVec< TPZCompMesh *> &meshvec_Hybrid)
split the connects between flux elements and create a dim-1 pressure element
void InsertPeriferalMaterialObjects(TPZVec< TPZCompMesh *> &meshvec_Hybrid)
insert the material objects for HDivWrap and LagrangeInterface in the atomic meshes ...
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...
int InsertMaterialObject(TPZMaterial *mat)
Insert a material object in the datastructure.
Definition: pzcmesh.cpp:287
virtual void SetPreferredOrder(int order) override=0
Sets the preferred interpolation order along a side.
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
virtual TPZTransform< REAL > SideToSideTransform(int sidefrom, int sideto)=0
Compute the transformation between the master element space of one side of an element to the master e...
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
static void AssociateElements(TPZCompMesh *cmesh, TPZVec< int64_t > &elementgroup)
Associate elements with a volumetric element.
TPZGeoEl * Reference() const
Return a pointer to the corresponding geometric element if such exists, return 0 otherwise.
Definition: pzcompel.cpp:1137
TPZCompElSide Reference() const
Returns a pointer to the elementside referenced by the geometric elementside.
This class implements a geometric mesh for the pz environment. Geometry.
Definition: pzgmesh.h:48
std::tuple< int64_t, int > SplitConnects(const TPZCompElSide &left, const TPZCompElSide &right, TPZVec< TPZCompMesh *> &meshvec_Hybrid)
split the connect between two neighbouring elements
static void VerifySolutionConsistency(TPZCompMesh *fluxmesh, std::ostream &out)
verify the consistency of the solution of the flux mesh
void ResetElConnected()
Initialize with zero fNElConnected.
Definition: pzconnect.h:258
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...
void Jacobian(TPZVec< REAL > &param, TPZFMatrix< REAL > &jacobian, TPZFMatrix< REAL > &axes, REAL &detjac, TPZFMatrix< REAL > &jacinv) const
Jacobian associated with the side of the element.
Implements computational mesh. Computational Mesh.
Definition: pzcmesh.h:47
TPZVec< int > & GetActiveApproximationSpaces()
Get the vector of active physics.
TPZAdmChunkVector< TPZCompEl * > & ElementVec()
Returns a reference to the element pointers vector.
Definition: pzcmesh.h:183
void PRefine(int order) override
Changes the interpolation order of a side. Updates all constraints and block sizes ...
Definition: pzintel.cpp:1592
virtual void Solution(TPZVec< REAL > &qsi, int var, TPZVec< STATE > &sol)
Calculates the solution - sol - for the variable var at point qsi, where qsi is expressed in terms of...
Definition: pzcompel.cpp:421
int Side() const
Definition: pzgeoelside.h:169
Contains declaration of TPZInterpolatedElement class which implements computational element of the in...
void ReCreateMultiphysicsMesh(TPZMultiphysicsCompMesh *cmesh_HDiv, double Lagrange_term_multiplier=1.)
create a multiphysics hybridized mesh based on and input mesh
void Fill(const T &copy, const int64_t from=0, const int64_t numelem=-1)
Will fill the elements of the vector with a copy object.
Definition: pzvec.h:460
int Side() const
Returns the side index.
Definition: pzcompel.h:688
virtual void SetDegree(int degree)
Assigns the degree of the element.
void BuildMultiphysicsSpace(TPZVec< int > &active_approx_spaces, TPZVec< TPZCompMesh * > &mesh_vector)
Set active approximation spaces.
void RemoveDepend(int64_t myindex, int64_t dependindex)
Remove dependency between connects if exist.
Definition: pzconnect.cpp:178
pthread_cond_t cond
Definition: numatst.cpp:318
Contains the TPZIntPoints class which defines integration rules.
void CopyMaterials(TPZCompMesh &mesh) const
Copies the materials of this mesh to the given mesh.
Definition: pzcmesh.cpp:1797
Contains the TPZTransform<> class which implements an affine transformation between points in paramet...
Implements an affine transformation between points in parameter space. Topology Utility.
Definition: pzmganalysis.h:14
void SetTrueUseQsiEta()
This class implements a discontinuous element (for use with discontinuous Galerkin). Computational Element.
Definition: TPZCompElDisc.h:35
void InitializeBlock()
Resequence the block object, remove unconnected connect objects and reset the dimension of the soluti...
Definition: pzcmesh.cpp:391
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
Contains the declaration of the TPZCondensedCompEl class, which implements an computational element w...
void push_back(const T object)
Definition: pzstack.h:48
virtual void AddElement(TPZCompEl *cel)
add an element to the element group
void SetKeepMatrix(bool keep)
Set the flag that determines whether the matrix needs to be kept or not.
void Apply(TPZVec< T > &vectorin, TPZVec< T > &vectorout)
Transforms the vector.
Definition: pztrnsform.cpp:121
Implements computational element based on an interpolation space. Computational Element.
Definition: pzintel.h:27
Non abstract class which implements full matrices with preallocated storage with (N+1) entries...
Definition: pzfmatrix.h:716
virtual void Point(int i, TPZVec< REAL > &pos, REAL &w) const =0
Returns i-th point at master element and related weight.
static TPZCompElSide RightElement(TPZInterpolatedElement *intel, int side)
find an element which shares the connect and has the same dimension