Beispiel #1
0
Transform::Transform( const std::string nodeName ) :
	vgd::node::GeometricalTransformation( nodeName )
{
	// Add field
	addField( new FCenterType(getFCenter()) );
	addField( new FScaleOrientationType(getFScaleOrientation()) );
	addField( new FScaleFactorType(getFScaleFactor()) );
	addField( new FRotationType(getFRotation()) );
	addField( new FTranslationType(getFTranslation()) );

	// Link
	link( getDFNode() );
}
void calculateGeomCoefficients(pEntity face, double *Cij, double *Dij, double &vol){
	// Cij_x = Cij[0];		Dij_x = Dij[0];
	// Cij_y = Cij[1];		Dij_y = Dij[1];
	// Cik_x = Cij[2];		Dij_x = Dij[2];
	// Cik_y = Cij[3];		Dij_y = Dij[3];
	// Cjk_x = Cij[4];		Dij_x = Dij[4];
	// Cjk_y = Cij[5];		Dij_y = Dij[5];

	int i, pos, id0, id1;
	double faceCenter[3], edgeCenter[3], IJ[2], innerprod, sign;
	double I[3], J[3], v[2];
	pEntity edge;

	pos = 0;
	getFCenter(face,faceCenter);
	for (i=0; i<3; i++){					// loop over all three face's edges to calculate Cij and Dij
		edge = F_edge(face, i);
		edgeCenter[0] = .0;
		edgeCenter[1] = .0;
		E_center(edge,edgeCenter);			// get edge middle point
		V_coord(edge->get(0,0),I);			// get node I coordinate
		V_coord(edge->get(0,1),J);			// get node J coordinate
		id0 = EN_id(edge->get(0,0));		// get node I ID
		id1 = EN_id(edge->get(0,1));		// get node J ID
		sign = ( id0 > id1 )?-1.0:1.0; 		// vector IJ must point from the smaller vertex ID to the greater
		IJ[0] = sign*(J[0]-I[0]);			// edge vector, used as a reference vector
		IJ[1] = sign*(J[1]-I[1]);
		v[0] = edgeCenter[0]-faceCenter[0];	// reference vector
		v[1] = edgeCenter[1]-faceCenter[1];
		innerprod = v[1]*IJ[0] + (-v[0])*IJ[1];	// Cij must point as if I inside the CV and J outside
		if ( innerprod <= .0 ){
			v[0] = -v[0];
			v[1] = -v[1];
		}
		Cij[pos] = v[1];
		Cij[pos+1] = -v[0];
		Dij[pos] = -(J[1]-I[1])/2.0;					// Dij vector is orthogonal to edge (it's unknown Dij orientation)
		Dij[pos+1] =  (J[0]-I[0])/2.0;
		v[0] = edgeCenter[0]-faceCenter[0];				// reference vector
		v[1] = edgeCenter[1]-faceCenter[1];

		innerprod = Dij[pos]*v[0] + Dij[pos+1]*v[1];	// Dij must point to outside element
		if (  innerprod <= .0 ){
			Dij[pos] = -Dij[pos];
			Dij[pos+1] = -Dij[pos+1];
		}
		pos += 2;
	}
	vol = F_area(face)/3.0;								// calculate node control volume
}
// calculates: Cij, Dij and nodal volume
int EBFV1_preprocessor_2D(pMesh theMesh, void *pData, int &ndom){
#ifdef TRACKING_PROGRAM_STEPS
	cout << "TRACKING_PROGRAM_STEPS: EBFV1_preprocessor_2D\tIN\n";
#endif

	GeomData *pGCData = (GeomData*)pData;
	pGCData->setMeshDim(theMesh->getDim());

	theMesh->modifyState(2,1);	// create edge data structure
	theMesh->modifyState(0,2);	// create adjacency around nodes
	theMesh->modifyState(1,2);	// create faces around edge

	//cout << "Mesh dimension: 2D\n";
	int i,j,flag,dom;
	double edgeCenter[3], I[3], J[3];

	std::vector<double> Cij(3), Dij(3);
	pEntity edge, face, node;

	/// initialize coefficients
	initializeCoefficients(theMesh,pGCData);

	std::set<int> setOfDomain;

	// for each face, calculate all data needed and attach them to the its edges
	FIter fit = M_faceIter(theMesh);
	while ( (face = FIter_next(fit)) ){
		// look up only for leave elements (without children)
		if ( !theMesh->getRefinementDepth(face) ){
			dom = EN_getFlag(face);
			char dom_string[256]; sprintf(dom_string,"dom_str_%d",dom);

			if (!dom){
				throw Exception(__LINE__,__FILE__,"dom = 0\n");
			}

			setOfDomain.insert(dom);		// store every new domain
			double faceCenter[3] = {.0, .0, .0};
			getFCenter(face,faceCenter);

			// loop over all three face's edges to calculate Cij and Dij
			for (i=0; i<3; i++){
				edge = F_edge(face, i);

				// set edge belonging to domain 'dom'
				EN_attachDataInt(edge,MD_lookupMeshDataId( dom_string ),1);

				edgeCenter[0] = edgeCenter[1] = .0;
				E_center(edge,edgeCenter);				// edge centroid
				V_coord(edge->get(0,0),I);
				V_coord(edge->get(0,1),J);

				int id0 = EN_id(edge->get(0,0));
				int id1 = EN_id(edge->get(0,1));

				// edge vector, used as a reference vector
				double IJ[2] = {J[0]-I[0], J[1]-I[1]};

				// vector IJ must point from the smaller vertex ID to the greater
				if ( id0 > id1 ){
					for (j=0; j<2; j++){
						IJ[j] = -IJ[j];
					}
				}

				// vector: from element center to edge middle point, used as a reference vector
				double v[2] = {edgeCenter[0]-faceCenter[0],edgeCenter[1]-faceCenter[1]};

				// Cij is orthogonal to v
				for (j=0; j<2; j++){
					Cij[j] = .0;
				}

				// Cij must point as if I inside the CV and J outside
				double innerprod = v[1]*IJ[0] + (-v[0])*IJ[1];
				if ( innerprod <= .0 ){
					for (j=0; j<2; j++){
						v[j] = -v[j];
					}
				}

				// associate Cij coefficient to edge
				pGCData->getCij(edge,dom,Cij);
				Cij[0] += v[1];
				Cij[1] += -v[0];

				pGCData->setCij(edge,dom,Cij);
				//cout << "Cij = " << Cij[0] << "\t" << Cij[1] << "\t" << Cij[2] << "\n";
#ifdef __ADAPTATION_DEBUG__
		if (Cij[0]==.0 && Cij[1]==.0){
			char msg[256]; sprintf(msg,"Edge %d-%d has Cij coefficient NULL Cij[0]=Cij[1]=0.0",id0,id1);
			throw Exception(__LINE__,__FILE__,msg);
		}
#endif
			}

			// calculate volume of control volume and associate it to elements nodes
			const double porosity = .0;
			double A = F_area(face)/3.0;	// element area
			//cout << "area = " << A << endl;
			for (j=0; j<3; j++){
				node = face->get(0,j);
				EN_attachDataInt(node,MD_lookupMeshDataId( dom_string ),1);
				double v1 = pGCData->getVolume(node,dom);
				double v2 = pGCData->getWeightedVolume(node);
				v1 += A;
				v2 += A*porosity;
				pGCData->setVolume(node,dom,v1);
				pGCData->setWeightedVolume(node,v2);
			}
		}
	}
	FIter_delete(fit);

	int numBE = 0;
	// Calculate Dij coefficient only for boundary edges.
	EIter eit = M_edgeIter(theMesh);
	while ( (edge = EIter_next(eit)) ){
		if ( !theMesh->getRefinementDepth(edge) ){
 			flag = EN_getFlag(edge);
 			std::set<int>::iterator iter = setOfDomain.find( flag );
 			if (iter == setOfDomain.end()){		// this line is for general (h**o/hetero) adaptation
				numBE++;
				double I[3] = {.0,.0,.0}, J[3] = {.0,.0,.0};
				V_coord(edge->get(0,0),I);
				V_coord(edge->get(0,1),J);

				// Dij vector is orthogonal to edge (it's unknown Dij orientation)
				Dij[0] = -(J[1]-I[1])/2.0;
				Dij[1] =  (J[0]-I[0])/2.0;

				// make Dij points to outside domain. First, take face that uses edge and its flag
				int domains[2] = {0,0};
				for (i=0; i<E_numFaces(edge); i++){
					face = E_face(edge,i);
					if (!face){
						throw Exception(__LINE__,__FILE__,"Null face!\n");
					}
					domains[i] = EN_getFlag(face);
				}
				// that the reference face to make Dij points to outside
				face = E_face(edge, 0);

				if (!face){
					throw Exception(__LINE__,__FILE__,"Null face!\n");
				}

				// now, get face's center and edge's center
				double faceCenter[3] = {.0, .0, .0}, edgeCenter[3] = {.0, .0, .0};
				getFCenter(face,faceCenter);	// element centroid
				E_center(edge,edgeCenter);		// edge centroid

				// vector: from element center to edge middle point, used as a reference vector
				double v[2] = {edgeCenter[0]-faceCenter[0],edgeCenter[1]-faceCenter[1]};

				// Dij must point to outside element
				double innerprod = Dij[0]*v[0] + Dij[1]*v[1];
				if (  innerprod <= .0 ){
					for (j=0; j<2; j++){
						Dij[j] = -Dij[j];
					}
				}
				// associate to edge domains flags to wjich it belongs
				EN_attachDataInt(edge,MD_lookupMeshDataId("dom1"),domains[0]);
				EN_attachDataInt(edge,MD_lookupMeshDataId("dom1"),domains[1]);
				pGCData->setDij(edge,domains[0],domains[1],Dij);
			}
		}
	}
	EIter_delete(eit);
	//cout << "preprocessor: Number of Boundary edges = " << numBE << endl;
	calculateEdgeLength(theMesh,pGCData);
	calculateCijNorm(theMesh,pGCData,setOfDomain);

	// For 2-D domains, multiply volume by reservoir height (H) for 2D/3D simulations (physics occurs only on 2-D but reservoir volume is considered)
	double vt = .0;
	double vol,wvol;
	std::set<int>::iterator iter = setOfDomain.begin();
	for(;iter!=setOfDomain.end();iter++){
		VIter vit = M_vertexIter(theMesh);
		while (pEntity node = VIter_next(vit)){
			// do not divide vol by number of remote copies!
			vol = pGCData->getVolume(node,*iter);
			vt += vol;
			wvol = 0.2*vol;
			pGCData->setWeightedVolume(node,wvol);
		}
		VIter_delete(vit);
	}
	pGCData->setTotalReservoirVolume(vt);
	//cout << "Number of domains: " << setOfDomain.size() << ". They are: ";
//	for( iter = setOfDomain.begin(); iter!=setOfDomain.end(); iter++){
//		cout << *iter << "  ";
//	}
//	cout << endl;

	validete_coefficients(theMesh,setOfDomain,pGCData);

#ifdef TRACKING_PROGRAM_STEPS
	cout << "TRACKING_PROGRAM_STEPS: EBFV1_preprocessor_2D\tOUT\n";
#endif
	return 0;
}
void getFCenter(pFace face, double *center){
	vector<pVertex> vertex;
	M_GetVertices(face,vertex);
	getFCenter(vertex[0],vertex[1],vertex[2],center);
	vertex.clear();
}
Beispiel #5
0
void Transform::setCenter( const vgm::Vec3f center )
{
	getFieldRW<FCenterType>(getFCenter())->setValue( center );
}
Beispiel #6
0
const vgm::Vec3f Transform::getCenter( void ) const
{
	return ( getFieldRO<FCenterType>(getFCenter())->getValue() );
}
// Calculates Cij, Dij(boundary faces) and nodal volume. It also works for multi domains meshes
int EBFV1_preprocessor_3D(pMesh theMesh, void *pData, int &ndom){
	PetscPrintf(PETSC_COMM_WORLD,"Starting EBFV1-3D pre-processor...");

	GeomData *pGCData = (GeomData*)pData;
	pGCData->setMeshDim(theMesh->getDim());
	if (theMesh->getDim() != 3){
		throw Exception(__LINE__,__FILE__,"Only 3-D meshes are allowed. Exiting...\n");
	}

	theMesh->modifyState(3,2);
	theMesh->modifyState(2,3);

	pEntity tetra, edge, face;
	int i,j,k,K,m;
	double tCenter[3], eCenter[3], v[3], *vec[2], val, *tetraFCenter[4];
	double normal[3], I[3], J[3], IJ[3], proj[3];

	// allocate vectors
	for (i=0; i<4; i++) tetraFCenter[i] = new double[3];
	for (i=0; i<2; i++) vec[i] = new double[3];

	// Search over all tetrahedra flags set to define domains. Store all flags on a list and initialize Cij vector
	std::set<int> setOfDomain;
	std::vector<double> Cij(3,.0);
	RIter rit = M_regionIter(theMesh);
	while ( (tetra = RIter_next(rit)) ){
		int flag = GEN_tag(tetra->getClassification());
		setOfDomain.insert( flag );
		for (i=0; i<6; i++){
			edge = (pEntity)tetra->get(1,i);
			pGCData->setCij(edge,flag,Cij);
		}
	}
	RIter_delete(rit);

	// mark faces (boundary)
	bool detectBdryFaces = false;
	std::set<int>::iterator iter = setOfDomain.begin();
	for (; iter != setOfDomain.end(); iter++){
		int countBDRYFaces = 0;
		int dom = *iter;
		char dom_string[256]; sprintf(dom_string,"dom_str_%d",dom);
		RIter rit = M_regionIter(theMesh);
		while ( (tetra = RIter_next(rit)) ){
			int tetraflag = GEN_tag(tetra->getClassification());
			if (tetraflag==dom){
				for (i=0;i<4;i++){
					face = (pFace)tetra->get(2,i);
					int faceflag = GEN_tag(face->getClassification());
					// if flags are different, then face in on boundary
					if (faceflag!=tetraflag){
						detectBdryFaces = true;
						countBDRYFaces++;
						// set edge belonging to domain 'dom'
						EN_attachDataInt(face,MD_lookupMeshDataId( dom_string ),1);
					}
				}
			}
		}
		RIter_delete(rit);
	}
	//throw 1;

	if (!detectBdryFaces){
		throw Exception(__LINE__,__FILE__,"Any boundary face (triangles) were detected. Boundary elements MUST have different flag of internal elements.");
	}

	/// initialize weighted volume
	VIter vit = M_vertexIter(theMesh);
	while (pEntity v = VIter_next(vit))
		pGCData->setWeightedVolume(v,0.0);
	VIter_delete(vit);

	vector<pVertex> tetraVertex(4), edgeVertex(2);
	double vt = .0; // total volume

	// loop over elements
	// for each element:	1 - calculate Cij for each edge and store them on the respective edge
	//						2 - calculate element contribution to volume of control volume
//	PetscPrintf(PETSC_COMM_WORLD,"Loop over tetras - start...  ");MPI_Barrier(MPI_COMM_WORLD);
	rit = M_regionIter(theMesh);
	while ( (tetra = RIter_next(rit)) ){
		// get all four tetrahedron's vertices
		for (i=0; i<4; i++){
			tetraVertex[i] = (pEntity)tetra->get(0,i);
		}

		int tetraFaces[4][3] = { {EN_id(tetraVertex[0]),EN_id(tetraVertex[1]),EN_id(tetraVertex[2])},
				{EN_id(tetraVertex[0]),EN_id(tetraVertex[1]),EN_id(tetraVertex[3])},
				{EN_id(tetraVertex[0]),EN_id(tetraVertex[2]),EN_id(tetraVertex[3])},
				{EN_id(tetraVertex[1]),EN_id(tetraVertex[2]),EN_id(tetraVertex[3])}};

		getFCenter(tetraVertex[0], tetraVertex[1], tetraVertex[2], tetraFCenter[0]);
		getFCenter(tetraVertex[0], tetraVertex[1], tetraVertex[3], tetraFCenter[1]);
		getFCenter(tetraVertex[0], tetraVertex[2], tetraVertex[3], tetraFCenter[2]);
		getFCenter(tetraVertex[1], tetraVertex[2], tetraVertex[3], tetraFCenter[3]);

		// get tetrahedron center
		tCenter[0] = tCenter[1] = tCenter[2] = .0;
		R_center(tetra,tCenter);

		double coord1[3]; V_coord(tetraVertex[0],coord1);
		double coord2[3]; V_coord(tetraVertex[1],coord2);
		double coord3[3]; V_coord(tetraVertex[2],coord3);
		double coord4[3]; V_coord(tetraVertex[3],coord4);

		// step #1: Cij
		// identify which domain the current tetrahedron belongs to
		// edges on domain's partition have differents Cij, one for each domain
		const int dom = GEN_tag(tetra->getClassification());
		char dom_string[256]; sprintf(dom_string,"dom_str_%d",dom);
		markTetraBdryFaces(theMesh,tetra,dom);
		setOfDomain.insert(dom); // store every new domain

		for (int pos1=0; pos1<3; pos1++){
			for (int pos2=pos1+1; pos2<4; pos2++){
				edge = (pEdge)theMesh->getEdge((mVertex*)tetraVertex[pos1],(mVertex*)tetraVertex[pos2]);

				// set edge belonging to domain 'dom'
				EN_attachDataInt(edge,MD_lookupMeshDataId( dom_string ),1);


				//M_GetVertices(edge,edgeVertex);
				for (i=0; i<2; i++) edgeVertex[i] = (pEntity)edge->get(0,i);
				// edge's Cij is the sum of two vectors. Both are orthogonals to planes
				// defined by three vectors. They are:
				// v - ec->tc:		edge center to tetra center
				// vec[0] - ec->fcr:	edge center to right face center
				// vec[1] - ec->fcl:	edge center to left face center
				// Cij = (v)x(vec[0]) + (v)x(vec[1]), Cij points to outside of control volume

				// create vector v:
				for (i=0; i<3; i++) I[i] = J[i]= .0;
				V_coord(edgeVertex[0],I);
				V_coord(edgeVertex[1],J);

				double sign = ( EN_id(edgeVertex[0]) > EN_id(edgeVertex[1]) )?-1.0:1.0;
				for (i=0; i<3; i++){
					IJ[i] = sign*(J[i] - I[i]);
				}

				// get edge center
				eCenter[0] = eCenter[1] = eCenter[2] = .0;
				for (i=0; i<3; i++){
					eCenter[i] = .5*(I[i]+J[i]);
				}

				// create vector v: from edge middle point to tetrahedral centroid
				for (i=0; i<3; i++){
					v[i] = tCenter[i] - eCenter[i];
				}

				// search for tetra faces that share the same edge and get their centers. Of course, there are only two faces
				// sharing the same edge. FMDB can do this job easily, but for 3D big meshes a face structure has a high memory cost.

				K = 0;
				// loop over tetra's faces
				for (i=0; i<4; i++){
					// loop over face's vertices
					for (j=0; j<3; j++){
						if (EN_id(edgeVertex[0]) == tetraFaces[i][j]){
							for (k=0; k<3; k++){
								if (EN_id(edgeVertex[1])==tetraFaces[i][k]){
									for (m=0; m<3; m++) vec[K][m] = -eCenter[m] + tetraFCenter[i][m];
									K++;
								}
							}
						}
					}
				}

				// IJ vector is a reference to Cij. IJ points from node I to node J
				// where: I_id < J_id
				// vec projections on edge IJ must have the same orientation as IJ vector
				double n = sqrt( IJ[0]*IJ[0] + IJ[1]*IJ[1] + IJ[2]*IJ[2] ) ;

				// Cij calculation n ;
				for (j=0; j<3; j++){
					Cij[j] = .0;
				}
				pGCData->getCij(edge,dom,Cij);
				double normal1[3], normal2[3];
				cross(v,vec[0],normal1);
				cross(vec[1],v,normal2);

				for (j=0; j<3; j++){
					proj[j] = .0;
				}
				for (j=0; j<3; j++){
					normal[j] = .5*(normal1[j]+normal2[j]);
				}
				val = dot(normal,IJ)/(n*n);
				for (j=0; j<3; j++){
					proj[j] = val*IJ[j];
				}
				double sinal = (dot(proj,IJ)<.0)?-1.:1.;
				for (j=0; j<3; j++){
					Cij[j] += sinal*normal[j];
				}
				pGCData->setCij(edge,dom,Cij);
			}
		}

		// step #2: volume of control volume
		const double porosity = .0;
		const double tetraVolume = R_Volume(tetra);
		const double nodalVolume = .25*tetraVolume;
		vt = +tetraVolume;

		for (i=0; i<4; i++){
			// total nodal volume
			double v1 = pGCData->getVolume(tetraVertex[i],dom);
			v1 += nodalVolume;
			pGCData->setVolume(tetraVertex[i],dom,v1);
			double v2 = pGCData->getWeightedVolume(tetraVertex[i]);
			v2 += nodalVolume*porosity;
			pGCData->setWeightedVolume(tetraVertex[i],v2);
		}
	}
	RIter_delete(rit);	// END TETRAHEDRALS LOOP
	pGCData->setTotalReservoirVolume(vt);
	//PetscPrintf(PETSC_COMM_WORLD,"Finished\n");MPI_Barrier(MPI_COMM_WORLD);

	// deallocate vectors
	for (i=0; i<4; i++) delete[] tetraFCenter[i];
	for (i=0; i<2; i++) delete[] vec[i];

	/*
	 * Dij vector calculation. A loop over all boundary (external/internal) faces is made. Depending on how FMDB is used, faces on all
	 * tetrahedrals may be created and they must be filtered. If a face does not belong to boundary it will assume the tetrahedral domain
	 * flag. This value is greater than 3000 and is used to filter them from those provided by mesh file.
	 */

	int count = 0;
	dblarray Dij(3,.0);
	//PetscPrintf(PETSC_COMM_WORLD,"Loop over boundary faces - start... ");///MPI_Barrier(MPI_COMM_WORLD);
	if ( M_numFaces(theMesh) != 0 ){
		FIter fit = M_faceIter(theMesh);
		while ( (face = FIter_next(fit)) ){
			int flag = GEN_tag(face->getClassification());
			iter = setOfDomain.find(flag);
			// get only faces built over surfaces defined by user in geometric model
			// it only work if surface flags defined by user are different from those set to tetrahedrals
			if ( iter==setOfDomain.end() ){
				computeDij(theMesh,face,pGCData);
			}
		}
		FIter_delete(fit);
	}
	//PetscPrintf(PETSC_COMM_WORLD,"Finished\n");MPI_Barrier(MPI_COMM_WORLD);
	calculateEdgeLength(theMesh,pGCData);
	calculateCijNorm(theMesh,pGCData,setOfDomain);
	identifyBoundaryElements(theMesh,pGCData,setOfDomain);
	i = 0;
	ndom = (int)setOfDomain.size();
	int *domlist = new int[ndom];
	for(iter = setOfDomain.begin(); iter!=setOfDomain.end(); iter++){
		domlist[i++] =  *iter;
	}

	PetscPrintf(PETSC_COMM_WORLD," finished.\n");
	cout << "-------------------------------------------------------------------------------------------------------------------------\n\n";
	return 0;
}