Esempio n. 1
0
    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;
    }
Esempio n. 2
0
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();
    }
}
Esempio n. 3
0
   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;
   }
Esempio n. 5
0
    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);
    }
Esempio n. 6
0
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);
}