inline void c_Continuation::nextImpl(FI& fi) { const_assert(!hhvm); ASSERT(m_running); try { if (m_isMethod) { MethodCallPackage mcp; mcp.isObj = m_obj.get(); if (mcp.isObj) { mcp.obj = mcp.rootObj = m_obj.get(); } else { mcp.rootCls = getCalledClass().get(); } fi.setStaticClassName(getCalledClass()); (m_callInfo->getMeth1Args())(mcp, 1, this); } else { (m_callInfo->getFunc1Args())(NULL, 1, this); } } catch (Object e) { if (e.instanceof("exception")) { m_running = false; m_done = true; m_value.setNull(); throw_exception(e); } else { throw; } } m_running = false; }
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. }
inline __host__ __device__ i_short2 gradient_descent_match2(i_short2 prediction, F f, FI& feature_img, float& distance, unsigned scale = 1) { i_short2 match = prediction; float match_distance = feature_img.distance(f, prediction); unsigned match_i = 8; box2d domain = feature_img.domain() - border(7); if (!domain.has(prediction)) return prediction; assert(domain.has(prediction)); for (int search = 0; search < 7; search++) { for(int i = 0; i != 25; i++) { i_int2 n(prediction + i_int2(c25_h[i])); { float d = feature_img.distance(f, n, scale); if (d < match_distance) { match = n; match_i = i; match_distance = d; } } } if (i_int2(prediction) == i_int2(match) || !domain.has(match)) break; else prediction = match; } distance = match_distance; return match; }
inline void c_Continuation::nextImpl(FI& fi) { const_assert(!hhvm); preNext(); try { if (m_isMethod) { MethodCallPackage mcp; mcp.isObj = hhvm || m_obj.get(); if (mcp.isObj) { mcp.obj = mcp.rootObj = m_obj.get(); } else { mcp.rootCls = m_called_class.get(); } mcp.extra = m_extra; if (!hhvm) { fi.setStaticClassName(m_called_class); } (m_callInfo->getMeth1Args())(mcp, 1, this); } else { if (hhvm) { MethodCallPackage mcp; mcp.isObj = false; mcp.obj = mcp.rootObj = NULL; mcp.extra = m_extra; (m_callInfo->getMeth1Args())(mcp, 1, this); } else { (m_callInfo->getFunc1Args())(m_extra, 1, this); } } } catch (Object e) { if (e.instanceof("exception")) { m_running = false; m_done = true; throw_exception(e); } else { throw; } } m_running = false; }
/// @brief /// Main evaluation routine. Computes the inverse of the /// matrix representation of the mimetic inner product in a /// single cell with kown permeability @f$K@f$. Adds a /// regularization term in order to guarantee a positive /// definite matrix. /// /// @tparam RockInterface /// Type representing rock properties. Assumed to /// expose a method @code permeability(i) @endcode which /// retrieves the static permeability tensor of cell @code /// i @endcode. The permeability tensor, @$K@$, is in /// turn, assumed to expose a method @code operator()(int /// i, int j) @endcode such that the call @code K(i,j) /// @endcode retrieves the @f$ij@f$'th component of the /// cell permeability @f$K@f$. /// /// @param [in] c /// Cell for which to evaluate the inverse of the mimetic /// inner product. /// /// @param [in] r /// Specific reservoir properties. Only the permeability /// is used in method @code buildMatrix() @endcode. /// /// @param [in] nf /// Number of faces (i.e., number of neighbours) of cell /// @code *c @endcode. void buildStaticContrib(const CellIter& c, const RockInterface& r, const typename CellIter::Vector& grav, const int nf) { // Binv = (N*lambda*K*N' + t*diag(A)*(I - Q*Q')*diag(A))/vol // ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ // precompute: n_ precompute: second_term_ // t = 6/dim * trace(lambda*K) typedef typename CellIter::FaceIterator FI; typedef typename CellIter::Vector CV; typedef typename FI ::Vector FV; // Now we need to remember the rocks, since we will need // the permeability for dynamic assembly. prock_ = &r; const int ci = c->index(); static_assert (FV::dimension == int(dim), ""); assert (int(t1_.size()) >= nf * dim); assert (int(t2_.size()) >= nf * dim); assert (int(fa_.size()) >= nf * nf); SharedFortranMatrix T2 (nf, dim, &t2_ [0]); SharedFortranMatrix fa (nf, nf , &fa_ [0]); SharedFortranMatrix second_term(nf, nf, &second_term_[ci][0]); SharedFortranMatrix n(nf, dim, &n_[ci][0]); // Clear matrices of any residual data. zero(second_term); zero(n); zero(T2); zero(fa); // Setup: second_term <- I, n <- N, T2 <- C const CV cc = c->centroid(); int i = 0; for (FI f = c->facebegin(); f != c->faceend(); ++f, ++i) { second_term(i,i) = Scalar(1.0); fa(i,i) = f->area(); FV fc = f->centroid(); fc -= cc; fc *= fa(i,i); FV fn = f->normal (); fn *= fa(i,i); for (int j = 0; j < dim; ++j) { n (i,j) = fn[j]; T2(i,j) = fc[j]; } } assert (i == nf); // T2 <- orth(T2) if (orthogonalizeColumns(T2) != 0) { assert (false); } // second_term <- second_term - T2*T2' == I - Q*Q' symmetricUpdate(Scalar(-1.0), T2, Scalar(1.0), second_term); // second_term <- diag(A) * second_term * diag(A) symmetricUpdate(fa, second_term); // Gravity term: Kg_ = K * grav vecMulAdd_N(Scalar(1.0), r.permeability(ci), &grav[0], Scalar(0.0), &Kg_[ci][0]); }
void buildFaceIndices() { #ifdef VERBOSE std::cout << "Building unique face indices... " << std::flush; Opm::time::StopWatch clock; clock.start(); #endif typedef CellIterator CI; typedef typename CI::FaceIterator FI; // We build the actual cell to face mapping in two passes. // [code mostly lifted from IncompFlowSolverHybrid::enumerateGridDof(), // but with a twist: This code builds a mapping from cells in index // order to unique face numbers, while the mapping built in the // enumerateGridDof() method was ordered by cell iterator order] // Allocate and reserve structures. const int nc = numberOfCells(); std::vector<int> cell(nc, -1); std::vector<int> num_faces(nc); // In index order. std::vector<int> fpos; fpos .reserve(nc + 1); std::vector<int> num_cf; num_cf.reserve(nc); // In iterator order. std::vector<int> faces ; // First pass: enumerate internal faces. int cellno = 0; fpos.push_back(0); int tot_ncf = 0, tot_ncf2 = 0, max_ncf = 0; for (CI c = cellbegin(); c != cellend(); ++c, ++cellno) { const int c0 = c->index(); ASSERT((0 <= c0) && (c0 < nc) && (cell[c0] == -1)); cell[c0] = cellno; num_cf.push_back(0); int& ncf = num_cf.back(); for (FI f = c->facebegin(); f != c-> faceend(); ++f) { if (!f->boundary()) { const int c1 = f->neighbourCellIndex(); ASSERT((0 <= c1) && (c1 < nc) && (c1 != c0)); if (cell[c1] == -1) { // Previously undiscovered internal face. faces.push_back(c1); } } ++ncf; } num_faces[c0] = ncf; fpos.push_back(int(faces.size())); max_ncf = std::max(max_ncf, ncf); tot_ncf += ncf; tot_ncf2 += ncf * ncf; } ASSERT(cellno == nc); // Build cumulative face sizes enabling direct insertion of // face indices into cfdata later. std::vector<int> cumul_num_faces(numberOfCells() + 1); cumul_num_faces[0] = 0; std::partial_sum(num_faces.begin(), num_faces.end(), cumul_num_faces.begin() + 1); // Avoid (most) allocation(s) inside 'c' loop. std::vector<int> l2g; l2g.reserve(max_ncf); std::vector<double> cfdata(tot_ncf); int total_num_faces = int(faces.size()); // Second pass: build cell-to-face mapping, including boundary. typedef std::vector<int>::iterator VII; for (CI c = cellbegin(); c != cellend(); ++c) { const int c0 = c->index(); ASSERT ((0 <= c0 ) && ( c0 < nc) && (0 <= cell[c0]) && (cell[c0] < nc)); const int ncf = num_cf[cell[c0]]; l2g.resize(ncf, 0); for (FI f = c->facebegin(); f != c->faceend(); ++f) { if (f->boundary()) { // External, not counted before. Add new face... l2g[f->localIndex()] = total_num_faces++; } else { // Internal face. Need to determine during // traversal of which cell we discovered this // face first, and extract the face number // from the 'faces' table range of that cell. // Note: std::find() below is potentially // *VERY* expensive (e.g., large number of // seeks in moderately sized data in case of // faulted cells). const int c1 = f->neighbourCellIndex(); ASSERT ((0 <= c1 ) && ( c1 < nc) && (0 <= cell[c1]) && (cell[c1] < nc)); int t = c0, seek = c1; if (cell[seek] < cell[t]) std::swap(t, seek); int s = fpos[cell[t]], e = fpos[cell[t] + 1]; VII p = std::find(faces.begin() + s, faces.begin() + e, seek); ASSERT(p != faces.begin() + e); l2g[f->localIndex()] = p - faces.begin(); } } ASSERT(int(l2g.size()) == num_faces[c0]); std::copy(l2g.begin(), l2g.end(), cfdata.begin() + cumul_num_faces[c0]); } num_faces_ = total_num_faces; max_faces_per_cell_ = max_ncf; face_indices_.assign(cfdata.begin(), cfdata.end(), num_faces.begin(), num_faces.end()); #ifdef VERBOSE clock.stop(); double elapsed = clock.secsSinceStart(); std::cout << "done. Time elapsed: " << elapsed << std::endl; #endif }
inline __host__ __device__ std::pair<i_short2, float> gradient_descent_match(i_short2 prediction_, F f, FI& feature_img, unsigned scale = 1) { typedef std::pair<i_short2, float> ret; i_short2 prediction = prediction_; typedef typename FI::architecture A; i_short2 match = prediction; float match_distance = feature_img.distance(f, prediction); unsigned match_i = 8; box2d domain = feature_img.domain() - border(0); if (!domain.has(prediction)) { return ret(prediction, 999999.f); } assert(domain.has(prediction)); for (int search = 0; search < 10; search++) { int i = arch_neighb2d<A>::get(c8_it_h, c8_it, match_i)[0]; int end = arch_neighb2d<A>::get(c8_it_h, c8_it, match_i)[1]; { i_int2 n(prediction + i_int2(arch_neighb2d<A>::get(c8_h, c8, i))); if (feature_img.domain().has(n)) { float d = feature_img.distance(f, n, scale); if (d < match_distance) { match = n; match_i = i; match_distance = d; } } i = (i + 1) & 7; } #pragma unroll 4 for(; i != end; i = (i + 1) & 7) { i_int2 n(prediction + i_int2(arch_neighb2d<A>::get(c8_h, c8, i))); if (feature_img.domain().has(n)) { float d = feature_img.distance(f, n, scale); if (d < match_distance) { match = n; match_i = i; match_distance = d; } } } if (i_int2(prediction) == i_int2(match) || !domain.has(match)) break; else prediction = match; } // if (scale == 2) // match = prediction + 2 * (match - prediction); // match_distance = feature_img.distance(f, match, scale); return ret(match, match_distance); }
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."); } } } }