コード例 #1
0
void PeriodicFlow<_Tesselation>::interpolate(Tesselation& Tes, Tesselation& NewTes)
{
        CellHandle oldCell;
        RTriangulation& Tri = Tes.Triangulation();
	for (VCellIterator cellIt=NewTes.cellHandles.begin(); cellIt!=NewTes.cellHandles.end(); cellIt++){
		CellHandle& newCell = *cellIt;
		if (newCell->info().Pcondition || newCell->info().isGhost) continue;
		CVector center ( 0,0,0 );
		if (newCell->info().fictious()==0) for ( int k=0;k<4;k++ ) center= center + 0.25* (Tes.vertex(newCell->vertex(k)->info().id())->point()-CGAL::ORIGIN);
		else {
			Real boundPos=0; int coord=0;
			for ( int k=0;k<4;k++ ) {
				if (!newCell->vertex (k)->info().isFictious) center= center+0.3333333333*(Tes.vertex(newCell->vertex(k)->info().id())->point()-CGAL::ORIGIN);
				else {
					coord=boundary (newCell->vertex(k)->info().id()).coordinate;
					boundPos=boundary (newCell->vertex(k)->info().id()).p[coord];
				}
			}
			center=CVector(coord==0?boundPos:center[0],coord==1?boundPos:center[1],coord==2?boundPos:center[2]);
		}
                oldCell = Tri.locate(Point(center[0],center[1],center[2]));
		//FIXME: should use getInfo
                newCell->info().p() = oldCell->info().shiftedP();
        }
//  	Tes.Clear();//Don't reset to avoid segfault when getting pressure in scripts just after interpolation
}
コード例 #2
0
/******************************************************************************
* /// Determines whether the given tetrahedral cell is a ghost cell (or an invalid cell).
******************************************************************************/
bool DelaunayTessellation::isGhostCell(CellHandle cell) const
{
	// Find head vertex with the lowest index.
	const auto& p0 = cell->vertex(0)->point();
	int headVertex = p0.index();
	if(headVertex == -1) {
		OVITO_ASSERT(!isValidCell(cell));
		return true;
	}
	bool isGhost = p0.isGhost();
	for(int v = 1; v < 4; v++) {
		const auto& p = cell->vertex(v)->point();
		if(p.index() == -1) {
			OVITO_ASSERT(!isValidCell(cell));
			return true;
		}
		if(p.index() < headVertex) {
			headVertex = p.index();
			isGhost = p.isGhost();
		}
	}

	OVITO_ASSERT(isValidCell(cell));
	return isGhost;
}
コード例 #3
0
	/**
	 * Returns unity normal to contact surface between given cells
	 * (must be neighbors). Direction of normal is from "from" to "to"
	 */
	static RealD contactNormal(const CellHandle from, const CellHandle to) {
		int oppositeVertexIndex = from->index(to);
		
		VertexHandle cw = from->vertex(Triangulation::cw(oppositeVertexIndex));
		VertexHandle ccw = from->vertex(Triangulation::ccw(oppositeVertexIndex));
		
		RealD along = realD(cw->point()) - realD(ccw->point());
		return linal::normalize(
				linal::perpendicularClockwise(along));
	}
コード例 #4
0
	static int otherVertexIndex(
			const CellHandle cell, const VertexHandle a, const VertexHandle b) {
	/// return index of that vertex of cell, which is not a, b
		for (int i = 0; i < CELL_SIZE; i++) {
			VertexHandle d = cell->vertex(i);
			if ( (d != a) && (d != b) ) { return i; }
		}
		THROW_BAD_MESH("Cell contains equal vertices");
	}
