⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boundary.cpp

📁 pic 模拟程序!面向对象
💻 CPP
字号:
/* * boundary.cpp *  * 0.99  (NTG, JohnV, 12-28-93) Separated into individual module from pic.h. * 0.991  (JohnV 08-21-95)  * 1.001  (JohnV 05-06-96) Added toNodes() for all boundaries. * 1.002  (JohnV 05-09-96) In toNodes() use ngp for normal fields at edges. * 1.003  (PeterM 8-12-96) In the constructor, ordered the points left-to-right * 1.004  (JohnV 11-05-96) Constructor sets points = NULL, oblique() depends on this. * 1.1    (JohnV 01-31-00) Modifications to suppport space time functions for emitters. */// System includes#include <cassert>#include "ptclgrp.h"#include "boundary.h"#include "fields.h"#include "gpdist.h"#include "mapNGDs.h"#include "dump.h"//--------------------------------------------------------------------//	Set fields pointer upon attaching to a SpatialRegion.Boundary::Boundary( oopicList<LineSegment> *_segments){	segments = new oopicList<LineSegment>;	*segments = *_segments;  //the advisor deletes *_segments.  We need a copy.	j1 = (int)segments->head->data->A.e1();	k1 = (int)segments->head->data->A.e2();	j2 = (int)segments->head->data->B.e1();	k2 = (int)segments->head->data->B.e2();	points = segments->head->data->points;	normal = segments->head->data->normal;	fill = 0;	fields = NULL;        ptrMapNGDs = 0;	xt_depend = NULL;	EnergyFlux = NULL;	Particle_diagnostic = NULL;	BoundaryType = NOTHING;}void Boundary::setFields(Fields& f){	fields = &f;}////--------------------------------------------------------------------//	Collect particles.void Boundary::collect(Particle& p, Vector3& dxMKS){	//	consider switching to a ParticleGroup format to conserve memory	if(Particle_diagnostic) Particle_diagnostic->record_particle(p,alongx2());	}Boundary::~Boundary() {  if (segments) {    segments->deleteAll();    segments=NULL;  }  if (Particle_diagnostic) {    delete Particle_diagnostic;    Particle_diagnostic = NULL;  }  if (xt_depend) {    delete xt_depend;    xt_depend = NULL;  }    // probably should delete particleoopicList contents here, if any}//---------------------------------------------------------------------//	setBoundaryMask sets the boundary masks in Grid for determing boundaries.//	Note that this version assume a line segment boundary, grid-aligned.// Volumetric boundaries must overload this function.void Boundary::setBoundaryMask(Grid &grid){		Grid* LocalGrid;	minK=grid.getK(),maxK=0,minJ=grid.getJ(),maxJ=0;	Vector2** X;	int j,k;	X = new Vector2*[minJ+1];	for (j=0; j<=minJ; j++){		X[j] = new Vector2[minK+1];		for (k=0; k<=minK; k++)			X[j][k] = grid.getMKS(j,k);	}	LocalGrid = new Grid(grid.getJ(),grid.getK(), X, grid.query_geometry(),											 grid.getPeriodicFlagX1(),											 grid.getPeriodicFlagX2());  oopicListIter <LineSegment> lsI(*segments);  for(lsI.restart();!lsI.Done();lsI++) {	 int j1,j2,k1,k2,normal,*points,h_nor,v_nor;  //local copies of above	 j1=(int)lsI.current()->A.e1();	 k1=(int)lsI.current()->A.e2();	 j2=(int)lsI.current()->B.e1();	 k2=(int)lsI.current()->B.e2();	 int temp;	 if (minK > (temp=MIN(k1,k2)))		 minK=temp;	 if (minJ > (temp=MIN(j1,j2)))		 minJ=temp;	 if (maxK < (temp=MAX(k1,k2)))		 maxK= temp;	 if (maxJ < (temp=MAX(j1,j2)))		 maxJ=temp;		 	 normal=lsI.current()->normal;	 h_nor = lsI.current()->h_nor;	 v_nor = lsI.current()->v_nor;	 points=lsI.current()->points;  	 	 if (j1==j2)	for (k=k1; k<k2; k++) {		 grid.setBoundaryMask2(j1, k, this, v_nor);		 LocalGrid->setBoundaryMask2(j1, k, this, v_nor);	 }	 else if(k1==k2) for (j=j1; j<j2; j++) {		 grid.setBoundaryMask1(j, k1, this, h_nor);		 LocalGrid->setBoundaryMask1(j, k1, this, h_nor);	 }	 else // oblique boundary		 {		  int j,k, jl,kl,jh,kh;		  /* start with the second point, advance one point at a time */		  for(j=2;j<4*abs(j2-j1)+4;j+=2) {			 jl=points[j-2];			 kl=points[j-1];			 jh=points[j];			 kh=points[j+1];			 if(kh==kl && jl!=jh){ /*horizontal segment*/				 grid.setBoundaryMask1(jl,kl,this, h_nor);				 LocalGrid->setBoundaryMask1(jl,kl,this, h_nor);			 }			 else				 for(k=MIN(kl,kh);k<MAX(kl,kh);k++){					 grid.setBoundaryMask2(jl,k,this, v_nor);					 LocalGrid->setBoundaryMask2(jl,k,this, v_nor);				 }		 }		} }		int inside = 0;	if (this->fill){		for (j=minJ; j<maxJ; j++){			inside = 0; // starting outside filled region			for (k=minK; k<maxK; k++){				if (LocalGrid->getNorm1()[j][k]<0)					inside = 1;				else if (LocalGrid->getNorm1()[j][k]>0)					inside = 0;				if (inside) {					grid.SetNodeBoundary(this, j, k);					grid.setCellMask(j,k,this);				}			}		}	}	delete LocalGrid;}#ifdef HAVE_HDF5int Boundary::dumpH5(dumpHDF5 &dumpObj, int number){  //cerr << "Entered Boundary::Dump--HDF5.\n";  hid_t fileId, groupId; //datasetId,dataspaceId;  herr_t status;  string outFile;  hsize_t rank; //  hsize_t     dimsf[1];     hsize_t dims;  hid_t scalarType = dumpObj.getHDF5ScalarType();  hid_t  attrdataspaceId,attributeId;  //  strstream s;#ifdef HAVE_SSTREAM  stringstream s;#else  strstream s;#endif  s <<  "boundary" << number <<ends;   string bname = s.str();  //  // Open the hdf5 file with write accessx  fileId = H5Fopen(dumpObj.getDumpFileName().c_str(), H5F_ACC_RDWR, H5P_DEFAULT);  bname = "/Boundaries/" + bname;  groupId = H5Gcreate(fileId,bname.c_str() ,0);     string datasetName = "dims";    rank = 1;  dims = 4;  attrdataspaceId = H5Screate_simple(rank, &dims, NULL);     attributeId = H5Acreate(groupId, datasetName.c_str(), scalarType, attrdataspaceId,			  H5P_DEFAULT);// get the data     Grid *grid = fields->get_grid();// Write the physical dimensions of the boundary    Scalar xw[4];  // in this format:  xs, ys, xf, yf  Vector2 **X=grid->getX();  xw[0] = X[j1][k1].e1();  xw[1] = X[j1][k1].e2();  xw[2] = X[j2][k2].e1();  xw[3] = X[j2][k2].e2();    status = H5Awrite(attributeId, scalarType, xw);  status = H5Aclose(attributeId);  status = H5Sclose(attrdataspaceId);// dump boundary type as attribute  dims = 1;  attrdataspaceId = H5Screate_simple(1, &dims, NULL);  attributeId = H5Acreate(groupId, "boundaryType",H5T_NATIVE_INT, attrdataspaceId, H5P_DEFAULT);  status = H5Awrite(attributeId, H5T_NATIVE_INT, &BoundaryType);  status = H5Aclose(attributeId);  status = H5Sclose(attrdataspaceId);  // dump n as attribute  dims = 1;  int n = 0;  attrdataspaceId = H5Screate_simple(1, &dims, NULL);  attributeId = H5Acreate(groupId, "nQuads",H5T_NATIVE_INT, attrdataspaceId, H5P_DEFAULT);  status = H5Awrite(attributeId, H5T_NATIVE_INT,&n );  status = H5Aclose(attributeId);  status = H5Sclose(attrdataspaceId);  H5Gclose(groupId);  H5Fclose(fileId);  //cerr << "exiting boundary::dumpH5.\n";  return(TRUE);}#endifint Boundary::Dump(FILE* DMPFile){//#ifdef UNIX	Grid *grid = fields->get_grid();// Write the physical dimensions of the boundary	{		Scalar xw[4];  // in this format:  xs, ys, xf, yf		Vector2 **X=grid->getX();		xw[0] = X[j1][k1].e1();		xw[1] = X[j1][k1].e2();		xw[2] = X[j2][k2].e1();		xw[3] = X[j2][k2].e2();		XGWrite(xw,ScalarInt,4,DMPFile,ScalarChar);	}	// write the BoundaryType	XGWrite(&BoundaryType, 4, 1, DMPFile, "int");	// Write the min. dummy set of stuff	int n=0; // number of floating point quads to restore	XGWrite(&n,4,1,DMPFile,"int");	// these two ints are presently unused	// but they are expected by restore:	XGWrite(&n,4,1,DMPFile,"int");	XGWrite(&n,4,1,DMPFile,"int");	//#endif	return(TRUE);}// In practice, this should never be called// but it'll read in data anwyay, and do nothing with it.int Boundary::Restore(FILE *DMPFile, int _BoundaryType,							  Scalar _A1,Scalar _A2, Scalar _B1, Scalar _B2,int nQuads) {	int i;	if(BoundaryType !=  _BoundaryType) return FALSE;	if(!onMe(_A1,_A2,_B1,_B2)) return FALSE;	for(i=0;i<nQuads;i++) {		Scalar x_in[4];		XGRead(x_in,ScalarInt,4,DMPFile,ScalarChar);	}	return(TRUE);}int Boundary::Restore_2_00(FILE *DMPFile, int j1,int k1,int j2,int k2) {	return(TRUE);}Scalar* Boundary::getEF(){	return(EnergyFlux);}Scalar Boundary::getBoltzmannFlux(){	return(-1);}//-------------------------------------------------------------------// Interpolates fields to the nodal locations.  Could be more accurate// but slower if it used the Q in the edge cells to obtain E normal.void Boundary::toNodes(){   oopicListIter <LineSegment> lsI(*segments);   for(lsI.restart();!lsI.Done();lsI++) {      int j1,j2,k1,k2,normal,*points;  //local copies of above      j1=(int)lsI()->A.e1();      k1=(int)lsI()->A.e2();      j2=(int)lsI()->B.e1();      k2=(int)lsI()->B.e2();      normal = lsI()->normal;      points=lsI()->points;             int j, k;      Scalar w1m, w1p, w2m, w2p;      Vector3** ENode = fields->getENode();      Vector3** BNode = fields->getBNode();      Vector3** intEdl = fields->getIntEdl();      Vector3** intBdS = fields->getIntBdS();      Grid* grid = fields->get_grid();      if(j1==j2 && k1==k2) return;  // don't do toNodes on one-point boundaries.      if (j1==j2)           	 {	    int jin, jinHalf;	    if (normal == 1)	       {		  jin = j1 + 1;		  jinHalf = j1;	       }	    else jinHalf = jin = j1 - 1;	    for (j=j1, k=k1; k<=k2; k++)	       {		  ENode[j][k].set_e1(intEdl[jinHalf][k].e1()/grid->dl1(jinHalf, k));					  /*			ENode[j][k].set_e1(2*intEdl[jinHalf][k].e1()/grid->dl1(jinHalf, k) 					- ENode[jin][k].e1());					*/					  if (k == grid->getK())			// fix B3 at outside edge		     {			BNode[j][k].set_e3(intBdS[jinHalf][k-1].e3()/grid->dS3(jinHalf, k-1));		     }		  else if (k > 0)		     {			w2m = grid->dl2(j, k)/(grid->dl2(j, k-1) + grid->dl2(j, k));			w2p = 1 - w2m;			ENode[j][k].set_e2(w2p*intEdl[j][k].e2()/grid->dl2(j, k) 					   + w2m*intEdl[j][k-1].e2()/grid->dl2(j, k-1));			BNode[j][k].set_e1(intBdS[j][k].e1()*w2p/grid->dS1(j, k)					   + intBdS[j][k-1].e1()*w2m/grid->dS1(j, k-1));			//			 BNode[j][k].set_e3(2*(intBdS[jinHalf][k].e3()*w2p/grid->dS3(jinHalf, k) 			//			  + intBdS[jinHalf][k-1].e3()*w2m/grid->dS3(jinHalf, k-1)) - BNode[jin][k].e3());			// BNode[jin][k] might be a boundary node			BNode[j][k].set_e3(intBdS[jinHalf][k].e3()*w2p/grid->dS3(jinHalf, k) 					   + intBdS[jinHalf][k-1].e3()*w2m/grid->dS3(jinHalf, k-1));		     }		  if (k > 0 || !grid->axis())		     {			ENode[j][k].set_e3(intEdl[j][k].e3()/grid->dl3(j,k));			//	 BNode[j][k].set_e2(2*intBdS[jinHalf][k].e2()/grid->dS2(jinHalf, k)			//						  - BNode[jin][k].e2());			BNode[j][k].set_e2(intBdS[jinHalf][k].e2()/grid->dS2(jinHalf, k));		     }  	       }	 }      else if (k1==k2)                	 {	    int kin, kinHalf;	    if (normal == 1)	       {		  kin = k1 + 1;		  kinHalf = k1;	       }	    else kin = kinHalf = k1 - 1;	    for (j=j1, k=k1; j<=j2; j++)	       {		  if (j > 0 && j < grid->getJ())		     {			w1m = grid->dl1(j, k)/(grid->dl1(j-1, k) + grid->dl1(j, k));			w1p = 1 - w1m;			ENode[j][k].set_e1(w1p*intEdl[j][k].e1()/grid->dl1(j, k) 					   + w1m*intEdl[j-1][k].e1()/grid->dl1(j-1, k));			if (k > 0 || !grid->axis())			   BNode[j][k].set_e2(intBdS[j][k].e2()*(w1p/grid->dS2(j, k)) 					      + intBdS[j-1][k].e2()*w1m/grid->dS2(j-1, k));			BNode[j][k].set_e3(2*(intBdS[j][kinHalf].e3()*w1p/grid->dS3(j, kinHalf) 					      + intBdS[j-1][kinHalf].e3()*w1m/grid->dS3(j-1, kinHalf)) - BNode[j][kin].e3());		     }		  ENode[j][k].set_e2(intEdl[j][kinHalf].e2()/grid->dl2(j, kinHalf));		  /*			ENode[j][k].set_e2(2*intEdl[j][kinHalf].e2()/grid->dl2(j, kinHalf)					- ENode[j][kin].e2());					*/					  if (k > 0 || !grid->axis()) ENode[j][k].set_e3(intEdl[j][k].e3()/grid->dl3(j, k));		  BNode[j][k].set_e1(2*intBdS[j][kinHalf].e1()/grid->dS1(j, kinHalf)				     - BNode[j][kin].e1());	       }	 }   }}// return 1 if the two points are on the line determined by this boundary, //to within a reasonable// tolerance.  return 0 otherwise.// Also returns 0 if the neither point is actually on the segment// determined by A1, A2, B1, B2int Boundary::onMe(Scalar tA1,Scalar tA2,Scalar tB1,Scalar tB2) {	Grid *grid = fields->get_grid();	Scalar A1 = grid->getX()[j1][k1].e1();	Scalar A2 = grid->getX()[j1][k1].e2();	Scalar B1 = grid->getX()[j2][k2].e1();	Scalar B2 = grid->getX()[j2][k2].e2();	// First check to see if it can overlap the current boundary	if(MIN(tA1,tB1) > MAX(A1,B1))  // there is no X1 overlap		return 0;	if(MAX(tA1,tB1) < MIN(A1,B1))  // there is no X1 overlap		return 0;	if(MIN(tA2,tB2) > MAX(A2,B2))  // there is no X2 overlap		return 0;	if(MAX(tA2,tB2) < MIN(A2,B2))  // there is no X2 overlap		return 0;	// pick a minimum delta:  if the boundary read in has distances less	// than delta, assume it's the same boundary. 	Scalar delta = 0.001*MIN(-grid->getX()[0][0].e2() + grid->getX()[0][1].e2(),							 -grid->getX()[0][0].e1() + grid->getX()[1][0].e1());	Scalar Dist1 = LineDist(A1,A2,B1,B2,tA1,tA2);	Scalar Dist2 = LineDist(A1,A2,B1,B2,tB1,tB2);	// if both distances are less than Delta, it's in this boundary.	if(Dist1 < delta && Dist2 < delta) { return 1;}	else return 0;}void Boundary::recvStripe(int dir){  Vector3 **intEdl = fields->getIntEdl();  Vector3 **intBdS = fields->getIntBdS();  Vector3 **I = fields->getI();  switch(dir){// Fields coming from right (right moving window)    case 1:{      assert(j1 == j2);// On KC's authority, one always has k1 <= k2      for(int k=k1; k<=k2; k++) {        intEdl[j1-1][k].set_e1(0.);        intEdl[j1][k].set_e2(0.);        intEdl[j1][k].set_e3(0.);        intBdS[j1][k].set_e1(0.);        intBdS[j1-1][k].set_e2(0.);        intBdS[j1-1][k].set_e3(0.);        I[j1-1][k].set_e1(0.);        I[j1][k].set_e2(0.);        I[j1][k].set_e3(0.);      }    }    break;// Fields coming from left (left moving window)    case 2:{      assert(j1 == j2);// On KC's authority, one always has k1 <= k2      for(int k=k1; k<=k2; k++) {        intEdl[j1][k] = 0.;        intBdS[j1][k] = 0.;        I[j1][k] = 0.;      }    }    break;// Fields coming from bottom (from greater k, downward moving window)    case 3:{      assert(k1 == k2);// On KC's authority, one always has k1 <= k2      for(int j=j1; j<=j2; j++) {        intEdl[j][k1].set_e1(0.);        intEdl[j][k1-1].set_e2(0.);        intEdl[j][k1].set_e3(0.);        intBdS[j][k1-1].set_e1(0.);        intBdS[j][k1].set_e2(0.);        intBdS[j][k1-1].set_e3(0.);        I[j][k1].set_e1(0.);        I[j][k1-1].set_e2(0.);        I[j][k1].set_e3(0.);      }    }    break;// Fields coming from top (from smaller k, upward moving window)    case 4:{      assert(k1 == k2);// On KC's authority, one always has k1 <= k2      for(int j=j1; j<=j2; j++) {        intEdl[j][k1] = 0.;        intBdS[j][k1] = 0.;        I[j][k1] = 0.;      }    }    break;  }}	

⌨️ 快捷键说明

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