void assign_bc(const GI& g, BCS& bcs) { typedef Dune::FlowBC BC; typedef typename GI::CellIterator CI; typedef typename CI::FaceIterator FI; int max_bid = 0; for (CI c = g.cellbegin(); c != g.cellend(); ++c) { for (FI f = c->facebegin(); f != c->faceend(); ++f) { int bid = f->boundaryId(); if (bid > max_bid) { max_bid = bid; bcs.resize(bid + 1); } bcs.flowCond(bid) = BC(BC::Dirichlet, u(f->centroid())); } } }
inline void setupRegionBasedConditions(const Opm::parameter::ParameterGroup& param, const GridInterface& g, BCs& bcs) { // Extract region and pressure value for Dirichlet bcs. typedef typename GridInterface::Vector Vector; Vector low; low[0] = param.getDefault("dir_block_low_x", 0.0); low[1] = param.getDefault("dir_block_low_y", 0.0); low[2] = param.getDefault("dir_block_low_z", 0.0); Vector high; high[0] = param.getDefault("dir_block_high_x", 1.0); high[1] = param.getDefault("dir_block_high_y", 1.0); high[2] = param.getDefault("dir_block_high_z", 1.0); double dir_block_pressure = param.get<double>("dir_block_pressure"); // Set flow conditions for that region. // For this to work correctly, unique boundary ids should be used, // otherwise conditions may spread outside the given region, to all // faces with the same bid as faces inside the region. typedef typename GridInterface::CellIterator CI; typedef typename CI::FaceIterator FI; int max_bid = 0; std::vector<int> dir_bids; for (CI c = g.cellbegin(); c != g.cellend(); ++c) { for (FI f = c->facebegin(); f != c->faceend(); ++f) { int bid = f->boundaryId(); max_bid = std::max(bid, max_bid); if (bid != 0 && isInside(low, high, f->centroid())) { dir_bids.push_back(bid); } } } bcs.resize(max_bid + 1); for (std::vector<int>::const_iterator it = dir_bids.begin(); it != dir_bids.end(); ++it) { bcs.flowCond(*it) = FlowBC(FlowBC::Dirichlet, dir_block_pressure); } // Transport BCs are defaulted. }
void findPeriodicPartners(std::vector<BoundaryFaceInfo>& bfinfo, std::array<double, 6>& side_areas, const GridView& g, const std::array<bool, 2*GridView::dimension>& is_periodic, double spatial_tolerance = 1e-6) { // Pick out all boundary faces, simultaneously find the // bounding box of their centroids, and the max id. const int dim = GridView::dimension; typedef typename GridView::template Codim<0>::Iterator CI; typedef typename GridView::IntersectionIterator FI; typedef Dune::FieldVector<double, dim> Vector; std::vector<FI> bface_iters; Vector low(1e100); Vector hi(-1e100); int max_bid = 0; for (CI c = g.template begin<0>(); c != g.template end<0>(); ++c) { for (FI f = g.ibegin(*c); f != g.iend(*c); ++f) { if (f->boundaryId()) { bface_iters.push_back(f); Vector fcent = f->geometry().center(); for (int dd = 0; dd < dim; ++dd) { low[dd] = std::min(low[dd], fcent[dd]); hi[dd] = std::max(hi[dd], fcent[dd]); } max_bid = std::max(max_bid, f->boundaryId()); } } } int num_bdy = bface_iters.size(); if (max_bid != num_bdy) { OPM_THROW(std::runtime_error, "createPeriodic() assumes that every boundary face has a unique boundary id. That seems to be violated."); } // Store boundary face info in a suitable structure. Also find side total volumes. std::fill(side_areas.begin(), side_areas.end(), 0.0); bfinfo.clear(); bfinfo.reserve(num_bdy); for (int i = 0; i < num_bdy; ++i) { BoundaryFaceInfo bf; bf.face_index = i; bf.bid = bface_iters[i]->boundaryId(); bf.canon_pos = -1; bf.partner_face_index = -1; bf.partner_bid = 0; bf.area = bface_iters[i]->geometry().volume(); bf.centroid = bface_iters[i]->geometry().center(); for (int dd = 0; dd < dim; ++dd) { double coord = bf.centroid[dd]; if (fabs(coord - low[dd]) <= spatial_tolerance) { bf.canon_pos = 2*dd; break; } else if (fabs(coord - hi[dd]) <= spatial_tolerance) { bf.canon_pos = 2*dd + 1; break; } } if (bf.canon_pos == -1) { std::cerr << "Centroid: " << bf.centroid << "\n"; std::cerr << "Bounding box min: " << low << "\n"; std::cerr << "Bounding box max: " << hi << "\n"; OPM_THROW(std::runtime_error, "Boundary face centroid not on bounding box. Maybe the grid is not an axis-aligned shoe-box?"); } side_areas[bf.canon_pos] += bf.area; bf.centroid[bf.canon_pos/2] = 0.0; bfinfo.push_back(bf); } assert(bfinfo.size() == bface_iters.size()); // Sort the infos so that partners end up close. std::sort(bfinfo.begin(), bfinfo.end()); // Identify partners. for (int i = 0; i < num_bdy; ++i) { if (bfinfo[i].partner_face_index != -1) { continue; } if (!is_periodic[bfinfo[i].canon_pos]) { continue; } int lower = std::max(0, i - 10); int upper = std::min(num_bdy, i + 10); bool ok = match(bfinfo, i, lower, upper); if (!ok) { // We have not found a partner. ok = match(bfinfo, i, 0, num_bdy); if (!ok) { OPM_MESSAGE("Warning: No partner found for boundary id " << bfinfo[i].bid); // OPM_THROW(std::runtime_error, "No partner found."); } } } }