コード例 #5
0
	/**
	 * The point q must lie inside the triangle t.
	 * Find the edge of t which is crossed by the ray qp.
	 * Write the result as a pair of vertices to a,b (or NULLs if not found).
	 * Degenerate cases are not handled.
	 */
	static void findCrossedInsideOutFacet(
			const CellHandle t, const Real2 q, const Real2 p,
			VertexHandle& a, VertexHandle& b, const real eps) {
		a = NULL; b = NULL;
		for (int i = 0; i < CELL_SIZE; i++) {
			VertexHandle a1 = t->vertex((i + 1) % CELL_SIZE);
			VertexHandle b1 = t->vertex((i + 2) % CELL_SIZE);
			if (linal::angleContains(q, realD(a1), realD(b1), p, eps)) {
				a = a1; b = b1; break;
			}
		}
	}
コード例 #6
0
void Foam::DelaunayMeshTools::drawDelaunayCell
(
    Ostream& os,
    const CellHandle& c,
    label offset
)
{
    // Supply offset as tet number
    offset *= 4;

    os  << "# cell index: " << label(c->cellIndex())
        << " INT_MIN = " << INT_MIN
        << endl;

    os  << "# circumradius "
        << mag(c->dual() - topoint(c->vertex(0)->point()))
        << endl;

    for (int i = 0; i < 4; i++)
    {
        os  << "# index / type / procIndex: "
            << label(c->vertex(i)->index()) << " "
            << label(c->vertex(i)->type()) << " "
            << label(c->vertex(i)->procIndex())
            <<
                (
                    CGAL::indexedVertexOps::uninitialised(c->vertex(i))
                  ? " # This vertex is uninitialised!"
                  : ""
                )
            << endl;

        meshTools::writeOBJ(os, topoint(c->vertex(i)->point()));
    }

    os  << "f " << 1 + offset << " " << 3 + offset << " " << 2 + offset << nl
        << "f " << 2 + offset << " " << 3 + offset << " " << 4 + offset << nl
        << "f " << 1 + offset << " " << 4 + offset << " " << 3 + offset << nl
        << "f " << 1 + offset << " " << 2 + offset << " " << 4 + offset << endl;

//    os  << "# cicumcentre " << endl;

//    meshTools::writeOBJ(os, c->dual());

//    os  << "l " << 1 + offset << " " << 5 + offset << endl;
}
コード例 #7
0
	static VertexHandle otherVertex(
			const CellHandle cell, const VertexHandle a, const VertexHandle b) {
	/// return that vertex of cell, which is not a, b
		return cell->vertex(otherVertexIndex(cell, a, b));
	}
コード例 #8
0
	static CellHandle neighborThrough(
			const CellHandle cell, const VertexHandle a, const VertexHandle b) {
	/// return neighbor cell that shares with given cell vertices a, b
		return cell->neighbor(otherVertexIndex(cell, a, b));
	}
コード例 #9
0
	/** The center of the given cell */
	static RealD center(const CellHandle t) {
		RealD a = realD(t->vertex(0));
		RealD b = realD(t->vertex(1));
		RealD c = realD(t->vertex(2));
		return (a + b + c) / 3;
	}
コード例 #10
0
	/** Is the cell with a small layer around contains the point */
	static bool contains(const CellHandle ch, const RealD& q, const real eps) {
		RealD a = realD(ch->vertex(0));
		RealD b = realD(ch->vertex(1));
		RealD c = realD(ch->vertex(2));
		return linal::triangleContains(a, b, c, q, eps);
	}
コード例 #11
0
	static real minimalCellHeight(const CellHandle ch) {
		return linal::minimalHeight(
				realD(ch->vertex(0)->point()),
				realD(ch->vertex(1)->point()),
				realD(ch->vertex(2)->point()));
	}
