/* ---------------------------------------------------------------------- */ struct Wells * clone_wells(const struct Wells *W) /* ---------------------------------------------------------------------- */ { int np, nperf, ok, pos, w; const int *cells; const double *WI, *comp_frac; struct WellControls *ctrl; struct Wells *newWells; if (W == NULL) { newWells = NULL; } else { np = W->number_of_phases; newWells = create_wells(W->number_of_phases, W->number_of_wells, W->well_connpos[ W->number_of_wells ]); if (newWells != NULL) { pos = W->well_connpos[ 0 ]; ok = 1; for (w = 0; ok && (w < W->number_of_wells); w++) { nperf = W->well_connpos[w + 1] - pos; cells = W->well_cells + pos; WI = W->WI != NULL ? W->WI + pos : NULL; comp_frac = W->comp_frac != NULL ? W->comp_frac + w*np : NULL; ok = add_well(W->type[ w ], W->depth_ref[ w ], nperf, comp_frac, cells, WI, W->name[ w ], newWells); if (ok) { ok = (ctrl = well_controls_clone(W->ctrls[w])) != NULL; } if (ok) { /* Destroy control set implied by add_well() */ well_controls_destroy(newWells->ctrls[w]); /* Assign complete clone of w's control set */ newWells->ctrls[w] = ctrl; } pos = W->well_connpos[w + 1]; } if (! ok) { destroy_wells(newWells); newWells = NULL; } } } assert (wells_equal(newWells, W, false)); return newWells; }
int main(int argc, char* argv[]) { const Opm::parameter::ParameterGroup param(argc, argv, false); const Opm::GridManager gm(5, 5); const UnstructuredGrid* g = gm.c_grid(); const int nc = g->number_of_cells; const Opm::BlackoilPropertiesBasic oldprops(param, 2, nc); const Opm::BlackoilPropsAd props(oldprops); typedef AutoDiff::ForwardBlock<double> ADB; Wells* wells = create_wells(2, 2, 5); const double inj_frac[] = { 1.0, 0.0 }; const double prod_frac[] = { 0.0, 0.0 }; const int num_inj = 3; const int inj_cells[num_inj] = { 0, 1, 2 }; const int num_prod = 2; const int prod_cells[num_prod] = { 20, 21 }; const double WI[3] = { 1e-12, 1e-12, 1e-12 }; bool ok = add_well(INJECTOR, 0.0, num_inj, inj_frac, inj_cells, WI, "Inj", wells); ok = ok && add_well(PRODUCER, 0.0, num_prod, prod_frac, prod_cells, WI, "Prod", wells); ok = ok && append_well_controls(BHP, 500.0*Opm::unit::barsa, 0, 0, wells); // ok = ok && append_well_controls(BHP, 200.0*Opm::unit::barsa, 0, 1, wells); double oildistr[2] = { 0.0, 1.0 }; ok = ok && append_well_controls(SURFACE_RATE, 1e-3, oildistr, 1, wells); if (!ok) { THROW("Something went wrong with well init."); } set_current_control(0, 0, wells); set_current_control(1, 0, wells); double grav[] = { /*1.0*/ 0.0, 0.0 }; Opm::DerivedGeology geo(*g, props, grav); Opm::LinearSolverFactory linsolver(param); Opm::ImpesTPFAAD ps(*g, props, geo, *wells, linsolver); Opm::BlackoilState state; initStateBasic(*g, oldprops, param, 0.0, state); initBlackoilSurfvol(*g, oldprops, state); Opm::WellState well_state; well_state.init(wells, state); ps.solve(1.0, state, well_state); std::cout << "Cell pressure:" << std::endl; std::copy(state.pressure().begin(), state.pressure().end(), std::ostream_iterator<double>(std::cout, " ")); std::cout << std::endl; std::cout << "Face flux:" << std::endl; std::copy(state.faceflux().begin(), state.faceflux().end(), std::ostream_iterator<double>(std::cout, " ")); std::cout << std::endl; std::cout << "Well bhp pressure:" << std::endl; std::copy(well_state.bhp().begin(), well_state.bhp().end(), std::ostream_iterator<double>(std::cout, " ")); std::cout << std::endl; return 0; }
void WellsManager::createWellsFromSpecs(std::vector<WellConstPtr>& wells, size_t timeStep, const C2F& c2f, const int* cart_dims, FC begin_face_centroids, int dimensions, std::vector<double>& dz, std::vector<std::string>& well_names, std::vector<WellData>& well_data, std::map<std::string, int>& well_names_to_index, const PhaseUsage& phaseUsage, const std::map<int,int>& cartesian_to_compressed, const double* permeability, const NTG& ntg, std::vector<int>& wells_on_proc) { if (dimensions != 3) { OPM_THROW(std::domain_error, "WellsManager::createWellsFromSpecs() only " "supported in three space dimensions"); } std::vector<std::vector<PerfData> > wellperf_data; wellperf_data.resize(wells.size()); wells_on_proc.resize(wells.size(), 1); int well_index = 0; for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) { WellConstPtr well = (*wellIter); if (well->getStatus(timeStep) == WellCommon::SHUT) { continue; } { // COMPDAT handling CompletionSetConstPtr completionSet = well->getCompletions(timeStep); // shut completions and open ones stored in this process will have 1 others 0. std::vector<std::size_t> completion_on_proc(completionSet->size(), 1); std::size_t shut_completions_number = 0; for (size_t c=0; c<completionSet->size(); c++) { CompletionConstPtr completion = completionSet->get(c); if (completion->getState() == WellCompletion::OPEN) { int i = completion->getI(); int j = completion->getJ(); int k = completion->getK(); const int* cpgdim = cart_dims; int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k); std::map<int, int>::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx); if (cgit == cartesian_to_compressed.end()) { if ( is_parallel_run_ ) { completion_on_proc[c]=0; continue; } else { OPM_MESSAGE("****Warning: Cell with i,j,k indices " << i << ' ' << j << ' ' << k << " not found in grid. The completion will be igored (well = " << well->name() << ')'); } } else { int cell = cgit->second; PerfData pd; pd.cell = cell; { const Value<double>& transmissibilityFactor = completion->getConnectionTransmissibilityFactorAsValueObject(); const double wellPi = completion ->getWellPi(); if (transmissibilityFactor.hasValue()) { pd.well_index = transmissibilityFactor.getValue(); } else { double radius = 0.5*completion->getDiameter(); if (radius <= 0.0) { radius = 0.5*unit::feet; OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius); } std::array<double, 3> cubical = WellsManagerDetail::getCubeDim<3>(c2f, begin_face_centroids, cell); // overwrite dz values calculated in getCubeDim. if (dz.size() > 0) { cubical[2] = dz[cell]; } const double* cell_perm = &permeability[dimensions*dimensions*cell]; pd.well_index = WellsManagerDetail::computeWellIndex(radius, cubical, cell_perm, completion->getSkinFactor(), completion->getDirection(), ntg[cell]); } pd.well_index *= wellPi; } wellperf_data[well_index].push_back(pd); } } else { ++shut_completions_number; if (completion->getState() != WellCompletion::SHUT) { OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled"); } } } if ( is_parallel_run_ ) { // sum_completions_on_proc includes completions // that are shut std::size_t sum_completions_on_proc = std::accumulate(completion_on_proc.begin(), completion_on_proc.end(),0); // Set wells that are not on this processor to SHUT. // A well is not here if only shut completions are found. if ( sum_completions_on_proc == shut_completions_number ) { // Mark well as not existent on this process wells_on_proc[wellIter-wells.begin()] = 0; continue; } else { // Check that the complete well is on this process if ( sum_completions_on_proc < completionSet->size() ) { std::cout<< "Well "<< well->name() << " semms not be in " << "completely in the disjoint partition of " << "process deactivating here." << std::endl; // Mark well as not existent on this process wells_on_proc[wellIter-wells.begin()] = 0; continue; } } } } { // WELSPECS handling well_names_to_index[well->name()] = well_index; well_names.push_back(well->name()); { WellData wd; wd.reference_bhp_depth = well->getRefDepth(); wd.welspecsline = -1; if (well->isInjector( timeStep )) wd.type = INJECTOR; else wd.type = PRODUCER; well_data.push_back(wd); } } well_index++; } // Set up reference depths that were defaulted. Count perfs. const int num_wells = well_data.size(); int num_perfs = 0; assert (dimensions == 3); for (int w = 0; w < num_wells; ++w) { num_perfs += wellperf_data[w].size(); } // Create the well data structures. w_ = create_wells(phaseUsage.num_phases, num_wells, num_perfs); if (!w_) { OPM_THROW(std::runtime_error, "Failed creating Wells struct."); } // Add wells. for (int w = 0; w < num_wells; ++w) { const int w_num_perf = wellperf_data[w].size(); std::vector<int> perf_cells (w_num_perf); std::vector<double> perf_prodind(w_num_perf); for (int perf = 0; perf < w_num_perf; ++perf) { perf_cells [perf] = wellperf_data[w][perf].cell; perf_prodind[perf] = wellperf_data[w][perf].well_index; } const double* comp_frac = NULL; // We initialize all wells with a null component fraction, // and must (for injection wells) overwrite it later. const int ok = add_well(well_data[w].type, well_data[w].reference_bhp_depth, w_num_perf, comp_frac, perf_cells.data(), perf_prodind.data(), well_names[w].c_str(), w_); if (!ok) { OPM_THROW(std::runtime_error, "Failed adding well " << well_names[w] << " to Wells data structure."); } } }