//void DivideRecursive(TPZCompEl *locel,int index,TPZVec<int> indexsubs,int hn); void TPZAnalysisError::HPAdapt(REAL CurrentEtaAdmissible, std::ostream &out) { arq << "CurrentEtaAdmissible " << CurrentEtaAdmissible << endl; TPZAdmChunkVector<TPZCompEl *>&listel = Mesh()->ElementVec(); bool store_error = false; EvaluateError(CurrentEtaAdmissible,store_error, out); TPZVec<TPZCompElSide> SingLocal(fSingular); fSingular.Resize(0); int64_t nel = fElIndexes.NElements(); for(int64_t ielloc=0;ielloc<nel;ielloc++) { int64_t iel = fElIndexes[ielloc]; // if the element has already been treated (e.g. singularity) skip the process if(iel == -1) continue; TPZInterpolatedElement *elem = (TPZInterpolatedElement *) listel[iel]; if(!elem || elem->Material()->Id() < 0) { PZError << "TPZAnalysisError::HPAdapt boundary element with error?\n"; PZError.flush(); continue; } REAL csi = fElErrors[ielloc] / fAdmissibleError; // Verificar se o element atual e um elemento singular int64_t ising, nsing = SingLocal.NElements(); for(ising=0; ising<nsing; ising++) { if(elem == SingLocal[ising].Element()) { ZoomInSingularity(csi,SingLocal[ising]); break; } } // Go to the end of the loop if the element was handled by the singularity if(ising < nsing) continue; //calculo da ordem pn do elemento atual int nsides = elem->Reference()->NSides(); REAL pFo = double(elem->EffectiveSideOrder(nsides-1));//quadrilatero // Newton's Method -> compute pNew REAL pFn = pFo, res = 10.0, phi, del, dph, tol = 0.001; int64_t MaxIter = 100; int64_t iter=0; while (iter < MaxIter && res > tol) { phi = pFo+log(csi)-pFo*log(pFn/pFo); dph = pFn/(pFo+pFn); del = dph*(phi-pFn); if (del+pFn <= 0.0) // caiu fora do intervalo! del = 0.5 - pFn; res = fabs(del); pFn = del+pFn; iter++; } // end of Newton's Method if (iter == MaxIter) PZError << "\n - Newton's Method Failed at Element = " << elem->Reference()->Id() << endl; if(pFn < 1.) pFn = 1.; REAL factor = pow(csi,-1.0/pFn)*(pow(pFn/pFo,pFo/pFn)); if(factor <= 0.75) factor = 0.5; // refine h else factor = 1.0; // don't refine h // Newton's Method -> compute once again pNew pFn = pFo; iter = 0; res = 10.0; while (iter < MaxIter && res > tol) { phi = -pFn*log(factor)-log(csi)+pFo*log(pFn/pFo); dph = pFn/(pFo-pFn*log(factor)); del = -dph*phi; if (del+pFn <= 0.0) // caiu fora do intervalo! del = 0.5 - pFn; res = fabs(del); pFn = del+pFn; iter++; } // end of Newton's Method if (iter == MaxIter) PZError << "\n - Newton's Method Failed at Element = " << elem->Reference()->Id() << endl; if(pFn < 1.) pFn = 1.; int pNew = 0;//(int) floor(pFn + 0.5); // get the integer while(REAL(pNew) < (pFn+0.5)) pNew++; TPZVec<REAL> x(3),cs(2,0.); elem->Reference()->X(cs,x); elem->PRefine(pNew); TPZCompEl *locel = elem; //Divide elements if(factor == 0.5 ) { TPZVec<int64_t> indexsubs; int64_t index = locel->Index(); elem->Divide(index,indexsubs,1); } } }
//SingularElements(..) void TPZAnalysisError::ZoomInSingularity(REAL csi, TPZCompElSide elside, REAL singularity_strength) { REAL hn = 1./pow(csi,1./singularity_strength); REAL Q=2.; REAL NcReal = log( 1.+(1./hn - 1.)*(Q - 1.) )/log(Q); int Nc = 0; while(REAL(Nc) < (NcReal+0.5)) Nc++; int minporder = 2; TPZStack<TPZCompElSide> ElToRefine; TPZStack<int> POrder; TPZStack<TPZGeoElSide> subelements; TPZStack<int64_t> csubindex; ElToRefine.Push(elside); POrder.Push(Nc); while(ElToRefine.NElements()) { /** Take the next element and its interpolation order from the stack*/ TPZCompElSide curelside = ElToRefine.Pop(); int curporder = POrder.Pop(); if(!curelside.Exists()) continue; int64_t cindex = curelside.Element()->Index(); if(cindex < 0) continue; /** Cast the element to an interpolated element if possible*/ TPZCompEl *cel = curelside.Element(); TPZInterpolatedElement *cintel = 0; cintel = dynamic_cast<TPZInterpolatedElement *> (cel); /** If the element is not interpolated, nothing to do */ if(!cintel) continue; /** Set the interpolation order of the current element to curporder*/ if(curporder == minporder) { cintel->PRefine(Nc); fSingular.Push(curelside); } else { cintel->PRefine(curporder); cintel->Divide(cindex,csubindex,1); /** Identify the subelements along the side and push them on the stack*/ } TPZGeoElSide gelside = curelside.Reference(); if(!gelside.Exists()) continue; gelside.GetSubElements2(subelements); int64_t ns = subelements.NElements(); curporder--; int64_t is; for(is=0; is<ns; is++) { TPZGeoElSide sub = subelements[is]; TPZCompElSide csub = sub.Reference(); if(csub.Exists()) { ElToRefine.Push(csub); POrder.Push(curporder); } } } ExpandConnected(fSingular); /* REAL H1_error,L2_error,estimate; TPZBlock *flux=0; int64_t nel = fElIndexes.NElements(); for(int64_t elloc=0;elloc<nel;elloc++) { int64_t el = fElIndexes[elloc]; estimate = fElErrors[elloc]; REAL csi = estimate / fAdmissibleError; REAL h = h_Parameter(intellist[el]); REAL hn = h/pow(csi,1./.9); REAL Nc = log( 1.+(h/hn - 1.)*(Q - 1.) )/log(Q); if(hn > 1.3*h) hn = 2.0*h*hn / (h + hn); REAL hsub = h;//100.0;//pode ser = h ; Cedric TPZCompEl *locel = intellist[el]; //obter um subelemento que contem o ponto singular e tem tamanho <= hn TPZAdmChunkVector<TPZCompEl *> sublist; while(hsub > hn) { TPZVec<int64_t> indexsubs; int64_t index = locel->Index(); locel->Divide(index,indexsubs,1); int64_t nsub = indexsubs.NElements(); TPZAdmChunkVector<TPZCompEl *> listsub(0); for(int64_t k=0;k<nsub;k++) { index = listsub.AllocateNewElement(); listsub[index] = Mesh()->ElementVec()[indexsubs[k]]; } //existe um unico filho que contem o ponto singular SingularElement(point,listsub,sublist); hsub = h_Parameter(sublist[0]); } TPZInterpolatedElement *intel = (TPZInterpolatedElement *) locel; intel->PRefine(Nc+1); indexlist.Push(intel->Index()); //os elemento viz devem ter ordens menores a cel quanto mais longe de point TPZInterpolatedElement *neighkeep,*neigh; //feito s�para o caso 1d , extender para o caso geral int dim = intel->Dimension(); if(dim != 1) { cout << "TPZAnalysisError::Step3 not dimension implemented , dimension = " << intellist[el]->Dimension() << endl; return ;//exit(1); } for(int side=0;side<2;side++) { int ly = 1; TPZGeoElSide neighside = intel->Reference()->Neighbour(side); TPZGeoElSide neighsidekeep = neighside; TPZCompElSide neighsidecomp(0,0); TPZStack<TPZCompElSide> elvec(0); TPZCompElSide thisside(intel,side); if(!neighsidekeep.Exists()) thisside.HigherLevelElementList(elvec,1,1); if(!neighsidekeep.Exists() && elvec.NElements() == 0) { neighsidekeep = thisside.LowerLevelElementList(1).Reference(); } else if(elvec.NElements() != 0) { neighsidekeep = elvec[0].Reference(); } while(ly < (Nc+1) && neighsidekeep.Exists() && neighsidekeep.Element()->Reference()->Material()->Id() > -1) { neigh = (TPZInterpolatedElement *) neighsidekeep.Element()->Reference(); if(neigh) { neigh->PRefine(ly); int otherside = (neighsidekeep.Side()+1)%2; neighsidekeep.SetSide(otherside); indexlist.Push(neighsidekeep.Reference().Element()->Index()); } neighside = neighsidekeep.Neighbour(); while(!neighside.Exists()) { neighsidecomp = neighsidekeep.Reference(); neighsidecomp.HigherLevelElementList(elvec,1,1); if(elvec.NElements()) { neighside = elvec[0].Reference(); break; } neighside = neighsidecomp.LowerLevelElementList(1).Reference(); if(!neighside.Exists()) break; } neighsidekeep = neighside; ly++; } } }//for Mesh()->InitializeBlock(); */ }