metric.cpp

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 1,214 行 · 第 1/3 页

CPP
1,214
字号
    {      Mmass[iv]=0;      OnBoundary[iv]=0;      Mmassxx[iv]=0;    }  for (i=0;i<nbt;i++)     if(triangles[i].link) // the real triangles       {	const Triangle &t=triangles[i];	// coor of 3 vertices 	R2 A=t[0];	R2 B=t[1];	R2 C=t[2];	// number of the 3 vertices	iA = Number(t[0]);	iB = Number(t[1]);	iC = Number(t[2]);		Real8 dett = bamg::Area2(A,B,C);	detT[i]=dett;	dett /= 6;	// construction of on boundary 	int nbb =0;	for(int j=0;j<3;j++)          {	    Triangle *ta=t.Adj(j);	    if ( ! ta || !ta->link) // no adj triangle => edge on boundary	      OnBoundary[Number(t[VerticesOfTriangularEdge[j][0]])]=1,		OnBoundary[Number(t[VerticesOfTriangularEdge[j][1]])]=1,		nbb++;	  }		workT[i] = nbb;	Mmass[iA] += dett;	Mmass[iB] += dett;	Mmass[iC] += dett;		if((nbb==0)|| !choice)	  {	    Mmassxx[iA] += dett;	    Mmassxx[iB] += dett;	    Mmassxx[iC] += dett;	  }      }  else    workT[i]=-1;//  for (Int4 kcount=0;kcount<n;kcount++,ss++)    for (Int4 nusol=0;nusol<nbsol;nusol++)    { //for all Solution        Real8 smin=ss[0],smax=ss[0];            Real8 h1=1.e30,h2=1e-30,rx=0;      Real8 coef = 1./(anisomax*anisomax);      Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;        int nbfield = typsols? sizeoftype[typsols[nusol]] : 1;       if (nbfield == 1)        for ( iv=0,k=0; iv<nbv; iv++,k+=n )				{				  dxdx[iv]=dxdy[iv]=dydy[iv]=0;				  smin=Min(smin,ss[k]);				  smax=Max(smax,ss[k]);				 }			  else			   {         //  cas vectoriel           for ( iv=0,k=0; iv<nbv; iv++,k+=n )          {	           double v=0;		     			     for (int i=0;i<nbfield;i++) 			         v += ss[k+i]*ss[k+i];			     v = sqrt(v);				   smin=Min(smin,v);				   smax=Max(smax,v);			    }			   }      Real8 sdelta = smax-smin;      Real8 absmax=Max(Abs(smin),Abs(smax));      Real8 cnorm = DoNormalisation ? coef2/sdelta : coef2;            if(verbosity>2) 	     cout << "    Solution " << nusol <<  " Min = " << smin << " Max = " 	       << smax << " Delta =" << sdelta << " cnorm = " << cnorm <<  " Nb of fields =" << nbfield << endl;            if ( sdelta < 1.0e-10*Max(absmax,1e-20) && (nbfield ==1)) 				{				  if (verbosity>2)				    cout << "      Solution " << nusol << " is constant. We skip. " 					 << " Min = " << smin << " Max = " << smax << endl;				continue;				}					 double *sf  = ss; 	 for (Int4 nufield=0;nufield<nbfield;nufield++,ss++) 	   {	     for ( iv=0,k=0; iv<nbv; iv++,k+=n )		       dxdx[iv]=dxdy[iv]=dydy[iv]=0;       for (i=0;i<nbt;i++) 	      if(triangles[i].link)	  {// for real all triangles 	    // coor of 3 vertices 	    R2 A=triangles[i][0];	    R2 B=triangles[i][1];	    R2 C=triangles[i][2];	    	    	    // warning the normal is internal and the 	    //   size is the length of the edge	    R2 nAB = Orthogonal(B-A);	    R2 nBC = Orthogonal(C-B);	    R2 nCA = Orthogonal(A-C);	    // remark :  nAB + nBC + nCA == 0 	    // number of the 3 vertices	    iA = Number(triangles[i][0]);	    iB = Number(triangles[i][1]);	    iC = Number(triangles[i][2]);	    	    // for the test of  boundary edge	    // the 3 adj triangles 	    Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]);	    Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]);	    Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]);	    // value of the P1 fonction on 3 vertices 	    sA = ss[iA*n];	    sB = ss[iB*n];	    sC = ss[iC*n];	    R2 Grads = (nAB * sC + nBC * sA + nCA * sB ) /detT[i] ;	    if(choice) 	      {		int nbb = 0;		Real8 dd = detT[i];		Real8 lla,llb,llc,llf;		Real8  taa[3][3],bb[3];		// construction of the trans of lin system		for (int j=0;j<3;j++)		  {		    int ie = OppositeEdge[j];		    TriangleAdjacent ta = triangles[i].Adj(ie);		    Triangle *tt = ta;		    if (tt && tt->link)		      {			Vertex &v = *ta.OppositeVertex();			R2 V = v;			Int4 iV = Number(v);			Real8 lA  = bamg::Area2(V,B,C)/dd;			Real8 lB  = bamg::Area2(A,V,C)/dd;			Real8 lC  = bamg::Area2(A,B,V)/dd;			taa[0][j] =  lB*lC;			taa[1][j] =  lC*lA;			taa[2][j] =  lA*lB;			//Real8 xx = V.x-V.y;			//Real8 yy = V.x + V.y;			//cout << " iv " << ss[iV*n] << " == " << (8*xx*xx+yy*yy)			//     << " l = " << lA << " " << lB << " " << lC 			//     << " = " << lA+lB+lC << " " <<  V << " == " << A*lA+B*lB+C*lC << endl;						lla = lA,llb=lB,llc=lC,llf=ss[iV*n] ;			bb[j]     =  ss[iV*n] - ( sA*lA + sB*lB + sC*lC ) ;		      }		    else		      {			nbb++;			taa[0][j]=0;			taa[1][j]=0;			taa[2][j]=0;			taa[j][j]=1;			bb[j]=0;		      }		  }		// resolution of 3x3 lineaire system transpose		Real8 det33 =  det3x3(taa[0],taa[1],taa[2]);				Real8 cBC   =  det3x3(bb,taa[1],taa[2]);		Real8 cCA   =  det3x3(taa[0],bb,taa[2]);		Real8 cAB   =  det3x3(taa[0],taa[1],bb);				assert(det33);		//	det33=1;		// verif		//	cout << " " << (taa[0][0]*cBC +  taa[1][0]*cCA + taa[2][0] * cAB)/det33 << " == " << bb[0] ;		//	cout << " " << (taa[0][1]*cBC +  taa[1][1]*cCA + taa[2][1] * cAB)/det33 << " == " << bb[1];		//	cout << " " << (taa[0][2]*cBC +  taa[1][2]*cCA + taa[2][2] * cAB)/det33 << " == " << bb[2] 		//	     << "  -- " ;		//cout << lla*sA + llb*sB+llc*sC+ (lla*llb* cAB +  llb*llc* cBC + llc*lla*cCA)/det33 		//   << " == " << llf <<  endl;		// computation of the gradient in the element 				// H( li*lj) = grad li grad lj + grad lj grad lj		// grad li = njk  / detT ; with i j k ={A,B,C)		Real8 Hxx = cAB * ( nBC.x*nCA.x) +  cBC * ( nCA.x*nAB.x) + cCA * (nAB.x*nBC.x);		Real8 Hyy = cAB * ( nBC.y*nCA.y) +  cBC * ( nCA.y*nAB.y) + cCA * (nAB.y*nBC.y);		Real8 Hxy = cAB * ( nBC.y*nCA.x) +  cBC * ( nCA.y*nAB.x) + cCA * (nAB.y*nBC.x) 		          + cAB * ( nBC.x*nCA.y) +  cBC * ( nCA.x*nAB.y) + cCA * (nAB.x*nBC.y);		Real8 coef = 1.0/(3*dd*det33);		Real8 coef2 = 2*coef;		//	cout << " H = " << Hxx << " " << Hyy << " " <<  Hxy/2 << " coef2 = " << coef2 << endl;		Hxx *= coef2;		Hyy *= coef2;		Hxy *= coef2;		//cout << i  << " H = " << 3*Hxx/dd << " " << 3*Hyy/dd << " " <<  3*Hxy/(dd*2) << " nbb = " << nbb << endl;		if(nbb==0)		  {		    dxdx[iA] += Hxx;		    dydy[iA] += Hyy;		    dxdy[iA] += Hxy;		    		    dxdx[iB] += Hxx;		    dydy[iB] += Hyy;		    dxdy[iB] += Hxy;		    		    dxdx[iC] += Hxx;		    dydy[iC] += Hyy;		    dxdy[iC] += Hxy;		  }			      }	    else	      {				// if edge on boundary no contribution  => normal = 0		if ( ! tBC || ! tBC->link ) nBC = O;		if ( ! tCA || ! tCA->link ) nCA = O;		if ( ! tAB || ! tAB->link ) nAB = O;	    		// remark we forgot a 1/2 because		//       $\\int_{edge} w_i = 1/2 $ if $i$ is in edge 		//                          0  if not		// if we don't take the  boundary 		// dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;				dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;		dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x;		dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x;				// warning optimization (1) the divide by 2 is done on the metrix construction		dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ;		dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ;		dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ; 				dydy[iA] += ( nCA.y + nAB.y ) *Grads.y;		dydy[iB] += ( nAB.y + nBC.y ) *Grads.y;		dydy[iC] += ( nBC.y + nCA.y ) *Grads.y;	      }	    	  } // for real all triangles      Int4 kk=0;      for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )	if(Mmassxx[iv]>0) 	  {	    dxdx[iv] /= 2*Mmassxx[iv];	    // warning optimization (1) on term dxdy[iv]*ci/2 	    dxdy[iv] /= 4*Mmassxx[iv];	    dydy[iv] /= 2*Mmassxx[iv];	    // Compute the matrix with abs(eigen value)	    Metric M(dxdx[iv], dxdy[iv], dydy[iv]);	    MatVVP2x2 Vp(M);	    //cout <<iv <<  "  M  = " <<  M <<  " aniso= " << Vp.Aniso() ;	    Vp.Abs();	    M = Vp;	      dxdx[iv] = M.a11;	      dxdy[iv] = M.a21;	      dydy[iv] = M.a22;	      //  cout << " (abs)  iv M  = " <<  M <<  " aniso= " << Vp.Aniso() <<endl;	  }	else kk++;                  // correction of second derivate      // by a laplacien      Real8 *d2[3] = { dxdx, dxdy, dydy};      Real8 *dd;      for (int xy = 0;xy<3;xy++)	{	  dd = d2[xy];      // do leat 2 iteration for boundary problem	  for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++)	    {	      for (i=0;i<nbt;i++) 		if(triangles[i].link) // the real triangles 		  {		    // number of the 3 vertices		    iA = Number(triangles[i][0]);		    iB = Number(triangles[i][1]);		    iC = Number(triangles[i][2]);		    Real8 cc=3;		    if(ijacobi==0)		      cc = Max((Real8) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.);		    workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc;		  }	      for (iv=0;iv<nbv;iv++)		workV[iv]=0;	      for (i=0;i<nbt;i++) 		if(triangles[i].link) // the real triangles 		  {		    // number of the 3 vertices		    iA = Number(triangles[i][0]);		    iB = Number(triangles[i][1]);		    iC = Number(triangles[i][2]);		    Real8 cc =  workT[i]*detT[i];		    workV[iA] += cc;		    workV[iB] += cc;		    workV[iC] += cc;		  }	      for (iv=0;iv<nbv;iv++)		if( ijacobi<NbJacobi || OnBoundary[iv])		  dd[iv] = workV[iv]/(Mmass[iv]*6);	      	    }	  	}      // constuction  of the metrix from the Hessian dxdx. dxdy,dydy      Real8 rCutOff=CutOff*absmax;// relative cut off       for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )	{ // for all vertices 	  //{	  //Metric M(dxdx[iv], dxdy[iv], dydy[iv]);	  // MatVVP2x2 Vp(M);	  	  //cout << " iv M="<<  M << "  Vp = " << Vp << " aniso  " << Vp.Aniso() << endl;	  //}	  MetricIso Miso;// new code to compute ci ---	  	  Real8 ci ;	  if (RelativeMetric)	    { //   compute the norm of the solution	       double xx =0,*sfk=sf+k; 	       for (int ifield=0;ifield<nbfield;ifield++,sfk++)	          xx += *sfk* *sfk;	       	       xx=sqrt(xx);	       ci = coef2/Max(xx,rCutOff);	    }	  else ci = cnorm;	   // old //	  Real8 ci = RelativeMetric ? coef2/(Max(Abs(ss[k]),rCutOff)) : cnorm ; //   modif F Hecht 101099	  Metric Miv(dxdx[iv]*ci, dxdy[iv]*ci,  dydy[iv]*ci);	  MatVVP2x2 Vp(Miv);	  Vp.Abs();	 if(power!=1.0) 	      Vp.pow(power);	  	  h1=Min(h1,Vp.lmin());	  h2=Max(h2,Vp.lmax());	  Vp.Maxh(hmin);	  Vp.Minh(hmax);	  rx = Max(rx,Vp.Aniso2());	  Vp.BoundAniso2(coef);	  hn1=Min(hn1,Vp.lmin());	  hn2=Max(hn2,Vp.lmax());	  rnx = Max(rnx,Vp.Aniso2());	  Metric MVp(Vp);	  vertices[iv].m.IntersectWith(MVp);	}// for all vertices       if (verbosity>2)	{ 	  cout << "              Field " << nufield << " of solution " << nusol  << endl;	  cout << "              before bounding :  Hmin = " << sqrt(1/h2) << " Hmax = " 	       << sqrt(1/h1)  << " factor of anisotropy max  = " << sqrt(rx) << endl;	  cout << "              after  bounding :  Hmin = " << sqrt(1/hn2) << " Hmax = " 	       << sqrt(1/hn1)  << " factor of anisotropy max  = " << sqrt(rnx) << endl;	}	 } //  end of for all field    }// end for all solution   delete [] detT;  delete [] Mmass;  delete [] dxdx;  delete [] dxdy;  delete [] dydy;  delete []  workT;  delete [] workV;  delete [] Mmassxx;  delete []  OnBoundary; }void Triangles::ReadMetric(const char * fmetrix,const Real8 hmin1=1.0e-30,const Real8 hmax1=1.0e30,const Real8 coef=1){

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?