/home/bill/OPM concepts/Well-bore turbulence notes.txt $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "well.bore" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep well.bore in OPM 170802 11h43m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "well-bore" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep well-bore in OPM 170802 11h44m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : opm-simulators/opm/autodiff/MultisegmentWells_impl.hpp: // determining in-flow (towards well-bore) or out-flow (towards reservoir) $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "well bore" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep well bore in OPM 170802 11h45m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-core/build/doc/doxygen/html/WellsManager__impl_8hpp_source.html:
205  OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius);
opm-core/opm/core/wells/WellsManager_impl.hpp: OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius); opm-upscaling/opm/porsol/blackoil/BlackoilWells.hpp: OPM_MESSAGE("Warning: Well bore internal radius set to " << radius); ewoms/ebos/eclpeacemanwell.hh: // we assume the well borehole in the center of the dof and that it is vertical, opm-simulators/opm/polymer/fullyimplicit/SimulatorFullyImplicitBlackoilPolymer_impl.hpp: OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius); opm-parser/testdata/integration_tests/IOConfig/SPE1CASE2.DATA:-- Item 9 is the well bore internal diameter, opm-parser/testdata/integration_tests/IOConfig/SPE9_END.DATA:-- Column 9: well bore diameter opm-parser/build/bin/testdata/integration_tests/IOConfig/SPE1CASE2.DATA:-- Item 9 is the well bore internal diameter, opm-parser/build/bin/testdata/integration_tests/IOConfig/SPE9_END.DATA:-- Column 9: well bore diameter opm-data/solvent_test_suite/SPE1CASE2_SOLVENT.DATA:-- Item 9 is the well bore internal diameter, opm-data/solvent_test_suite/SPE9_CP_SOLVENT_CO2_MISC_TL.DATA:-- Column 9: well bore diameter opm-data/solvent_test_suite/SPE9_CP_SOLVENT_CO2.DATA:-- Column 9: well bore diameter opm-data/solvent_test_suite/SPE1CASE2_SOLVENT_MISC_TL.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe3/eclipse-simulation/SPE3CASE1.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe3/eclipse-simulation/SPE3CASE2.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe3/SPE3CASE1.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe3/SPE3CASE2.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE1.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE2_FAMII.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE2_2P.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE2_ACTNUM.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE2_SLGOF.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/eclipse-simulation/SPE1CASE2.PRT: 0: -- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_2P.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_FAMII.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE1.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_ACTNUM.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_ACTNUM_RESTART.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_RESTART.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe1/SPE1CASE2_SLGOF.DATA:-- Item 9 is the well bore internal diameter, opm-data/spe9/SPE9_CP_SHORT_RESTART.DATA:-- Column 9: well bore diameter opm-data/spe9/eclipse-simulation/SPE9_CP.PRT: 0: -- Column 9: well bore diameter opm-data/spe9/SPE9_CP.DATA:-- Column 9: well bore diameter opm-data/spe9/SPE9_CP_GROUP.DATA:-- Column 9: well bore diameter opm-data/spe9/SPE9_CP_SHORT.DATA:-- Column 9: well bore diameter opm-data/spe9/SPE9.DATA:-- Column 9: well bore diameter +-----+ >> not much help Check : /home/buill/OPM/opm-simulators/opm/autodiff/MultisegmentWells_impl.hpp **************************************** 02Aug2017 11:30 Well-bore turbulence /home/bill/OPM/opm-simulators/opm/autodiff/MultisegmentWells_impl.hpp +-----+ template void MultisegmentWells:: addWellControlEq(const SolutionState& state, const WellState& xw, const Vector& aliveWells, LinearisedBlackoilResidual& residual) { ... // the name of the function is a a little misleading. // Basically it is the function for the pressure equation. // And also, it work as the control equation when it is the segment ... // THP control is not implemented for the moment. ... // The current control in the well state overrides // the current control set in the Wells struct, which // is instead treated as a default. ... case THP: { OPM_THROW(std::runtime_error, "THP control is not implemented for multi-sgement wells yet!!"); } ... // RESERVOIR and SURFACE rates look the same, from a // high-level point of view, in the system of // simultaneous linear equations. ... // for each segment: 1, if the segment is the top segment, then control equation // 2, if the segment is not the top segment, then the pressure equation +-----+ template void MultisegmentWells:: updateWellControls(WellState& xw) const { ... // Loop over all controls except the current one, and also // skip any RESERVOIR_RATE controls, since we cannot // handle those. ... +-----+ // TODO: This is just a preliminary version, remains to be improved later when we decide a better way // TODO: to intergrate the usual wells and multi-segment wells. template void MultisegmentWells:: computeWellConnectionPressures(const SolutionState& state, const WellState& xw, const std::vector& kr_adb, const std::vector& fluid_density) { ... // 1. Compute properties required by computeConnectionPressureDelta(). // Note that some of the complexity of this part is due to the function // taking std::vector arguments, and not Eigen objects. ... // for the non-segmented/regular wells, calculated the average pressures. // If it is the top perforation, then average with the bhp(). // If it is not the top perforation, then average with the perforation above it(). ... // Use cell values for the temperature as the wells don't knows its temperature yet. const ADB perf_temp = subset(state.temperature, well_cells); // Compute b, rsmax, rvmax values for perforations. // Evaluate the properties using average well block pressures // and cell values for rs, rv, phase condition and temperature. ... // Surface density. // The compute density segment wants the surface densities as // an np * number of wells cells array ... // compute the average of the fluid densites in the well blocks. // the average is weighted according to the fluid relative permeabilities. // const std::vector kr_adb = Base::computeRelPerm(state); ... // compute the averaged density for the well block // TODO: for the non-segmented wells, they should be set to zero // TODO: for the moment, they are still calculated, while not used later. ... +-----+ template void MultisegmentWells:: variableStateExtractWellsVars(const std::vector& indices, std::vector& vars, SolutionState& state) const { ... // The qs and bhp are no longer primary variables, but could // still be used in computations. They are identical to the // pressures and flows of the top segments. ... ******************************** /home/bill/OPM/opm-simulators/opm/autodiff/StandardWells.hpp does computeWellFlux include turbulent flow? What file is it in? +-----+ template void computeWellFlux(const SolutionState& state, const std::vector& mob_perfcells, const std::vector& b_perfcells, Vector& aliveWells, std::vector& cq_s) const; ... ********************************** 03Aug2017 09:10 Perry's Chemical Engineers' Handbook, 1984 6th edition, 50th anniversary, McGraw-Hill ISBN 0-07-049479-7 Chapter 5 Fluid & particle mechanics Section "Fluid dynamics" F friction loss (specific energy) G mass velocity g local acceleration due to gravity gc dimensional constant i specific enthalpy J mechanical equivalent of heat (conversion factor?) Q heat added u specific internal (or instrinsic) energy V linear velocity v specific volume W work added We work delivered by an external source (eg blower or pump) Z height above any arbitrary horizontal datum plane Z*g/gc potential energy relative to the reference level V^2/2/gc kinetic energy J*u + Z*g/gc + V^2/2/gc total energy of the unit weight of fluid J*T*ds = J*dQ + dF friction loss relation For steady flow of fluid (no acceleration, [addition,depletion] of fluid) (5-35) (J*u2 + Z2*g/gc + V2^2/2/gc) - (J*u1 + Z1*g/gc + V1^2/2/gc) = J*Q + W (5-36) W = p1*v1 - p2*v2 + We Overall energy balance form of Bernoulli's theorem missing electromagnetic & other forms of energy (5-37) J*u1 + Z1*g/gc + V1^2/2/gc + p1*v1 + J*Q + W = J*u2 + Z2*g/gc + V2^2/2/gc + p2*v2 Mechanical energy form of Bernoulli's theorem (5-41) Z1*g/gc + V1^2/2/gc - int[dp, 1 to 2 : v] - F + We = Z2*g/gc + V2^2/2/gc For isothermal flow of an ideal gas : (5-42) int[dp, 1 to 2 : v] = -R*T/M*ln(v2/v1) = -R*T/M*ln(p2/p1) +-----+ CIRCULAR PIPES for LIQUID flow D duct diameter del(p) change in pressure f Fanning friction factor G mass velocity g local acceleration due to gravity gc dimensional constant hv velocity head (V^2/2/gc) L duct length N_Re Reynold's number q volume rate of flow rho fluid density V fluid velocity w weight rate of flow Fanning or Darcy equation for LIQUID flow (5-57) F = (4*f*L/D)*V^2/2/gc = (4*f*L/D)*hv = (4*f*L/D)*G^2/2/gc/rho^2 = 32*f*L*w^2/pi^2/rho^2/gc/D^5 = 32*f*L*q^2/pi^2/rho^2/gc/D^5 . del(p) = F*rho Turbulent flow (N_Re > 3000), Colebrook equation (5-58) 1/sqrt(f) = -4*log( epsilon/3.7/D + 1.256/N_Re/sqrt(f) ) Rough pipes (steel) - von Karman's equation (5-59) 1/sqrt(f) = -4*log( epsilon/3.7/D ) +---+ COMPRESSIBLE Flow RH hydraulic radius x differential length of duct In general, for gases the Fanning equation (5-57) must be used in differentiable form (5-57) F = (4*f*L/D)*V^2/2/gc (5-88) d[dx : F] = d[dx : (4*f /D)*V^2/2/gc ] = 4*f /D *V^2/2/gc = 4*f *V^2/2/gc/2/RH = f *V^2 /gc /RH (5-88 result seems WRONG!?) = f*G^2/2/gc/rho^2/RH (5-88 result seems WRONG!?) . Sub into mechanical energy equation (5-41) (5-89) v*d[p] + V*d[V]/gc = -( f*V^2/2/gc/RH + g/gc*sin(theta) )*d[x] phi angle wrt horizontal datum plane oriented perpendicular to local gravity rho_avg density at average pressure (p1 + p2)/2 M molecular weight of gas Integrate (5-89) for : - uniform duct (constant X-sectional area, etc), so G=V/c = constant - angle phi = constant over length of duct - p is known as a function of v only, so v*d[p] - ideal gas, p*v = R*T/M - isothermal flow (5-90) p1^2 - p2^2 = f*L*G^2*R*T/gc/RH/M*( 1 + 2*RH/f/L*ln(p1/p2) ) For short ducts, L/D = 100 and (p1 - p2)/p1 < 0.20, can drop last term (5-91) p1 - p2 = f*L*G^2 /2/gc/RH/rho_average For a round pipe, (5-91) becomes (5-92) w = pi/8*sqrt( (p1^2 - p2^2)*gc*D^5*M/f/L/R/T Actually, given complications of - mass additions along perforated horizontal well bore - 2-phases - phase changes - etc OPM probably uses differential form (5-89) in relations given in section "Two-phase flow" page 5-40 later in book, taking into account Fig 5-48, 5-49, and equations (5-147) through (5-152) So look for (5-57) and (5-92) in OPM as a starting point. ********************************* 03Aug2017 11:47 Search [LMDE2]/home/bill/OPM for turbulent pipe flow in well-bore $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "Fanning" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep Fanning in OPM 170803 11h46m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp: // used to calculate the Fanning friction factor +-----+ namespace Opm { class Segment { public: Segment(); ... double m_internal_diameter; // effective roughness of the tubing // used to calculate the Fanning friction factor // for top segment, it is UNDEFINED // we use invalid_value for the top segment +-----+ >> GOOD, so check use of m_internal_diameter $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "m_internal_diameter" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep m_internal_diameter in OPM 170803 11h54m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp: double m_internal_diameter; opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: m_internal_diameter(invalid_value), opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: m_internal_diameter(internal_diameter_in), opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: return m_internal_diameter; opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: && this->m_internal_diameter == rhs.m_internal_diameter opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: && this->m_internal_diameter == rhs.m_internal_diameter +-----+ >> only other is in "Segment.cpp", as I would expect as this is private /home/bill/OPM/opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp : +-----+ bool Segment::operator==( const Segment& rhs ) const { return this->m_segment_number == rhs.m_segment_number && this->m_branch == rhs.m_branch && this->m_outlet_segment == rhs.m_outlet_segment && this->m_total_length == rhs.m_total_length && this->m_depth == rhs.m_depth && this->m_internal_diameter == rhs.m_internal_diameter && this->m_roughness == rhs.m_roughness && this->m_cross_area == rhs.m_cross_area && this->m_volume == rhs.m_volume && this->m_data_ready == rhs.m_data_ready; } bool Segment::operator!=( const Segment& rhs ) const { return this->m_segment_number == rhs.m_segment_number && this->m_branch == rhs.m_branch && this->m_outlet_segment == rhs.m_outlet_segment && this->m_total_length == rhs.m_total_length && this->m_depth == rhs.m_depth && this->m_internal_diameter == rhs.m_internal_diameter && this->m_roughness == rhs.m_roughness && this->m_cross_area == rhs.m_cross_area && this->m_volume == rhs.m_volume && this->m_data_ready == rhs.m_data_ready; +-----+ >> both segments of code are the same!?? What uses "Segment::Segment" ?? $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "Segment::Segment" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep Segment::Segment in OPM 170803 12h04m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentCells() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentLength() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentDepth() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentDiameter() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentCrossArea() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentRoughness() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::segmentVolume() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector>& WellMultiSegment::segmentPerforations() const { opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: Segment::Segment() opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: Segment::Segment(int segment_number_in, int branch_in, int outlet_segment_in, double length_in, double depth_in, opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp: int Segment::segmentNumber() const { +-----+ >> OK, so check opm-simulators/opm/autodiff/WellMultiSegment.cpp /home/bill/OPM/opm-simulators/opm/autodiff/WellMultiSegment.cpp +-----+ namespace Opm { WellMultiSegment::WellMultiSegment(const Well* well, size_t time_step, const Wells* wells) { m_well_name_ = well->name(); if (well->isMultiSegment(time_step)) { initMultiSegmentWell(well, time_step, wells); } else { initNonMultiSegmentWell(well, time_step, wells); } updateWellOps(); } ... void WellMultiSegment::initMultiSegmentWell(const Well* well, size_t time_step, const Wells* wells) { const auto& completion_set = well->getCompletions(time_step); void WellMultiSegment::initNonMultiSegmentWell(const Well* well, size_t time_step, const Wells* wells) { const auto& completion_set = well->getCompletions(time_step); ... void WellMultiSegment::updateWellOps() { m_wops_.s2p = Matrix(m_number_of_perforations_, m_number_of_segments_); m_wops_.p2s = Matrix(m_number_of_segments_, m_number_of_perforations_); +-----+ What calls "WellMultiSegment"? (could be huge!?) $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "WellMultiSegment" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep WellMultiSegment in OPM 170803 12h15m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : 7.2 kbytes +-----+ >> many like : opm-simulators/opm/autodiff/MultisegmentWells.cpp: MultisegmentWellOps::MultisegmentWellOps(const std::vector& wells_ms) opm-simulators/opm/autodiff/WellMultiSegment.cpp: std::string WellMultiSegment::compPressureDrop() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::compFrac() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: int WellMultiSegment::numberOfPhases() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::wellIndex() const { opm-simulators/opm/autodiff/WellMultiSegment.cpp: const std::vector& WellMultiSegment::perfDepth() const { ... opm-simulators/opm/autodiff/BlackoilMultiSegmentModel.hpp:#include opm-simulators/opm/autodiff/BlackoilMultiSegmentModel.hpp: const std::vector& wellsMultiSegment() const { return well_model_.msWells(); } ... opm-simulators/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp: WellMultiSegmentConstPtr well = wellsMultiSegment()[w]; ... opm_longname.txt:/home/bill/OPM/opm-simulators/opm/autodiff/WellMultiSegment.hpp opm_longname.txt:/home/bill/OPM/opm-simulators/opm/autodiff/WellMultiSegment.cpp +-----+ >> Almost all are in "opm-simulators/opm/autodiff/[MultisegmentWells,WellMultiSegment].[cpp,hpp]" >> three are in "opm-simulators/opm/autodiff/BlackoilMultiSegmentModel[hpp,_impl.hpp]" >> Two in "opm-simulators/opm/autodiff/WellStateMultiSegment.hpp" >> Two in "opm_longname.txt:" Look in "/home/bill/OPM/opm-simulators/opm/autodiff/[MultisegmentWells,WellMultiSegment].[cpp,hpp]" especially : opm-simulators/opm/autodiff/WellMultiSegment.cpp: std::string WellMultiSegment::compPressureDrop() const { ... std::string WellMultiSegment::compPressureDrop() const { return WellSegment::CompPressureDropEnumToString(m_comp_pressure_drop_); } >> Oops - I missed that last time I looked at the file So what calls m_comp_pressure_drop_ ?? $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "m_comp_pressure_drop_" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep m_comp_pressure_drop_ in OPM 170803 12h34m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-simulators/opm/autodiff/WellMultiSegment.hpp: WellSegment::CompPressureDropEnum m_comp_pressure_drop_; opm-simulators/opm/autodiff/WellMultiSegment.cpp: m_comp_pressure_drop_ = segment_set.compPressureDrop(); opm-simulators/opm/autodiff/WellMultiSegment.cpp: m_comp_pressure_drop_ = WellSegment::H__; opm-simulators/opm/autodiff/WellMultiSegment.cpp: return WellSegment::CompPressureDropEnumToString(m_comp_pressure_drop_); +-----+ >> OK, try WellSegment::H__ $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "WellSegment::H__" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep WellSegment::H__ in OPM 170803 12h37m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-simulators/opm/autodiff/WellMultiSegment.cpp: m_comp_pressure_drop_ = WellSegment::H__; +-----+ >> This doesn't help Try WellSegment::CompPressureDropEnum $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "WellSegment::CompPressureDropEnum" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep WellSegment::CompPressureDropEnum in OPM 170803 12h39m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-simulators/opm/autodiff/WellMultiSegment.hpp: WellSegment::CompPressureDropEnum m_comp_pressure_drop_; opm-simulators/opm/autodiff/WellMultiSegment.cpp: return WellSegment::CompPressureDropEnumToString(m_comp_pressure_drop_); opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.hpp: WellSegment::CompPressureDropEnum compPressureDrop() const; opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.hpp: WellSegment::CompPressureDropEnum m_comp_pressure_drop; opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.cpp: WellSegment::CompPressureDropEnum SegmentSet::compPressureDrop() const { opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.cpp: m_comp_pressure_drop = WellSegment::CompPressureDropEnumFromString(record1.getItem("PRESSURE_COMPONENTS").getTrimmedString(0)); opm-parser/opm/parser/eclipse/IntegrationTests/ParseMULTSEGWELL.cpp: const WellSegment::CompPressureDropEnum comp_pressure_drop = WellSegment::CompPressureDropEnumFromString(rec1.getItem("PRESSURE_COMPONENTS").getTrimmedString(0)); opm-parser/opm/parser/eclipse/IntegrationTests/ParseMULTSEGWELL.cpp: const std::string comp_pressure_drop_string = WellSegment::CompPressureDropEnumToString(comp_pressure_drop); +-----+ >> interesting things to look at opm-parser/opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.cpp: WellSegment::CompPressureDropEnum SegmentSet::compPressureDrop() const { >> nyet - I already looked at this opm-parser/opm/parser/eclipse/IntegrationTests/ParseMULTSEGWELL.cpp: const WellSegment::CompPressureDropEnum comp_pressure_drop = WellSegment::CompPressureDropEnumFromString(rec1.getItem("PRESSURE_COMPONENTS").getTrimmedString(0)); opm-parser/opm/parser/eclipse/IntegrationTests/ParseMULTSEGWELL.cpp: const std::string comp_pressure_drop_string = WellSegment::CompPressureDropEnumToString(comp_pressure_drop); >> 03Aug2017 12:47 I'm just going around in circles!! I have to learn how to track through C++ code Guessing, try "/home/bill/OPM/opm-simulators/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp" : +-----+ template SimulatorReport BlackoilMultiSegmentModel:: assemble(const ReservoirState& reservoir_state, WellState& well_state, const bool initial_assembly) { using namespace Opm::AutoDiffGrid; ... wellModel().computeSegmentFluidProperties(state); const double gravity = detail::getGravity(geo_.gravity(), UgGridHelpers::dimensions(grid_)); wellModel().computeSegmentPressuresDelta(gravity); std::vector mob_perfcells; std::vector b_perfcells; SimulatorReport report; wellModel().extractWellPerfProperties(state, sd_.rq, mob_perfcells, b_perfcells); if (param_.solve_welleq_initially_ && initial_assembly) { // solve the well equations as a pre-processing step report = asImpl().solveWellEq(mob_perfcells, b_perfcells, reservoir_state, state, well_state); } // the perforation flux here are different // it is related to the segment location V aliveWells; std::vector cq_s; wellModel().computeWellFlux(state, mob_perfcells, b_perfcells, aliveWells, cq_s); wellModel().updatePerfPhaseRatesAndPressures(cq_s, state, well_state); wellModel().addWellFluxEq(cq_s, state, residual_); asImpl().addWellContributionToMassBalanceEq(cq_s, state, well_state); wellModel().addWellControlEq(state, well_state, aliveWells, residual_); return report; } +-----+ >> OK, am I getting warmer? Try "computeSegmentPressuresDelta" $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "computeSegmentPressuresDelta" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep computeSegmentPressuresDelta in OPM 170803 12h55m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : +-----+ opm-simulators/opm/autodiff/MultisegmentWells.cpp: computeSegmentPressuresDelta(const double grav) opm-simulators/opm/autodiff/MultisegmentWells.hpp: computeSegmentPressuresDelta(const double grav); opm-simulators/opm/autodiff/BlackoilMultiSegmentModel_impl.hpp: wellModel().computeSegmentPressuresDelta(gravity); +-----+ >> Around in circles again It might help to have the opm-simulators docs - but my initial attempts couldn't build it (requests opm precedent or something) WAIT! random browsing : /home/bill/OPM/opm-core/opm/core/pressure/fsh.[c,h] >> Wow! but seems to be for formation, not a pipe, can't see Forchheimeer turbulent factor for porous media +-----+ hybsys_compute_press_flux(G->number_of_cells, G->cell_facepos, G->cell_faces, gpress, Binv, h->pimpl->sys, h->x, cpress, h->pimpl->cflux, h->pimpl->work); if (h->pimpl->nw > 0) { assert ((wpress != NULL) && (wflux != NULL)); hybsys_compute_press_flux_well(G->number_of_cells, G->cell_facepos, G->number_of_faces, h->pimpl->nw, h->pimpl->cwell_pos, h->pimpl->cwells, Binv, h->pimpl->WI, h->pimpl->wdp, h->pimpl->sys, h->pimpl->wsys, h->x, cpress, h->pimpl->cflux, wpress, wflux, h->pimpl->work); +-----+ >> I browsed through other files in /home/bill/OPM/opm-core/opm/core/pressure/, but saw no clear equation for pressure drop in well, although porous media pressure drops probably described. $ bash "/home/bill/OOPM builds/0_environment.sh" cd /home/bill/OPM grep 2>&1 -ri "pipe flow" | grep 2>&1 --invert-match "Binary file " | grep >"/home/bill/OOPM builds old/greps/grep pipe flow in OPM 170803 13h55m.txt" 2>&1 --invert-match "Permission denied" >> Results (manually copy-paste pertinent parts) : nothing 03Aug2017 14:16 STOP here Steve is going to subscribe via company Virtual Materials Group (VMG), 15k$ for 3-months VMG-Gasmod "Fully integrated gas reservoir/multi-phase gathering system simulator" including [well,reservoir,surface infrastructure] models. This is NOT Eclipse, and VMG is based in Calgary! VMG-Sim - Our flagship product; VMGSim is a world-class, rigorous and comprehensive steady-state process simulator developed with an integrated flowsheet design in a user-friendly, modern environment. No matter where you are in the world, a local VMG office or sales agent is within your continent. We have 3 offices located in Houston, Tokyo and Barcelona and 7 sales agents located worldwide. Our corporate and development headquarters are located in Calgary, Alberta, Canada.