Exemple #1
0
//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);
		} 
	}
}
Exemple #2
0
//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();
	 */
}