コード例 #12
0
void PeriodicFlow<_Tesselation>::computePermeability()
{
	if (debugOut)  cout << "----Computing_Permeability (Periodic)------" << endl;
	RTriangulation& Tri = T[currentTes].Triangulation();
	VSolidTot = 0, Vtotalissimo = 0, vPoral = 0, sSolidTot = 0, vTotalPorosity=0, vPoralPorosity=0;
	CellHandle neighbourCell;

	double k=0, distance = 0, radius = 0;
	int surfneg=0; int NEG=0, POS=0, pass=0;
	Real meanK=0, STDEV=0, meanRadius=0, meanDistance=0;
	Real infiniteK=1e3;
	double volume_sub_pore = 0.f;
	VectorCell& cellHandles= T[currentTes].cellHandles;
	for (VCellIterator cellIt=T[currentTes].cellHandles.begin(); cellIt!=T[currentTes].cellHandles.end(); cellIt++){
			CellHandle& cell = *cellIt;
			Point& p1 = cell->info();
			if (cell->info().blocked) {
				this->setBlocked(cell);}
			if (cell->info().isGhost) {cerr<<"skipping a ghost"<<endl; continue;}
			for (int j=0; j<4; j++){
				neighbourCell = cell->neighbor(j);
				Point& p2 = neighbourCell->info();
				if (!Tri.is_infinite(neighbourCell) /*&& (neighbour_cell->info().isvisited==ref || computeAllCells)*/) {
					//compute and store the area of sphere-facet intersections for later use
					VertexHandle W [3];
					for (int kk=0; kk<3; kk++) {
						W[kk] = cell->vertex(facetVertices[j][kk]);
					}
					Sphere& v0 = W[0]->point();
					Sphere& v1 = W[1]->point();
					Sphere& v2 = W[2]->point();
#ifdef USE_FAST_MATH
					//FIXME : code not compiling,, do the same as in "else"
					assert((W[permut3[jj][1]]->point()-W[permut3[jj][0]]->point())*(W[permut3[jj][2]]->point()-W[permut3[jj][0]]->point())>=0 && (W[permut3[jj][1]]->point()-W[permut3[jj][0]]->point())*(W[permut3[jj][2]]->point()-W[permut3[jj][0]]->point())<=1);
					for (int jj=0;jj<3;jj++)
						cell->info().facetSphereCrossSections[j][jj]=0.5*W[jj]->point().weight()*Wm3::FastInvCos1((W[permut3[jj][1]]->point()-W[permut3[jj][0]]->point())*(W[permut3[jj][2]]->point()-W[permut3[jj][0]]->point()));
#else
					cell->info().facetSphereCrossSections[j]=CVector(
					W[0]->info().isFictious ? 0 : 0.5*v0.weight()*acos((v1-v0)*(v2-v0)/sqrt((v1-v0).squared_length()*(v2-v0).squared_length())),
					W[1]->info().isFictious ? 0 : 0.5*v1.weight()*acos((v0-v1)*(v2-v1)/sqrt((v1-v0).squared_length()*(v2-v1).squared_length())),
					W[2]->info().isFictious ? 0 : 0.5*v2.weight()*acos((v0-v2)*(v1-v2)/sqrt((v1-v2).squared_length()*(v2-v0).squared_length())));
#endif
					//FIXME: it should be possible to skip completely blocked cells, currently the problem is it segfault for undefined areas
					//if (cell->info().blocked) continue;//We don't need permeability for blocked cells, it will be set to zero anyway

					pass+=1;
					CVector l = p1 - p2;
					distance = sqrt(l.squared_length());
					if (!rAverage) radius = 2* this->computeHydraulicRadius(cell, j);
					else radius = (this->computeEffectiveRadius(cell, j)+this->computeEquivalentRadius(cell,j))*0.5;
					if (radius<0) NEG++;
					else POS++;
					if (radius==0) {
						cout << "INS-INS PROBLEM!!!!!!!" << endl;
					}
					Real fluidArea=0;
					int test=0;
					if (distance!=0) {
						if (minPermLength>0 && distanceCorrection) distance=max(minPermLength*radius,distance);
						const CVector& Surfk = cell->info().facetSurfaces[j];
						Real area = sqrt(Surfk.squared_length());
						const CVector& crossSections = cell->info().facetSphereCrossSections[j];
						Real S0=0;
						S0=checkSphereFacetOverlap(v0,v1,v2);
						if (S0==0) S0=checkSphereFacetOverlap(v1,v2,v0);
						if (S0==0) S0=checkSphereFacetOverlap(v2,v0,v1);
						//take absolute value, since in rare cases the surface can be negative (overlaping spheres)
						fluidArea=abs(area-crossSections[0]-crossSections[1]-crossSections[2]+S0);
						cell->info().facetFluidSurfacesRatio[j]=fluidArea/area;
						// kFactor<0 means we replace Poiseuille by Darcy localy, yielding a particle size-independent bulk conductivity
						if (kFactor>0) cell->info().kNorm()[j]= kFactor*(fluidArea * pow(radius,2)) / (8*viscosity*distance);
						else cell->info().kNorm()[j]= -kFactor * area / distance;						
						meanDistance += distance;
						meanRadius += radius;
						meanK +=  (cell->info().kNorm())[j];

						if (k<0 && debugOut) {surfneg+=1; cout<<"__ k<0 __"<<k<<" "<<" fluidArea "<<fluidArea<<" area "<<area<<" "<<crossSections[0]<<" "<<crossSections[1]<<" "<<crossSections[2] <<" "<<W[0]->info().id()<<" "<<W[1]->info().id()<<" "<<W[2]->info().id()<<" "<<p1<<" "<<p2<<" test "<<test<<endl;}
					} else  {cout <<"infinite K2! surfaces will be missing (FIXME)"<<endl; k = infiniteK;}
					//Will be corrected in the next loop
					if (!neighbourCell->info().isGhost) (neighbourCell->info().kNorm())[Tri.mirror_index(cell, j)]= (cell->info().kNorm())[j];
					//The following block is correct but not very usefull, since all values are clamped below with MIN and MAX, skip for now
// 					else {//find the real neighbor connected to our cell through periodicity
// 						CellHandle true_neighbour_cell = cellHandles[neighbour_cell->info().baseIndex];
// 						for (int ii=0;ii<4;ii++)
// 							if (true_neighbour_cell->neighbor(ii)->info().index == cell->info().index){
// 								(true_neighbour_cell->info().kNorm())[ii]=(cell->info().kNorm())[j]; break;
// 							}
// 					}
					if(permeabilityMap){
						CellHandle c = cell;
						cell->info().s = cell->info().s + k*distance/fluidArea*this->volumePoreVoronoiFraction (c,j);
						volume_sub_pore += this->volumePoreVoronoiFraction (c,j);
					}
				}
			}
// 			cell->info().isvisited = !ref;
			if(permeabilityMap){
				cell->info().s = cell->info().s/volume_sub_pore;
				volume_sub_pore = 0.f;
			}
// 		}
	} 
	
	
	if (debugOut) cout<<"surfneg est "<<surfneg<<endl;
	meanK /= pass;
	meanRadius /= pass;
	meanDistance /= pass;
	Real globalK=kFactor*meanDistance*vPoral/(sSolidTot*8.*viscosity);//An approximate value of macroscopic permeability, for clamping local values below
	if (debugOut) {
		cout << "PassCompK = " << pass << endl;
		cout << "meanK = " << meanK << endl;
		cout << "globalK = " << globalK << endl;
		cout << "maxKdivKmean*globalK = " << maxKdivKmean*globalK << endl;
		cout << "minKdivKmean*globalK = " << minKdivKmean*globalK << endl;
		cout << "meanTubesRadius = " << meanRadius << endl;
		cout << "meanDistance = " << meanDistance << endl;
	}
	pass=0;
	if (clampKValues) for (VCellIterator cellIt=T[currentTes].cellHandles.begin(); cellIt!=T[currentTes].cellHandles.end(); cellIt++){
		CellHandle& cell = *cellIt;
		for (int j=0; j<4; j++) {
			neighbourCell = cell->neighbor(j);
			if (!Tri.is_infinite(neighbourCell) /*&& neighbour_cell->info().isvisited==ref*/) {
				pass++;
				(cell->info().kNorm())[j] = max(minKdivKmean*globalK, min((cell->info().kNorm())[j], maxKdivKmean*globalK));
				(neighbourCell->info().kNorm())[Tri.mirror_index(cell, j)]=(cell->info().kNorm())[j];
				if (!neighbourCell->info().isGhost) (neighbourCell->info().kNorm())[Tri.mirror_index(cell, j)]= (cell->info().kNorm())[j];
					else {//find the real neighbor connected to our cell through periodicity, as we want exactly the same permeability without rounding errors
						CellHandle& true_neighbourCell = cellHandles[neighbourCell->info().baseIndex];
						for (int ii=0;ii<4;ii++)
							if (true_neighbourCell->neighbor(ii)->info().index == cell->info().index){
								(true_neighbourCell->info().kNorm())[ii]=(cell->info().kNorm())[j]; break;
							}
					}

			}
		}
	}
	if (debugOut) cout << "PassKcorrect = " << pass << endl;

	if (debugOut) cout << "POS = " << POS << " NEG = " << NEG << " pass = "******"k_stdev.txt" ,std::ios::out);
		pass=0;
		FiniteCellsIterator cellEnd = Tri.finite_cells_end();
		for (FiniteCellsIterator cell = Tri.finite_cells_begin(); cell != cellEnd; cell++) {
			for (int j=0; j<4; j++) {
				neighbourCell = cell->neighbor(j);
				if (!Tri.is_infinite(neighbourCell) /*&& neighbour_cell->info().isvisited==ref*/) {
					pass++;
					STDEV += pow(((cell->info().kNorm())[j]-meanK),2);
				}
			}
		}
		STDEV = sqrt(STDEV/pass);
		if (debugOut) cout << "PassSTDEV = " << pass << endl;
		cout << "STATISTIC K" << endl;
		double k_min = 0, k_max = meanK + KOptFactor*STDEV;
		cout << "Kmoy = " << meanK << " Standard Deviation = " << STDEV << endl;
		cout << "kmin = " << k_min << " kmax = " << k_max << endl;
		pass=0;
		for (FiniteCellsIterator cell = Tri.finite_cells_begin(); cell != cellEnd; cell++) {
			for (int j=0; j<4; j++) {
				neighbourCell = cell->neighbor(j);
				if (!Tri.is_infinite(neighbourCell) /*&& neighbour_cell->info().isvisited==ref*/) {
					pass+=1;
					if ((cell->info().kNorm())[j]>k_max) {
						(cell->info().kNorm())[j]=k_max;
						(neighbourCell->info().kNorm())[Tri.mirror_index(cell, j)]= (cell->info().kNorm())[j];
					}
					k_opt_file << KOptFactor << " " << (cell->info().kNorm())[j] << endl;
				}
			}
		}
		if (debugOut) cout << "PassKopt = " << pass << endl;
	}
	if (debugOut) {
		FiniteVerticesIterator verticesEnd = Tri.finite_vertices_end();
		Real Vgrains = 0;
		int grains=0;

		for (FiniteVerticesIterator vIt = Tri.finite_vertices_begin(); vIt !=  verticesEnd; vIt++) {
			if (!vIt->info().isFictious && !vIt->info().isGhost) {
				grains +=1;
				Vgrains += 1.33333333 * M_PI * pow(vIt->point().weight(),1.5);
			}
		}
		cout<<grains<<"grains - " <<"vTotal = " << vTotal << " Vgrains = " << Vgrains << " vPoral1 = " << (vTotal-Vgrains) << endl;
		cout << "Vtotalissimo = " << Vtotalissimo/2 << " VSolidTot = " << VSolidTot/2 << " vPoral2 = " << vPoral/2  << " sSolidTot = " << sSolidTot << endl<< endl;

		if (!rAverage) cout << "------Hydraulic Radius is used for permeability computation------" << endl << endl;
		else cout << "------Average Radius is used for permeability computation------" << endl << endl;
		cout << "-----computed_Permeability Periodic-----" << endl;
	}
}