inline double UpscalerBase<Traits>::computeDelta(const int flow_dir) const { double side1_pos = 0.0; double side2_pos = 0.0; double side1_area = 0.0; double side2_area = 0.0; for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) { for (FaceIter f = c->facebegin(); f != c->faceend(); ++f) { if (f->boundary()) { int canon_bid = bcond_.getCanonicalBoundaryId(f->boundaryId()); if ((canon_bid - 1)/2 == flow_dir) { double area = f->area(); double pos_comp = f->centroid()[flow_dir]; if (canon_bid - 1 == 2*flow_dir) { side1_pos += area*pos_comp; side1_area += area; } else { side2_pos += area*pos_comp; side2_area += area; } } } } } // delta is the average length. return side2_pos/side2_area - side1_pos/side1_area; }
void Mesh::normalize() { // compute center of mass Eigen::Vector3d cm = Eigen::Vector3d::Zero(); for (VertexCIter v = vertices.begin(); v != vertices.end(); v++) { cm += v->position; } cm /= (double)vertices.size(); // translate to origin for (VertexIter v = vertices.begin(); v != vertices.end(); v++) { v->position -= cm; } // determine radius double rMax = 0; for (VertexCIter v = vertices.begin(); v != vertices.end(); v++) { rMax = std::max(rMax, v->position.norm()); } // rescale to unit sphere for (VertexIter v = vertices.begin(); v != vertices.end(); v++) { v->position /= rMax; } for (FaceIter f = faces.begin(); f != faces.end(); f++) { f->computeFeatures(); } }
Vector Vertex::normalAngleWeighted( void ) const // returns unit vertex normal using tip angle weights { Vector N(0.,0.,0.); HalfEdgeIter heBegin, he; FaceIter face; const Vector& p_i = this->position; Vector vec1, vec2; he = this->he->flip; vec1 = (he->vertex->position - p_i).unit(); face = he->face; he = heBegin = he->next->flip; do { vec2 = (he->vertex->position - p_i).unit(); N += face->normal() * atan2( cross(vec1,vec2).norm(), -dot(vec1,vec2) ); vec1 = vec2; face = he->face; he = he->next->flip; } while( he != heBegin ); return N.unit(); }
const HalfedgeMesh& HalfedgeMesh :: operator=( const HalfedgeMesh& mesh ) // The assignment operator does a "deep" copy of the halfedge mesh data structure; in // other words, it makes new instances of each mesh element, and ensures that pointers // in the copy point to the newly allocated elements rather than elements in the original // mesh. This behavior is especially important for making assignments, since the mesh // on the right-hand side of an assignment may be temporary (hence any pointers to elements // in this mesh will become invalid as soon as it is released.) { // Clear any existing elements. halfedges.clear(); vertices.clear(); edges.clear(); faces.clear(); boundaries.clear(); // These maps will be used to identify elements of the old mesh // with elements of the new mesh. (Note that we can use a single // map for both interior and boundary faces, because the map // doesn't care which list of faces these iterators come from.) map< HalfedgeCIter, HalfedgeIter > halfedgeOldToNew; map< VertexCIter, VertexIter > vertexOldToNew; map< EdgeCIter, EdgeIter > edgeOldToNew; map< FaceCIter, FaceIter > faceOldToNew; // Copy geometry from the original mesh and create a map from // pointers in the original mesh to those in the new mesh. for( HalfedgeCIter h = mesh.halfedgesBegin(); h != mesh.halfedgesEnd(); h++ ) halfedgeOldToNew[ h ] = halfedges.insert( halfedges.end(), *h ); for( VertexCIter v = mesh.verticesBegin(); v != mesh.verticesEnd(); v++ ) vertexOldToNew[ v ] = vertices.insert( vertices.end(), *v ); for( EdgeCIter e = mesh.edgesBegin(); e != mesh.edgesEnd(); e++ ) edgeOldToNew[ e ] = edges.insert( edges.end(), *e ); for( FaceCIter f = mesh.facesBegin(); f != mesh.facesEnd(); f++ ) faceOldToNew[ f ] = faces.insert( faces.end(), *f ); for( FaceCIter b = mesh.boundariesBegin(); b != mesh.boundariesEnd(); b++ ) faceOldToNew[ b ] = boundaries.insert( boundaries.end(), *b ); // "Search and replace" old pointers with new ones. for( HalfedgeIter he = halfedgesBegin(); he != halfedgesEnd(); he++ ) { he->next() = halfedgeOldToNew[ he->next() ]; he->twin() = halfedgeOldToNew[ he->twin() ]; he->vertex() = vertexOldToNew[ he->vertex() ]; he->edge() = edgeOldToNew[ he->edge() ]; he->face() = faceOldToNew[ he->face() ]; } for( VertexIter v = verticesBegin(); v != verticesEnd(); v++ ) v->halfedge() = halfedgeOldToNew[ v->halfedge() ]; for( EdgeIter e = edgesBegin(); e != edgesEnd(); e++ ) e->halfedge() = halfedgeOldToNew[ e->halfedge() ]; for( FaceIter f = facesBegin(); f != facesEnd(); f++ ) f->halfedge() = halfedgeOldToNew[ f->halfedge() ]; for( FaceIter b = boundariesBegin(); b != boundariesEnd(); b++ ) b->halfedge() = halfedgeOldToNew[ b->halfedge() ]; // Return a reference to the new mesh. return *this; }
double UpscalerBase<Traits>::computeAverageVelocity(const FlowSol& flow_solution, const int flow_dir, const int pdrop_dir) const { double side1_flux = 0.0; double side2_flux = 0.0; double side1_area = 0.0; double side2_area = 0.0; int num_faces = 0; int num_bdyfaces = 0; int num_side1 = 0; int num_side2 = 0; for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) { for (FaceIter f = c->facebegin(); f != c->faceend(); ++f) { ++num_faces; if (f->boundary()) { ++num_bdyfaces; int canon_bid = bcond_.getCanonicalBoundaryId(f->boundaryId()); if ((canon_bid - 1)/2 == flow_dir) { double flux = flow_solution.outflux(f); double area = f->area(); double norm_comp = f->normal()[flow_dir]; // std::cout << "bid " << f->boundaryId() << " area " << area << " n " << norm_comp << std::endl; if (canon_bid - 1 == 2*flow_dir) { ++num_side1; if (flow_dir == pdrop_dir && flux > 0.0) { #ifdef VERBOSE std::cerr << "Flow may be in wrong direction at bid: " << f->boundaryId()<<" (canonical: "<<canon_bid << ") Magnitude: " << std::fabs(flux) << std::endl; #endif // OPM_THROW(std::runtime_error, "Detected outflow at entry face: " << face); } side1_flux += flux*norm_comp; side1_area += area; } else { assert(canon_bid - 1 == 2*flow_dir + 1); ++num_side2; if (flow_dir == pdrop_dir && flux < 0.0) { #ifdef VERBOSE std::cerr << "Flow may be in wrong direction at bid: " << f->boundaryId() << " Magnitude: " << std::fabs(flux) << std::endl; #endif // OPM_THROW(std::runtime_error, "Detected inflow at exit face: " << face); } side2_flux += flux*norm_comp; side2_area += area; } } } } } // std::cout << "Faces: " << num_faces << " Boundary faces: " << num_bdyfaces // << " Side 1 faces: " << num_side1 << " Side 2 faces: " << num_side2 << std::endl; // q is the average velocity. return 0.5*(side1_flux/side1_area + side2_flux/side2_area); }
void Mesh::constructDirectionFields() { for (FaceIter f = faces.begin(); f != faces.end(); f++) { f->parent = f; } // traverse faces in any order FaceIter root = faces.begin() + (rand() % faces.size()); root->beta = 0; std::queue<FaceIter> queue; queue.push(root); while (!queue.empty()) { FaceIter f1 = queue.front(); queue.pop(); HalfEdgeIter he = f1->he; do { FaceIter f2 = he->flip->face; if (f2 != root && f2->parent == f2) { f2->parent = f1; double phi = he == he->edge->he ? he->edge->phi : -he->edge->phi; f2->beta = connectionAngle(f1->beta, he) - phi; queue.push(f2); } he = he->next; } while (he != f1->he); } for (FaceIter f = faces.begin(); f != faces.end(); f++) { Eigen::Vector3d localField(cos(f->beta), sin(f->beta), 0); Eigen::Vector3d x, y; f->axis(x, y); f->field = localField.x()*x + localField.y()*y; } }
void SteadyStateUpscaler<Traits>::computeInOutFlows(std::pair<double, double>& water_inout, std::pair<double, double>& oil_inout, const FlowSol& flow_solution, const std::vector<double>& saturations) const { typedef typename GridInterface::CellIterator CellIter; typedef typename CellIter::FaceIterator FaceIter; double side1_flux = 0.0; double side2_flux = 0.0; double side1_flux_oil = 0.0; double side2_flux_oil = 0.0; std::map<int, double> frac_flow_by_bid; int num_cells = this->ginterf_.numberOfCells(); std::vector<double> cell_inflows_w(num_cells, 0.0); std::vector<double> cell_outflows_w(num_cells, 0.0); // Two passes: First pass, deal with outflow, second pass, deal with inflow. // This is for the periodic case, so that we are sure all fractional flows have // been set in frac_flow_by_bid. for (int pass = 0; pass < 2; ++pass) { for (CellIter c = this->ginterf_.cellbegin(); c != this->ginterf_.cellend(); ++c) { for (FaceIter f = c->facebegin(); f != c->faceend(); ++f) { if (f->boundary()) { double flux = flow_solution.outflux(f); const SatBC& sc = this->bcond_.satCond(f); if (flux < 0.0 && pass == 1) { // This is an inflow face. double frac_flow = 0.0; if (sc.isPeriodic()) { assert(sc.saturationDifference() == 0.0); int partner_bid = this->bcond_.getPeriodicPartner(f->boundaryId()); std::map<int, double>::const_iterator it = frac_flow_by_bid.find(partner_bid); if (it == frac_flow_by_bid.end()) { OPM_THROW(std::runtime_error, "Could not find periodic partner fractional flow. Face bid = " << f->boundaryId() << " and partner bid = " << partner_bid); } frac_flow = it->second; } else { assert(sc.isDirichlet()); frac_flow = this->res_prop_.fractionalFlow(c->index(), sc.saturation()); } cell_inflows_w[c->index()] += flux*frac_flow; side1_flux += flux*frac_flow; side1_flux_oil += flux*(1.0 - frac_flow); } else if (flux >= 0.0 && pass == 0) { // This is an outflow face. double frac_flow = this->res_prop_.fractionalFlow(c->index(), saturations[c->index()]); if (sc.isPeriodic()) { frac_flow_by_bid[f->boundaryId()] = frac_flow; // std::cout << "Inserted bid " << f->boundaryId() << std::endl; } cell_outflows_w[c->index()] += flux*frac_flow; side2_flux += flux*frac_flow; side2_flux_oil += flux*(1.0 - frac_flow); } } } } } water_inout = std::make_pair(side1_flux, side2_flux); oil_inout = std::make_pair(side1_flux_oil, side2_flux_oil); }