void test_flowsolver(const GI& g, const RI& r, double tol, int kind) { typedef typename GI::CellIterator CI; typedef typename CI::FaceIterator FI; typedef double (*SolutionFuncPtr)(const Vec&); //typedef Dune::BasicBoundaryConditions<true, false> FBC; typedef Dune::FunctionBoundaryConditions<SolutionFuncPtr> FBC; typedef Dune::IncompFlowSolverHybrid<GI, RI, FBC, Dune::MimeticIPEvaluator> FlowSolver; FlowSolver solver; // FBC flow_bc; // assign_bc(g, flow_bc); FBC flow_bc(&u); typename CI::Vector gravity(0.0); std::cout << "========== Init pressure solver =============" << std::endl; Dune::time::StopWatch rolex; rolex.start(); solver.init(g, r, gravity, flow_bc); rolex.stop(); std::cout << "========== Time in seconds: " << rolex.secsSinceStart() << " =============" << std::endl; std::vector<double> src(g.numberOfCells(), 0.0); assign_src(g, src); std::vector<double> sat(g.numberOfCells(), 0.0); std::cout << "========== Starting pressure solve =============" << std::endl; rolex.start(); solver.solve(r, sat, flow_bc, src, tol, 3, kind); rolex.stop(); std::cout << "========== Time in seconds: " << rolex.secsSinceStart() << " =============" << std::endl; typedef typename FlowSolver::SolutionType FlowSolution; FlowSolution soln = solver.getSolution(); std::vector<typename GI::Vector> cell_velocity; estimateCellVelocity(cell_velocity, g, solver.getSolution()); // Dune's vtk writer wants multi-component data to be flattened. std::vector<double> cell_velocity_flat(&*cell_velocity.front().begin(), &*cell_velocity.back().end()); std::vector<double> cell_pressure; getCellPressure(cell_pressure, g, soln); compare_pressure(g, cell_pressure); Dune::VTKWriter<typename GI::GridType::LeafGridView> vtkwriter(g.grid().leafView()); vtkwriter.addCellData(cell_velocity_flat, "velocity", GI::GridType::dimension); vtkwriter.addCellData(cell_pressure, "pressure"); vtkwriter.write("testsolution-" + boost::lexical_cast<std::string>(0), Dune::VTKOptions::ascii); }
inline void EulerUpstreamImplicit<GI, RP, BC>::initObj(const GI& g, const RP& r, const BC& b) { //residual_computer_.initObj(g, r, b); mygrid_.init(g.grid()); porevol_.resize(mygrid_.numCells()); for (int i = 0; i < mygrid_.numCells(); ++i){ porevol_[i]= mygrid_.cellVolume(i)*r.porosity(i); } // int numf=mygrid_.numFaces(); int num_cells = mygrid_.numCells(); int ngconn = mygrid_.c_grid()->cell_facepos[num_cells]; //std::vector<double> htrans_(ngconn); htrans_.resize(ngconn); const double* perm = &(r.permeability(0)(0,0)); tpfa_htrans_compute(mygrid_.c_grid(), perm, &htrans_[0]); // int count = 0; myrp_= r; typedef typename GI::CellIterator CIt; typedef typename CIt::FaceIterator FIt; std::vector<FIt> bid_to_face; int maxbid = 0; for (CIt c = g.cellbegin(); c != g.cellend(); ++c) { for (FIt f = c->facebegin(); f != c->faceend(); ++f) { int bid = f->boundaryId(); maxbid = std::max(maxbid, bid); } } bid_to_face.resize(maxbid + 1); std::vector<int> egf_cf(mygrid_.numFaces()); int cix=0; for (CIt c = g.cellbegin(); c != g.cellend(); ++c) { int loc_fix=0; for (FIt f = c->facebegin(); f != c->faceend(); ++f) { if (f->boundary() && b.satCond(*f).isPeriodic()) { bid_to_face[f->boundaryId()] = f; } int egf=f->index(); int cf=mygrid_.cellFace(cix,loc_fix); egf_cf[egf]=cf; loc_fix+=1; } cix+=1; } #ifndef NDEBUG const UnstructuredGrid& c_grid=*mygrid_.c_grid(); #endif int hf_ind=0; int bf_ind=0; periodic_cells_.resize(0); periodic_faces_.resize(0); periodic_hfaces_.resize(0); periodic_nbfaces_.resize(0); //cell1 = cell0; direclet_cells_.resize(0); direclet_sat_.resize(0); direclet_sat_.resize(0); direclet_hfaces_.resize(0); assert(periodic_cells_.size()==0); for (CIt c = g.cellbegin(); c != g.cellend(); ++c) { int cell0 = c->index(); for (FIt f = c->facebegin(); f != c->faceend(); ++f) { // Neighbour face, will be changed if on a periodic boundary. // Compute cell[1], cell_sat[1] FIt nbface = f; if (f->boundary()) { bf_ind+=1; if (b.satCond(*f).isPeriodic()) { nbface = bid_to_face[b.getPeriodicPartner(f->boundaryId())]; assert(nbface != f); int cell1 = nbface->cellIndex(); assert(cell0 != cell1); int f_ind=f->index(); int fn_ind=nbface->index(); // mapping face indices f_ind=egf_cf[f_ind]; fn_ind=egf_cf[fn_ind]; assert((c_grid.face_cells[2*f_ind]==-1) || (c_grid.face_cells[2*f_ind+1]==-1)); assert((c_grid.face_cells[2*fn_ind]==-1) || (c_grid.face_cells[2*fn_ind+1]==-1)); assert((c_grid.face_cells[2*f_ind]==cell0) || (c_grid.face_cells[2*f_ind+1]==cell0)); assert((c_grid.face_cells[2*fn_ind]==cell1) || (c_grid.face_cells[2*fn_ind+1]==cell1)); periodic_cells_.push_back(cell0); periodic_cells_.push_back(cell1); periodic_faces_.push_back(f_ind); periodic_hfaces_.push_back(hf_ind); periodic_nbfaces_.push_back(fn_ind); } else if (!( b.flowCond(*f).isNeumann() && b.flowCond(*f).outflux() == 0.0)) { //cell1 = cell0; direclet_cells_.push_back(cell0); direclet_sat_.push_back(b.satCond(*f).saturation()); direclet_sat_.push_back(1-b.satCond(*f).saturation());//only work for 2 phases direclet_hfaces_.push_back(hf_ind); } } hf_ind+=1; } } mygrid_.makeQPeriodic(periodic_hfaces_,periodic_cells_); // use fractional flow instead of saturation as src TwophaseFluid myfluid(myrp_); int num_b=direclet_cells_.size(); for(int i=0; i <num_b; ++i){ std::array<double,2> sat = {{direclet_sat_[2*i] ,direclet_sat_[2*i+1] }}; std::array<double,2> mob; std::array<double,2*2> dmob; myfluid.mobility(direclet_cells_[i], sat, mob, dmob); double fl = mob[0]/(mob[0]+mob[1]); direclet_sat_[2*i] = fl; direclet_sat_[2*i+1] = 1-fl; } }
void test_flowsolver(const GI& g, const RI& r) { typedef typename GI::CellIterator CI; typedef typename CI::FaceIterator FI; typedef Opm::BasicBoundaryConditions<true, false> FBC; typedef Opm::IncompFlowSolverHybrid<GI, RI, FBC, Opm::MimeticIPEvaluator> FlowSolver; FlowSolver solver; typedef Opm::FlowBC BC; FBC flow_bc(7); #if !USE_ALUGRID flow_bc.flowCond(5) = BC(BC::Dirichlet, 100.0*Opm::unit::barsa); flow_bc.flowCond(6) = BC(BC::Dirichlet, 0.0*Opm::unit::barsa); #endif typename CI::Vector gravity(0.0); // gravity[2] = Dune::unit::gravity; solver.init(g, r, gravity, flow_bc); std::vector<double> src(g.numberOfCells(), 0.0); std::vector<double> sat(g.numberOfCells(), 0.0); // if (g.numberOfCells() > 1) { // src[0] = 1.0; // src.back() = -1.0; // } solver.solve(r, sat, flow_bc, src, 5e-9, 3, 1); #if 1 typedef typename FlowSolver::SolutionType FlowSolution; FlowSolution soln = solver.getSolution(); std::vector<typename GI::Vector> cell_velocity; estimateCellVelocity(cell_velocity, g, soln); // Dune's vtk writer wants multi-component data to be flattened. std::vector<double> cell_velocity_flat(&*cell_velocity.front().begin(), &*cell_velocity.back().end()); std::vector<double> cell_pressure; getCellPressure(cell_pressure, g, soln); Dune::VTKWriter<typename GI::GridType::LeafGridView> vtkwriter(g.grid().leafView()); vtkwriter.addCellData(cell_velocity_flat, "velocity", dim); vtkwriter.addCellData(cell_pressure, "pressure"); vtkwriter.write("testsolution-" + boost::lexical_cast<std::string>(0), Dune::VTKOptions::ascii); #else solver.printSystem("system"); typedef typename FlowSolver::SolutionType FlowSolution; FlowSolution soln = solver.getSolution(); std::cout << "Cell Pressure:\n" << std::scientific << std::setprecision(15); for (CI c = g.cellbegin(); c != g.cellend(); ++c) { std::cout << '\t' << soln.pressure(c) << '\n'; } std::cout << "Cell (Out) Fluxes:\n"; std::cout << "flux = [\n"; for (CI c = g.cellbegin(); c != g.cellend(); ++c) { for (FI f = c->facebegin(); f != c->faceend(); ++f) { std::cout << soln.outflux(f) << ' '; } std::cout << "\b\n"; } std::cout << "]\n"; #endif }