void MucContact::changeAffiliation( ResourceContextRef rc, Affiliation newAffiliation ) { BOOST_ASSERT(newAffiliation<=OWNER); JabberDataBlockRef item=JabberDataBlockRef(new JabberDataBlock("item")); Jid rj(realJid); item->setAttribute("jid",rj.getBareJid()); item->setAttribute("affiliation",affiliationName[newAffiliation-OUTCAST]); //todo: // if (!reason.empty) item->addChild("reason", reason); changeMucItem(rc, item); }
double LCOrbits::ArmVelocity(int em, int rec, double trec) { LCVector ri(MT), rj(MT), vi(MT), vj(MT), rij(MT), nij(MT), n(MT); ri = position(rec, trec); vi = velocity(rec, trec); rj = position(em, trec); vj = velocity(em, trec); rij = rj-ri; nij = rij.unit(); n = nij * (-1.); return(vj*n-vi*n); }
void TestJoinNode() { tbb::flow::graph g; TestSimpleSuccessorArc<tbb::flow::queueing>("queueing"); TestSimpleSuccessorArc<tbb::flow::reserving>("reserving"); TestSimpleSuccessorArc<tbb::flow::tag_matching>("tag_matching"); // queueing and tagging join nodes have input queues, so the input ports do not reverse. REMARK(" reserving preds"); { tbb::flow::join_node<tbb::flow::tuple<int,int>, tbb::flow::reserving> rj(g); tbb::flow::queue_node<int> q0(g); tbb::flow::queue_node<int> q1(g); tbb::flow::make_edge(q0,tbb::flow::input_port<0>(rj)); tbb::flow::make_edge(q1,tbb::flow::input_port<1>(rj)); q0.try_put(1); g.wait_for_all(); // quiesce ASSERT(!(tbb::flow::input_port<0>(rj).my_predecessors.empty()),"reversed port missing predecessor"); ASSERT((tbb::flow::input_port<1>(rj).my_predecessors.empty()),"non-reversed port has pred"); g.reset(); ASSERT((tbb::flow::input_port<0>(rj).my_predecessors.empty()),"reversed port has pred after reset()"); ASSERT((tbb::flow::input_port<1>(rj).my_predecessors.empty()),"non-reversed port has pred after reset()"); q1.try_put(2); g.wait_for_all(); // quiesce ASSERT(!(tbb::flow::input_port<1>(rj).my_predecessors.empty()),"reversed port missing predecessor"); ASSERT((tbb::flow::input_port<0>(rj).my_predecessors.empty()),"non-reversed port has pred"); g.reset(); ASSERT((tbb::flow::input_port<1>(rj).my_predecessors.empty()),"reversed port has pred after reset()"); ASSERT((tbb::flow::input_port<0>(rj).my_predecessors.empty()),"non-reversed port has pred after reset()"); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES // should reset predecessors just as regular reset. q1.try_put(3); g.wait_for_all(); // quiesce ASSERT(!(tbb::flow::input_port<1>(rj).my_predecessors.empty()),"reversed port missing predecessor"); ASSERT((tbb::flow::input_port<0>(rj).my_predecessors.empty()),"non-reversed port has pred"); g.reset(tbb::flow::rf_extract); ASSERT((tbb::flow::input_port<1>(rj).my_predecessors.empty()),"reversed port has pred after reset()"); ASSERT((tbb::flow::input_port<0>(rj).my_predecessors.empty()),"non-reversed port has pred after reset()"); ASSERT(q0.my_successors.empty(), "edge not removed by reset(rf_extract)"); ASSERT(q1.my_successors.empty(), "edge not removed by reset(rf_extract)"); #endif } REMARK(" done\n"); }
BOOST_GPU_ENABLED void operator()(const A &a, B &b, boost::mpl::vector_c<int,1,0>, const G &g, const TB &tb, size_t ni, size_t nj) { BOOST_STATIC_ASSERT(A::dimensionality == 2); BOOST_STATIC_ASSERT(B::dimensionality == 2); const int Ni = ni/N + (ni%N > 0); const int Nj = nj/N + (nj%N > 0); for (int j = g.y(); j < Nj; j += g.ny()) { range rj(j*N, min<int>((j+1)*N,nj)); for (int i = g.x(); i < Ni; i += g.nx()) { range ri(i*N, min<int>((i+1)*N,ni)); tile<typename B::element,N> bij; bij.load(ri, rj, a, tb); bij.transpose(rj, ri, b, tb); } } }
BOOST_GPU_ENABLED void operator()(A &a, boost::mpl::vector_c<int,1,0>, const G &g, const TB &b, size_t n) { BOOST_STATIC_ASSERT(A::dimensionality == 2); typedef typename A::element T; const int nB = n/B + (n%B > 0); for (int j = g.y(); j < nB; j += g.ny()) { range rj(j*B, min<int>((j+1)*B,n)); for (int i = g.x(); i <= j; i += g.nx()) { range ri(i*B, min<int>((i+1)*B,n)); tile<T,B> aij, aji; aij.load(ri, rj, a, b); aji.load(rj, ri, a, b); aij.transpose(rj, ri, a, b); if (i == j) continue; aji.transpose(ri, rj, a, b); } } }
int main() { FILE *fin = fopen("packrec.in", "r"); FILE *fout = fopen("packrec.out", "w"); int i, j, k, l, p, index; int min = 0x7fff; index = 0; struct rec in[4], out[100]; for(i = 0; i < 4; i++) fscanf(fin, "%d %d", &in[i].side[0], &in[i].side[1]); for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ if(i == j) continue; for(k = 0; k < 4; k++){ if(k == i || k == j) continue; l = 6 - i - j - k; for(p = 0; p < 16; p++){ int h1, w1, h2, w2, h3, w3, h4, w4; h1 = in[i].side[1 - (ri(p))]; w1 = in[i].side[ri(p)]; h2 = in[j].side[1 - (rj(p))]; w2 = in[j].side[rj(p)]; h3 = in[k].side[1 - (rk(p))]; w3 = in[k].side[rk(p)]; h4 = in[l].side[1 - (rl(p))]; w4 = in[l].side[rl(p)]; int win, hin; win = w1 + w2 + w3 + w4; hin = max4(h1, h2, h3, h4); store(out, &index, win, hin, &min); win = max2(w1+w2+w3, w4); hin = max3(h1, h2, h3)+h4; store(out, &index, win, hin, &min); win = max2(w1+w2, w3)+w4; hin = max3(h1+h3, h2+h3, h4); store(out, &index, win, hin, &min); win = w1+w4+max2(w2, w3); hin = max3(h1, h2+h3, h4); store(out, &index, win, hin, &min); if(h3 >= h2+h4) win = max3(w1, w2+w3, w3+w4); else if(h3 > h4 && h3 < h2+h4) win = max3(w1+w2, w2+w3, w3+w4); else if(h3 < h4 && h2+h4 <= h1+h3) win = max3(w1+w2, w1+w4, w3+w4); else if(h4 >= h1+h3) win = max3(w2, w1+w4, w3+w4); else if(h3 == h4) win = max2(w1+w2, w3+w4); hin = max2(h1+h3, h2+h4); store(out, &index, win, hin, &min); } } } } insertionSort(out, index); fprintf(fout, "%d\n", min); for(i = 0; i < index; i++){ if(i != 0 && out[i].side[0] == out[i-1].side[0]) continue; fprintf(fout, "%d %d\n", out[i].side[0], out[i].side[1]); } fclose(fin); fclose(fout); }
double LCOrbits::ArmCompute(int em, int rec, double trec) { double tA(0.), tij; if ((em<1)||(em>NARMMAX)||((rec<1)&&(rec>NARMMAX))){ std::cerr << "ERROR in LCOrbits::ArmCompute : Spacecraft number must be in [0," << NARMMAX << "] ! " << Endl; throw std::invalid_argument ("ERROR in LCOrbits::ArmCompute : Spacecraft number must be in [0,NARMMAX] ! "); } /* if(OrderArm != -10) OrderArm = order_default; if ((OrderArm<-2)||(OrderArm>2)) throw std::invalid_argument ("ERROR in LCOrbits::ArmCompute : Order must be 0 (for 0), 1 (for 1/2), 2 (for 1) or -1 (for analytical MLDC eccentric formulation)"); */ if(OrderArm >= 0){ LCVector ri(MT), rj(MT), vi(MT), vj(MT), rij(MT), nij(MT), n(MT); /*! **** Read positions and velocities and compute related quantities * Index i refers to receiver and j to emitter * \f{eqnarray*}{ * \vec{r}_{ij} & = & \vec{r}_j - \vec{r}_i = \vec{r}_{em} - \vec{r}_{rec} \\ * \vec{n}_{ij} & = & \vec{r}_{ij} / | \vec{r}_{ij} | \\ * \hat{n} & = & - \vec{n}_{ij} \\ * t_{ij} & = & - | \vec{r}_{ij} | / c = - | \vec{r}_{em} - \vec{r}_{rec} | / c * \f} */ ri = position(rec, trec); vi = velocity(rec, trec); vi = vi/LC::c_SI; rj = position(em, trec); vj = velocity(em, trec); vj = vj/LC::c_SI; /* ri.p[0] = 5.e9; ri.p[1] = 0.; ri.p[2] = 0.; rj.p[0] = -1.e-5; rj.p[1] = 0.; rj.p[2] = 0.; rij = rj-ri; */ rij = rj-ri; nij = rij.unit(); n = nij*(-1.); tij = rij.norm()/LC::c_SI; tij = -tij; /* MT->o->precision(16); Cout << "em = " << em << " -> rec = " << rec << " : " << rij.norm() << " ==> " << tij << Endl; for(int i=0; i<3; i++) Cout << "\t\t" << ri.p[i] << "\t\t" << rj.p[i] << "\t\t" << rij.p[i] << Endl; */ if (OrderArm>=0) tA += ArmOrderContrib(0, tij, ri, rj, vi, vj, rij, nij, n); if (OrderArm>=1) tA += ArmOrderContrib(1, tij, ri, rj, vi, vj, rij, nij, n); if (OrderArm>=2) tA += ArmOrderContrib(2, tij, ri, rj, vi, vj, rij, nij, n); return (tA); }else{ return( ArmSpecific(em, rec, trec) ); } }
/* Compute the value of satellite antenna phase correction, in meters. * @param satid Satellite ID * @param time Epoch of interest * @param satpos Satellite position, as a Triple * @param sunpos Sun position, as a Triple * * @return Satellite antenna phase correction, in meters. */ double ComputeSatPCenter::getSatPCenter( const SatID& satid, const DayTime& time, const Triple& satpos, const Triple& sunPosition ) { // Unitary vector from satellite to Earth mass center (ECEF) Triple rk( ( (-1.0)*(satpos.unitVector()) ) ); // Unitary vector from Earth mass center to Sun (ECEF) Triple ri( sunPosition.unitVector() ); // rj = rk x ri: Rotation axis of solar panels (ECEF) Triple rj(rk.cross(ri)); // Redefine ri: ri = rj x rk (ECEF) ri = rj.cross(rk); // Let's convert ri to an unitary vector. (ECEF) ri = ri.unitVector(); // Get vector from Earth mass center to receiver Triple rxPos(nominalPos.X(), nominalPos.Y(), nominalPos.Z()); // Compute unitary vector vector from satellite to RECEIVER Triple rrho( (rxPos-satpos).unitVector() ); // When not using Antex information, if satellite belongs to block // "IIR" its correction is 0.0, else it will depend on satellite model. // This variable that will hold the correction, 0.0 by default double svPCcorr(0.0); // Check is Antex antenna information is available or not, and if // available, whether satellite phase center information is absolute // or relative bool absoluteModel( false ); if( pAntexReader != NULL ) { absoluteModel = pAntexReader->isAbsolute(); } if( absoluteModel ) { // We will need the elevation, in degrees. It is found using // dot product and the corresponding unitary angles double elev( 90.0 - (std::acos( rrho.dot(rk) ) * RAD_TO_DEG) ); // Get satellite information in Antex format. Currently this // only works for GPS and Glonass. if( satid.system == SatID::systemGPS ) { std::stringstream sat; sat << "G"; if( satid.id < 10 ) { sat << "0"; } sat << satid.id; // Get satellite antenna information out of AntexReader object Antenna antenna( pAntexReader->getAntenna( sat.str(), time ) ); // Get antenna eccentricity for frequency "G01" (L1), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! Triple satAnt( antenna.getAntennaEccentricity( Antenna::G01) ); // Now, get the phase center variation. Triple var( antenna.getAntennaPCVariation( Antenna::G01, elev) ); // We must substract them satAnt = satAnt - var; // Change to ECEF Triple svAntenna( satAnt[2]*ri + satAnt[1]*rj + satAnt[0]*rk ); // Projection of "svAntenna" vector to line of sight vector rrho svPCcorr = (rrho.dot(svAntenna)); } else { // Check if this satellite belongs to Glonass system if( satid.system == SatID::systemGlonass ) { std::stringstream sat; sat << "R"; if( satid.id < 10 ) { sat << "0"; } sat << satid.id; // Get satellite antenna information out of AntexReader object Antenna antenna( pAntexReader->getAntenna( sat.str(), time ) ); // Get antenna offset for frequency "R01" (Glonass), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! Triple satAnt( antenna.getAntennaEccentricity( Antenna::R01) ); // Now, get the phase center variation. Triple var( antenna.getAntennaPCVariation( Antenna::R01, elev) ); // We must substract them satAnt = satAnt - var; // Change to ECEF Triple svAntenna( satAnt[2]*ri + satAnt[1]*rj + satAnt[0]*rk ); // Project "svAntenna" vector to line of sight vector rrho svPCcorr = (rrho.dot(svAntenna)); } else { // In this case no correction will be computed svPCcorr = 0.0; } } // End of 'if( satid.system == SatID::systemGPS )...' } else { // If no Antex information is given, or if phase center information // uses a relative model, then use a simpler, older approach // Please note that in this case all GLONASS satellite are // considered as having phase center at (0.0, 0.0, 0.0). The former // is not true for 'GLONASS-M' satellites (-0.545, 0.0, 0.0 ), but // currently there is no simple way to take this into account. // For satellites II and IIA: if( (satData.getBlock( satid, time ) == "II") || (satData.getBlock( satid, time ) == "IIA") ) { // First, build satellite antenna vector for models II/IIA Triple svAntenna(0.279*ri + 1.023*rk); // Projection of "svAntenna" vector to line of sight vector rrho svPCcorr = (rrho.dot(svAntenna)); } else { // For satellites belonging to block "I" if( (satData.getBlock( satid, time ) == "I") ) { // First, build satellite antenna vector for model I Triple svAntenna(0.210*ri + 0.854*rk); // Projection of "svAntenna" to line of sight vector (rrho) svPCcorr = (rrho.dot(svAntenna)); } } // End of 'if( (satData.getBlock( satid, time ) == "II") ||...' } // End of 'if( absoluteModel )...' // This correction is interpreted as an "advance" in the signal, // instead of a delay. Therefore, it has negative sign return (-svPCcorr); } // End of method 'ComputeSatPCenter::getSatPCenter()'
int main(int argc, char** argv) try { if (argc == 1) { std::cout << "Usage: cpchop gridfilename=filename.grdecl [subsamples=10] [ilen=5] [jlen=5] " << std::endl; std::cout << " [zlen=5] [imin=] [imax=] [jmin=] [jmax=] [upscale=true] [bc=fixed]" << std::endl; std::cout << " [resettoorigin=true] [seed=111] [z_tolerance=0.0] [minperm=1e-9] " << std::endl; std::cout << " [dips=false] [azimuthdisplacement=] [satnumvolumes=false] [mincellvolume=1e-9]" << std::endl; std::cout << " [filebase=] [resultfile=] [endpoints=false] [cappres=false]" << std::endl; std::cout << " [rock_list=] [anisotropicrocks=false]" << std::endl; exit(1); } Opm::parameter::ParameterGroup param(argc, argv); std::string gridfilename = param.get<std::string>("gridfilename"); Opm::CornerPointChopper ch(gridfilename); // The cells with i coordinate in [imin, imax) are included, similar for j. // The z limits may be changed inside the chopper to match actual min/max z. const int* dims = ch.dimensions(); int imin = param.getDefault("imin", 0); int imax = param.getDefault("imax", dims[0]); int jmin = param.getDefault("jmin", 0); int jmax = param.getDefault("jmax", dims[1]); double zmin = param.getDefault("zmin", ch.zLimits().first); double zmax = param.getDefault("zmax", ch.zLimits().second); int subsamples = param.getDefault("subsamples", 1); int ilen = param.getDefault("ilen", imax - imin); int jlen = param.getDefault("jlen", jmax - jmin); double zlen = param.getDefault("zlen", zmax - zmin); bool upscale = param.getDefault("upscale", true); std::string bc = param.getDefault<std::string>("bc", "fixed"); bool resettoorigin = param.getDefault("resettoorigin", true); boost::mt19937::result_type userseed = param.getDefault("seed", 0); int outputprecision = param.getDefault("outputprecision", 8); std::string filebase = param.getDefault<std::string>("filebase", ""); std::string resultfile = param.getDefault<std::string>("resultfile", ""); double minperm = param.getDefault("minperm", 1e-9); double minpermSI = Opm::unit::convert::from(minperm, Opm::prefix::milli*Opm::unit::darcy); // Following two options are for dip upscaling (slope of cell top and bottom edges) bool dips = param.getDefault("dips", false); // whether to do dip averaging double azimuthdisplacement = param.getDefault("azimuthdisplacement", 0.0); // posibility to add/subtract a value to/from azimuth for dip plane. double mincellvolume = param.getDefault("mincellvolume", 1e-9); // ignore smaller cells for dip calculations bool satnumvolumes = param.getDefault("satnumvolumes", false); // whether to count volumes pr. satnum // upscaling of endpoints and capillary pressure // Conversion factor, multiply mD numbers with this to get m² numbers const double milliDarcyToSqMetre = 9.869233e-16; // Input for surfaceTension is dynes/cm, SI units are Joules/square metre const double surfaceTension = param.getDefault("surfaceTension", 11.0) * 1e-3; // multiply with 10^-3 to obtain SI units bool endpoints = param.getDefault("endpoints", false); // whether to upscale saturation endpoints bool cappres = param.getDefault("cappres", false); // whether to upscale capillary pressure if (cappres) { endpoints = true; } std::string rock_list = param.getDefault<std::string>("rock_list", "no_list"); bool anisorocks = param.getDefault("anisotropicrocks", false); std::vector<std::vector<double> > rocksatendpoints_; std::vector<std::vector<double> > jfuncendpoints_; // Used if isotropic rock input int nsatpoints = 5; // nuber of saturation points in upscaled capillary pressure function per subsample double saturationThreshold = 0.00001; // For isotropic input rocks: std::vector<Opm::MonotCubicInterpolator> InvJfunctions; // Holds the inverse of the loaded J-functions. // For anisotropic input rocks: std::vector<Opm::MonotCubicInterpolator> SwPcfunctions; // Holds Sw(Pc) for each rocktype. // Read rock data from files specifyed in rock_list if (endpoints) { if (!rock_list.compare("no_list")) { std::cout << "Can't do endponts without rock list (" << rock_list << ")" << std::endl; throw std::exception(); } // Code copied from ReservoirPropertyCommon.hpp for file reading std::ifstream rl(rock_list.c_str()); if (!rl) { OPM_THROW(std::runtime_error, "Could not open file " << rock_list); } int num_rocks = -1; rl >> num_rocks; assert(num_rocks >= 1); rocksatendpoints_.resize(num_rocks); jfuncendpoints_.resize(num_rocks); // Loop through rock files defined in rock_list and store the data we need for (int i = 0; i < num_rocks; ++i) { std::string spec; while (spec.empty()) { std::getline(rl, spec); } // Read the contents of the i'th rock std::istringstream specstream(spec); std::string rockname; specstream >> rockname; std::string rockfilename = rockname; std::ifstream rock_stream(rockfilename.c_str()); if (!rock_stream) { OPM_THROW(std::runtime_error, "Could not open file " << rockfilename); } if (! anisorocks) { //Isotropic input rocks (Sw Krw Kro J) Opm::MonotCubicInterpolator Jtmp; try { Jtmp = Opm::MonotCubicInterpolator(rockname, 1, 4); } catch (const char * errormessage) { std::cerr << "Error: " << errormessage << std::endl; std::cerr << "Check filename" << std::endl; exit(1); } // Invert J-function, now we get saturation as a function of pressure: if (Jtmp.isStrictlyMonotone()) { InvJfunctions.push_back(Opm::MonotCubicInterpolator(Jtmp.get_fVector(), Jtmp.get_xVector())); } else { std::cerr << "Error: Jfunction " << i+1 << " in rock file " << rockname << " was not invertible." << std::endl; exit(1); } jfuncendpoints_[i][0] = Jtmp.getMinimumX().second; jfuncendpoints_[i][1] = Jtmp.getMaximumX().second; rocksatendpoints_[i][0] = Jtmp.getMinimumX().first; rocksatendpoints_[i][1] = Jtmp.getMaximumX().first; if (rocksatendpoints_[i][0] < 0 || rocksatendpoints_[i][0] > 1) { OPM_THROW(std::runtime_error, "Minimum rock saturation (" << rocksatendpoints_[i][0] << ") not sane for rock " << rockfilename << "." << std::endl << "Did you forget to specify anisotropicrocks=true ?"); } } else { //Anisotropic input rocks (Pc Sw Krxx Kryy Krzz) Opm::MonotCubicInterpolator Pctmp; try { Pctmp = Opm::MonotCubicInterpolator(rockname, 2, 1); } catch (const char * errormessage) { std::cerr << "Error: " << errormessage << std::endl; std::cerr << "Check filename and columns 1 and 2 (Pc and Sw)" << std::endl; exit(1); } if (cappres) { // Invert Pc(Sw) curve into Sw(Pc): if (Pctmp.isStrictlyMonotone()) { SwPcfunctions.push_back(Opm::MonotCubicInterpolator(Pctmp.get_fVector(), Pctmp.get_xVector())); } else { std::cerr << "Error: Pc(Sw) curve " << i+1 << " in rock file " << rockname << " was not invertible." << std::endl; exit(1); } } rocksatendpoints_[i][0] = Pctmp.getMinimumX().first; rocksatendpoints_[i][1] = Pctmp.getMaximumX().first; } } } double z_tolerance = param.getDefault("z_tolerance", 0.0); double residual_tolerance = param.getDefault("residual_tolerance", 1e-8); int linsolver_verbosity = param.getDefault("linsolver_verbosity", 0); int linsolver_type = param.getDefault("linsolver_type", 1); // Guarantee initialization double Pcmax = -DBL_MAX, Pcmin = DBL_MAX; // Check that we do not have any user input // that goes outside the coordinates described in // the cornerpoint file (runtime-exception will be thrown in case of error) ch.verifyInscribedShoebox(imin, ilen, imax, jmin, jlen, jmax, zmin, zlen, zmax); // Random number generator from boost. boost::mt19937 gen; // Seed the random number generators with the current time, unless specified on command line // Warning: Current code does not allow 0 for the seed!! boost::mt19937::result_type autoseed = time(NULL); if (userseed == 0) { gen.seed(autoseed); } else { gen.seed(userseed); } Opm::SinglePhaseUpscaler::BoundaryConditionType bctype = Opm::SinglePhaseUpscaler::Fixed; bool isFixed, isPeriodic; isFixed = isPeriodic = false; if (upscale) { if (bc == "fixed") { isFixed = true; bctype = Opm::SinglePhaseUpscaler::Fixed; } else if (bc == "periodic") { isPeriodic = true; bctype = Opm::SinglePhaseUpscaler::Periodic; } else { std::cout << "Boundary condition type (bc=" << bc << ") not allowed." << std::endl; std::cout << "Only bc=fixed or bc=periodic implemented." << std::endl; throw std::exception(); } } // Check for unused parameters (potential typos). if (param.anyUnused()) { std::cout << "***** WARNING: Unused parameters: *****\n"; param.displayUsage(); } // Note that end is included in interval for uniform_int. boost::uniform_int<> disti(imin, imax - ilen); boost::uniform_int<> distj(jmin, jmax - jlen); boost::uniform_real<> distz(zmin, std::max(zmax - zlen, zmin)); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > ri(gen, disti); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rj(gen, distj); boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rz(gen, distz); // Storage for results std::vector<double> porosities; std::vector<double> permxs; std::vector<double> permys; std::vector<double> permzs; std::vector<double> permyzs; std::vector<double> permxzs; std::vector<double> permxys; std::vector<double> minsws, maxsws; std::vector<std::vector<double> > pcvalues; std::vector<double> dipangs, azimuths; // Initialize a matrix for subsample satnum volumes. // Outer index is subsample index, inner index is SATNUM-value std::vector<std::vector<double> > rockvolumes; int maxSatnum = 0; // This value is determined from the chopped cells. int finished_subsamples = 0; // keep explicit count of successful subsamples for (int sample = 1; sample <= subsamples; ++sample) { int istart = ri(); int jstart = rj(); double zstart = rz(); ch.chop(istart, istart + ilen, jstart, jstart + jlen, zstart, zstart + zlen, resettoorigin); std::string subsampledgrdecl = filebase; // Output grdecl-data to file if a filebase is supplied. if (filebase != "") { std::ostringstream oss; if ((size_t) subsamples > 1) { // Only add number to filename if more than one sample is asked for oss << 'R' << std::setw(4) << std::setfill('0') << sample; subsampledgrdecl += oss.str(); } subsampledgrdecl += ".grdecl"; ch.writeGrdecl(subsampledgrdecl); } try { /* The upscaling may fail to converge on icky grids, lets just pass by those */ if (upscale) { Opm::EclipseGridParser subparser = ch.subparser(); subparser.convertToSI(); Opm::SinglePhaseUpscaler upscaler; upscaler.init(subparser, bctype, minpermSI, z_tolerance, residual_tolerance, linsolver_verbosity, linsolver_type, false); Opm::SinglePhaseUpscaler::permtensor_t upscaled_K = upscaler.upscaleSinglePhase(); upscaled_K *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); porosities.push_back(upscaler.upscalePorosity()); permxs.push_back(upscaled_K(0,0)); permys.push_back(upscaled_K(1,1)); permzs.push_back(upscaled_K(2,2)); permyzs.push_back(upscaled_K(1,2)); permxzs.push_back(upscaled_K(0,2)); permxys.push_back(upscaled_K(0,1)); } if (endpoints) { // Calculate minimum and maximum water volume in each cell // Create single-phase upscaling object to get poro and perm values from the grid Opm::EclipseGridParser subparser = ch.subparser(); std::vector<double> perms = subparser.getFloatingPointValue("PERMX"); subparser.convertToSI(); Opm::SinglePhaseUpscaler upscaler; upscaler.init(subparser, bctype, minpermSI, z_tolerance, residual_tolerance, linsolver_verbosity, linsolver_type, false); std::vector<int> satnums = subparser.getIntegerValue("SATNUM"); std::vector<double> poros = subparser.getFloatingPointValue("PORO"); std::vector<double> cellVolumes, cellPoreVolumes; cellVolumes.resize(satnums.size(), 0.0); cellPoreVolumes.resize(satnums.size(), 0.0); int tesselatedCells = 0; //double maxSinglePhasePerm = 0; double Swirvolume = 0; double Sworvolume = 0; const std::vector<int>& ecl_idx = upscaler.grid().globalCell(); Dune::CpGrid::Codim<0>::LeafIterator c = upscaler.grid().leafbegin<0>(); for (; c != upscaler.grid().leafend<0>(); ++c) { unsigned int cell_idx = ecl_idx[c->index()]; if (satnums[cell_idx] > 0) { // Satnum zero is "no rock" cellVolumes[cell_idx] = c->geometry().volume(); cellPoreVolumes[cell_idx] = cellVolumes[cell_idx] * poros[cell_idx]; double Pcmincandidate = 0.0, Pcmaxcandidate = 0.0, minSw, maxSw; if (!anisorocks) { if (cappres) { Pcmincandidate = jfuncendpoints_[int(satnums[cell_idx])-1][1] / sqrt(perms[cell_idx] * milliDarcyToSqMetre/poros[cell_idx]) * surfaceTension; Pcmaxcandidate = jfuncendpoints_[int(satnums[cell_idx])-1][0] / sqrt(perms[cell_idx] * milliDarcyToSqMetre/poros[cell_idx]) * surfaceTension; } minSw = rocksatendpoints_[int(satnums[cell_idx])-1][0]; maxSw = rocksatendpoints_[int(satnums[cell_idx])-1][1]; } else { // anisotropic input, we do not to J-function scaling if (cappres) { Pcmincandidate = SwPcfunctions[int(satnums[cell_idx])-1].getMinimumX().first; Pcmaxcandidate = SwPcfunctions[int(satnums[cell_idx])-1].getMaximumX().first; } minSw = rocksatendpoints_[int(satnums[cell_idx])-1][0]; maxSw = rocksatendpoints_[int(satnums[cell_idx])-1][1]; } if (cappres) { Pcmin = std::min(Pcmincandidate, Pcmin); Pcmax = std::max(Pcmaxcandidate, Pcmax); } Swirvolume += minSw * cellPoreVolumes[cell_idx]; Sworvolume += maxSw * cellPoreVolumes[cell_idx]; } ++tesselatedCells; // keep count. } // If upscling=false, we still (may) want to have porosities together with endpoints if (!upscale) { porosities.push_back(upscaler.upscalePorosity()); } // Total porevolume and total volume -> upscaled porosity: double poreVolume = std::accumulate(cellPoreVolumes.begin(), cellPoreVolumes.end(), 0.0); double Swir = Swirvolume/poreVolume; double Swor = Sworvolume/poreVolume; minsws.push_back(Swir); maxsws.push_back(Swor); if (cappres) { // Upscale capillary pressure function Opm::MonotCubicInterpolator WaterSaturationVsCapPressure; double largestSaturationInterval = Swor-Swir; double Ptestvalue = Pcmax; while (largestSaturationInterval > (Swor-Swir)/double(nsatpoints)) { if (Pcmax == Pcmin) { // This is a dummy situation, we go through once and then // we are finished (this will be triggered by zero permeability) Ptestvalue = Pcmin; largestSaturationInterval = 0; } else if (WaterSaturationVsCapPressure.getSize() == 0) { /* No data values previously computed */ Ptestvalue = Pcmax; } else if (WaterSaturationVsCapPressure.getSize() == 1) { /* If only one point has been computed, it was for Pcmax. So now do Pcmin */ Ptestvalue = Pcmin; } else { /* Search for largest saturation interval in which there are no computed saturation points (and estimate the capillary pressure that will fall in the center of this saturation interval) */ std::pair<double,double> SatDiff = WaterSaturationVsCapPressure.getMissingX(); Ptestvalue = SatDiff.first; largestSaturationInterval = SatDiff.second; } // Check for saneness of Ptestvalue: if (std::isnan(Ptestvalue) || std::isinf(Ptestvalue)) { std::cerr << "ERROR: Ptestvalue was inf or nan" << std::endl; break; // Jump out of while-loop, just print out the results // up to now and exit the program } double waterVolume = 0.0; for (unsigned int i = 0; i < ecl_idx.size(); ++i) { unsigned int cell_idx = ecl_idx[i]; double waterSaturationCell = 0.0; if (satnums[cell_idx] > 0) { // handle "no rock" cells with satnum zero double PtestvalueCell; PtestvalueCell = Ptestvalue; if (!anisorocks) { double Jvalue = sqrt(perms[cell_idx] * milliDarcyToSqMetre /poros[cell_idx]) * PtestvalueCell / surfaceTension; waterSaturationCell = InvJfunctions[int(satnums[cell_idx])-1].evaluate(Jvalue); } else { // anisotropic_input, then we do not do J-function-scaling waterSaturationCell = SwPcfunctions[int(satnums[cell_idx])-1].evaluate(PtestvalueCell); } } waterVolume += waterSaturationCell * cellPoreVolumes[cell_idx]; } WaterSaturationVsCapPressure.addPair(Ptestvalue, waterVolume/poreVolume); } WaterSaturationVsCapPressure.chopFlatEndpoints(saturationThreshold); std::vector<double> wattest = WaterSaturationVsCapPressure.get_fVector(); std::vector<double> cprtest = WaterSaturationVsCapPressure.get_xVector(); Opm::MonotCubicInterpolator CapPressureVsWaterSaturation(WaterSaturationVsCapPressure.get_fVector(), WaterSaturationVsCapPressure.get_xVector()); std::vector<double> pcs; for (int satp=0; satp<nsatpoints; ++satp) { pcs.push_back(CapPressureVsWaterSaturation.evaluate(Swir+(Swor-Swir)/(nsatpoints-1)*satp)); } pcvalues.push_back(pcs); } } if (dips) { Opm::EclipseGridParser subparser = ch.subparser(); std::vector<int> griddims = subparser.getSPECGRID().dimensions; std::vector<double> xdips_subsample, ydips_subsample; Opm::EclipseGridInspector gridinspector(subparser); for (int k=0; k < griddims[2]; ++k) { for (int j=0; j < griddims[1]; ++j) { for (int i=0; i < griddims[0]; ++i) { if (gridinspector.cellVolumeVerticalPillars(i, j, k) > mincellvolume) { std::pair<double,double> xydip = gridinspector.cellDips(i, j, k); xdips_subsample.push_back(xydip.first); ydips_subsample.push_back(xydip.second); } } } } // double azimuth = atan(xydip.first/xydip.second); // double dip = acos(1.0/sqrt(pow(xydip.first,2.0)+pow(xydip.second,2.0)+1.0)); // dips_subsample.push_back( xydip.first ); // azims_subsample.push_back(atan(xydip.first/xydip.second)); // Average xdips and ydips double xdipaverage = accumulate(xdips_subsample.begin(), xdips_subsample.end(), 0.0)/xdips_subsample.size(); double ydipaverage = accumulate(ydips_subsample.begin(), ydips_subsample.end(), 0.0)/ydips_subsample.size(); // Convert to dip and azimuth double azimuth = atan(xdipaverage/ydipaverage)+azimuthdisplacement; double dip = acos(1.0/sqrt(pow(xdipaverage,2.0)+pow(ydipaverage,2.0)+1.0)); dipangs.push_back(dip); azimuths.push_back(azimuth); } if (satnumvolumes) { Opm::EclipseGridParser subparser = ch.subparser(); Opm::EclipseGridInspector subinspector(subparser); std::vector<int> griddims = subparser.getSPECGRID().dimensions; int number_of_subsamplecells = griddims[0] * griddims[1] * griddims[2]; // If SATNUM is non-existent in input grid, this will fail: std::vector<int> satnums = subparser.getIntegerValue("SATNUM"); std::vector<double> rockvolumessubsample; for (int cell_idx=0; cell_idx < number_of_subsamplecells; ++cell_idx) { maxSatnum = std::max(maxSatnum, int(satnums[cell_idx])); rockvolumessubsample.resize(maxSatnum); // Ensure long enough vector rockvolumessubsample[int(satnums[cell_idx])-1] += subinspector.cellVolumeVerticalPillars(cell_idx); } // Normalize volumes to obtain relative volumes: double subsamplevolume = std::accumulate(rockvolumessubsample.begin(), rockvolumessubsample.end(), 0.0); std::vector<double> rockvolumessubsample_normalized; for (size_t satnum_idx = 0; satnum_idx < rockvolumessubsample.size(); ++satnum_idx) { rockvolumessubsample_normalized.push_back(rockvolumessubsample[satnum_idx]/subsamplevolume); } rockvolumes.push_back(rockvolumessubsample_normalized); } finished_subsamples++; } catch (...) { std::cerr << "Warning: Upscaling chopped subsample nr. " << sample << " failed, proceeding to next subsample\n"; } } // Make stream of output data, to be outputted to screen and optionally to file std::stringstream outputtmp; outputtmp << "################################################################################################" << std::endl; outputtmp << "# Results from property analysis on subsamples" << std::endl; outputtmp << "#" << std::endl; time_t now = time(NULL); outputtmp << "# Finished: " << asctime(localtime(&now)); utsname hostname; uname(&hostname); outputtmp << "# Hostname: " << hostname.nodename << std::endl; outputtmp << "#" << std::endl; outputtmp << "# Options used:" << std::endl; outputtmp << "# gridfilename: " << gridfilename << std::endl; outputtmp << "# i; min,len,max: " << imin << " " << ilen << " " << imax << std::endl; outputtmp << "# j; min,len,max: " << jmin << " " << jlen << " " << jmax << std::endl; outputtmp << "# z; min,len,max: " << zmin << " " << zlen << " " << zmax << std::endl; outputtmp << "# subsamples: " << subsamples << std::endl; if (userseed == 0) { outputtmp << "# (auto) seed: " << autoseed << std::endl; } else { outputtmp << "# (manual) seed: " << userseed << std::endl; } outputtmp << "################################################################################################" << std::endl; outputtmp << "# id"; if (upscale) { if (isPeriodic) { outputtmp << " porosity permx permy permz permyz permxz permxy"; } else if (isFixed) { outputtmp << " porosity permx permy permz"; } } if (endpoints) { if (!upscale) { outputtmp << " porosity"; } outputtmp << " Swir Swor"; if (cappres) { outputtmp << " Pc(Swir) Pc2 Pc3 Pc4 Pc(Swor)"; } } if (dips) { outputtmp << " dip azim(displacement:" << azimuthdisplacement << ")"; } if (satnumvolumes) { for (int satnumidx = 0; satnumidx < maxSatnum; ++satnumidx) { outputtmp << " satnum_" << satnumidx+1; } } outputtmp << std::endl; const int fieldwidth = outputprecision + 8; for (int sample = 1; sample <= finished_subsamples; ++sample) { outputtmp << sample << '\t'; if (upscale) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << porosities[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permxs[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permys[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permzs[sample-1] << '\t'; if (isPeriodic) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permyzs[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permxzs[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permxys[sample-1] << '\t'; } } if (endpoints) { if (!upscale) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << porosities[sample-1] << '\t'; } outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << minsws[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << maxsws[sample-1]; if (cappres) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << pcvalues[sample-1][0] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << pcvalues[sample-1][1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << pcvalues[sample-1][2] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << pcvalues[sample-1][3] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << pcvalues[sample-1][4]; } } if (dips) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << dipangs[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << azimuths[sample-1]; } if (satnumvolumes) { rockvolumes[sample-1].resize(maxSatnum, 0.0); for (int satnumidx = 0; satnumidx < maxSatnum; ++satnumidx) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << rockvolumes[sample-1][satnumidx] << '\t'; } } outputtmp << std::endl; } if (resultfile != "") { std::cout << "Writing results to " << resultfile << std::endl; std::ofstream outfile; outfile.open(resultfile.c_str(), std::ios::out | std::ios::trunc); outfile << outputtmp.str(); outfile.close(); } std::cout << outputtmp.str(); } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
int main(int argc, char** argv) try { Dune::MPIHelper::instance(argc, argv); Opm::parameter::ParameterGroup param(argc, argv); std::string gridfilename = param.get<std::string>("gridfilename"); Opm::CornerPointChopper ch(gridfilename); // The cells with i coordinate in [imin, imax) are included, similar for j. // The z limits may be changed inside the chopper to match actual min/max z. const int* dims = ch.dimensions(); int imin = param.getDefault("imin", 0); int imax = param.getDefault("imax", dims[0]); int jmin = param.getDefault("jmin", 0); int jmax = param.getDefault("jmax", dims[1]); double zmin = param.getDefault("zmin", ch.zLimits().first); double zmax = param.getDefault("zmax", ch.zLimits().second); int pairs = param.getDefault("pairs", 100); std::string direction = param.get<std::string>("direction"); int ilen = param.getDefault("ilen", 0); int jlen = param.getDefault("jlen", 0); double zlen = param.getDefault("zlen", 0.0); boost::mt19937::result_type userseed = param.getDefault("seed", 0); int outputprecision = param.getDefault("outputprecision", 8); std::string resultfile = param.getDefault<std::string>("resultfile", ""); double minperm = param.getDefault("minperm", 1e-9); double minpermSI = Opm::unit::convert::from(minperm, Opm::prefix::milli*Opm::unit::darcy); double z_tolerance = param.getDefault("z_tolerance", 0.0); double residual_tolerance = param.getDefault("residual_tolerance", 1e-8); int linsolver_verbosity = param.getDefault("linsolver_verbosity", 0); int linsolver_type = param.getDefault("linsolver_type", 1); // Check for unused parameters (potential typos). if (param.anyUnused()) { std::cout << "***** WARNING: Unused parameters: *****\n"; param.displayUsage(); } if (ilen <= 0) { std::cerr << "Error: ilen (" << ilen << ") must be greater than zero\n"; exit(1); } if (jlen <= 0) { std::cerr << "Error: jlen (" << jlen <<") must be greater than zero\n"; exit(1); } if (zlen <= 0.0) { std::cerr << "Eror: zlen (" << zlen <<") must be greater than zero\n"; exit(1); } // Check user supplied variogram direction, either horizontal or vertical enum variogram_directions { undefined, horizontal, vertical }; variogram_directions variogram_direction = undefined; std::string distancemetric; if ( direction == "vertical" || direction == "vert" ) { variogram_direction = vertical; distancemetric = "zcorn"; } else { // if (direction == "horizontal" || direction == "horiz") { variogram_direction = horizontal; distancemetric = "cells"; } if (variogram_direction == undefined) { std::cerr << "Error: variogram direction is undefined, user supplied '" << direction << "'.\n"; exit(1); } // Check that we do not have any user input // that goes outside the coordinates described in // the cornerpoint file (runtime-exception will be thrown in case of error) ch.verifyInscribedShoebox(imin, ilen, imax, jmin, jlen, jmax, zmin, zlen, zmax); // Random number generator from boost. boost::mt19937 gen; // Seed the random number generators with the current time, unless specified on command line // Warning: Current code does not allow 0 for the seed!! if (userseed == 0) { gen.seed(time(NULL)); } else { gen.seed(userseed); } // Note that end is included in interval for uniform_int. boost::uniform_int<> disti(imin, imax - ilen); boost::uniform_int<> distj(jmin, jmax - jlen); boost::uniform_real<> distz(zmin, std::max(zmax - zlen, zmin)); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > ri(gen, disti); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rj(gen, distj); boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rz(gen, distz); // Storage for results std::vector<double> distances; std::vector<double> porodiffs; std::vector<double> permxdiffs; std::vector<double> permydiffs; std::vector<double> permzdiffs; for (int pair = 1; pair <= pairs; ++pair) { int istart_1 = ri(); int jstart_1 = rj(); double zstart_1 = rz(); ch.chop(istart_1, istart_1 + ilen, jstart_1, jstart_1 + jlen, zstart_1, zstart_1 + zlen, false); Opm::EclipseGridParser subparser_1 = ch.subparser(); subparser_1.convertToSI(); Opm::SinglePhaseUpscaler upscaler_1; upscaler_1.init(subparser_1, Opm::SinglePhaseUpscaler::Fixed, minpermSI, z_tolerance, residual_tolerance, linsolver_verbosity, linsolver_type, false); Opm::SinglePhaseUpscaler::permtensor_t upscaled_K_1 = upscaler_1.upscaleSinglePhase(); upscaled_K_1 *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); double porosity_1 = upscaler_1.upscalePorosity(); // Pick another location to form a location-pair to be compared int istart_2 = 0, jstart_2 = 0; double zstart_2 = 0; if (variogram_direction == horizontal) { istart_2 = ri(); jstart_2 = rj(); zstart_2 = zstart_1; } else if (variogram_direction == vertical) { istart_2 = istart_1; jstart_2 = jstart_1; zstart_2 = rz(); } ch.chop(istart_2, istart_2 + ilen, jstart_2, jstart_2 + jlen, zstart_2, zstart_2 + zlen, false); Opm::EclipseGridParser subparser_2 = ch.subparser(); subparser_2.convertToSI(); Opm::SinglePhaseUpscaler upscaler_2; upscaler_2.init(subparser_2, Opm::SinglePhaseUpscaler::Fixed, minpermSI, z_tolerance, residual_tolerance, linsolver_verbosity, linsolver_type, false); Opm::SinglePhaseUpscaler::permtensor_t upscaled_K_2 = upscaler_2.upscaleSinglePhase(); upscaled_K_2 *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); double porosity_2 = upscaler_2.upscalePorosity(); if (variogram_direction == horizontal) { distances.push_back(sqrt(pow(istart_2 - istart_1,2) + pow(jstart_2 - jstart_1,2))); } else if (variogram_direction == vertical) { distances.push_back(fabs(zstart_2 - zstart_1)); } porodiffs.push_back(fabs(porosity_2 - porosity_1)); permxdiffs.push_back(fabs(upscaled_K_2(0,0) - upscaled_K_1(0,0))); permydiffs.push_back(fabs(upscaled_K_2(1,1) - upscaled_K_1(1,1))); permzdiffs.push_back(fabs(upscaled_K_2(2,2) - upscaled_K_1(2,2))); } // Make stream of output data, to be outputted to screen and optionally to file std::stringstream outputtmp; outputtmp << "################################################################################################" << std::endl; outputtmp << "# Data for experimental variogram" << std::endl; outputtmp << "#" << std::endl; time_t now = time(NULL); outputtmp << "# Finished: " << asctime(localtime(&now)); utsname hostname; uname(&hostname); outputtmp << "# Hostname: " << hostname.nodename << std::endl; outputtmp << "#" << std::endl; outputtmp << "# Options used:" << std::endl; outputtmp << "# gridfilename: " << gridfilename << std::endl; outputtmp << "# i; min,len,max: " << imin << " " << ilen << " " << imax << std::endl; outputtmp << "# j; min,len,max: " << jmin << " " << jlen << " " << jmax << std::endl; outputtmp << "# z; min,len,max: " << zmin << " " << zlen << " " << zmax << std::endl; outputtmp << "# direction: " << direction << std::endl; outputtmp << "# pairs: " << pairs << std::endl; outputtmp << "################################################################################################" << std::endl; outputtmp << "# distance (" << distancemetric << ") porositydiff permxdiff permydiff permzdiff" << std::endl; const int fieldwidth = outputprecision + 8; for (int pair = 1; pair <= pairs; ++pair) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << distances[pair-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << porodiffs[pair-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permxdiffs[pair-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permydiffs[pair-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permzdiffs[pair-1] << '\t' << std::endl; } if (resultfile != "") { std::cout << "Writing results to " << resultfile << std::endl; std::ofstream outfile; outfile.open(resultfile.c_str(), std::ios::out | std::ios::trunc); outfile << outputtmp.str(); outfile.close(); } std::cout << outputtmp.str(); } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; }
bool Coord_cl::lineOfSight( const Coord_cl &target, UI16 targetheight, bool touch ) { //Console::instance()->send( QString( "LOScheck: Source:%1,Target:%2,Targetheight:%3\n" ).arg( z ).arg( target.z ).arg( targetheight ) ); if( target.map != map ) return false; if( (x == target.x) && (y == target.y) && (z == target.z) ) return true; // if source and target are on the same position SI32 n = ( target.x - x ), m = ( target.y - y ), i = 0; SI08 sgn_x = ( x <= target.x ) ? 1 : (-1); // signum for x SI08 sgn_y = ( y <= target.y ) ? 1 : (-1); // signum for y SI08 sgn_z = ( z <= target.z ) ? 1 : (-1); // signum for z if( x == target.x ) sgn_x = 0; if( y == target.y ) sgn_y = 0; if( z == target.z ) sgn_z = 0; QValueList< Coord_cl > collisions; //first we get our x-y-coordinates if( sgn_x == 0 && sgn_y == 0 && !sgn_z == 0 ) // should fix shooting through floor issues { collisions.push_back( Coord_cl( x, y, 0, map ) ); } else if( sgn_x == 0 ) // if we are on the same x-level, just push every x/y coordinate in y-direction from src to trg into the array for( i = 0; i <= (sgn_y * m); ++i ) { collisions.push_back( Coord_cl( x, y + (sgn_y * i), 0, map ) ); } else if ( sgn_y == 0 ) // if we are on the same y-level, just push every x/y coordinate in x-direction from src to trg into the array for( i = 0; i <= (sgn_x * n); ++i ) { collisions.push_back( Coord_cl( x + (sgn_x * i), y, 0, map ) ); } else { SI32 oldpos = y; bool exaktpos = false; for( i = 0; (sgn_x * n >= sgn_y * m) && (i <= (sgn_x * n)); i++ ) { //Console::instance()->send( QString( "x:%1\n" ).arg( i ) ); SI32 gridx = x + (sgn_x * i); if( ( ( n == 0 ) && ( gridx == 0 ) ) || ( ( n + ( gridx * m ) == 0 ) ) ) continue; else { if( exaktpos ) { collisions.push_back( Coord_cl( gridx, oldpos-sgn_y, 0, map ) ); //Console::instance()->send( QString( "add exaktpos coordinate %1,%2\n" ).arg( gridx ).arg( oldpos-sgn_y ) ); exaktpos = false; } // linear evaluation of extended 2x2 matrix, abbreviated double t = (double)sgn_x * ((double)i+0.5) * (double)m / (double)n + (double)y; //Console::instance()->send( QString( "t:%1\n" ).arg( t ) ); if( ((sgn_y>0) && (specialFloor(t)==oldpos+0.5)) || ((sgn_y<0) && (specialFloor(t)==oldpos-0.5)) ) { exaktpos = true; } if( ((sgn_y>0) && (t<oldpos+0.5)) || ((sgn_y<0) && (t>oldpos-0.5)) || (oldpos==target.y) ) { collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) ); } // but if not, we have to take BOTH coordinates, which the calculated collision is between! else { collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) ); oldpos += sgn_y; collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) ); } } } oldpos = x; exaktpos = false; for( i = 0; (sgn_y * m >= sgn_x * n) && (i <= (sgn_y * m)); ++i ) { //Console::instance()->send( QString( "y:%1\n" ).arg( i ) ); SI32 gridy = y + (sgn_y * i); if( ( ( m == 0 ) && ( gridy == 0 ) ) || ( ( m + ( gridy * n ) == 0 ) ) ) continue; else { if( exaktpos ) { collisions.push_back( Coord_cl( oldpos-sgn_x, gridy, 0, map ) ); //Console::instance()->send( QString( "add exaktpos coordinate %1,%2\n" ).arg( oldpos-sgn_x ).arg( gridy ) ); exaktpos = false; } double t = (double)x + (double)n / (double)m * (double)sgn_y * ((double)i+0.5); //Console::instance()->send( QString( "t:%1\n" ).arg( t ) ); if( ((sgn_x>0) && (specialFloor(t)==oldpos+0.5)) || ((sgn_x<0) && (specialFloor(t)==oldpos-0.5)) ) { exaktpos = true; } if( ((sgn_x>0) && (t<oldpos+0.5)) || ((sgn_x<0) && (t>oldpos-0.5)) || (oldpos==target.x) ) { collisions.push_back( Coord_cl( oldpos, gridy, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( oldpos ).arg( gridy ) ); } // but if not, we have to take BOTH coordinates, which the calculated collision is between! else { collisions.push_back( Coord_cl( oldpos, gridy, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( oldpos ).arg( gridy ) ); oldpos += sgn_x;; collisions.push_back( Coord_cl( oldpos, gridy, 0, map ) ); //Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( oldpos ).arg( gridy ) ); } } } } // the next will search for multis QPtrList< cItem > multis; RegionIterator4Items ri( *this ); for( ri.Begin(); !ri.atEnd(); ri++ ) { P_ITEM pi = ri.GetData(); if( pi && pi->id() >= 0x4000 ) { multis.append( pi ); } } //touch wird von notouch getrennt, da der notouch algorithmus wesentlich aufwändiger //ist (touch benötigt die erste for-schleife nicht), macht den code zwar bisserl //unübersichtlicher, aber ist wesentlich effizienter //touch is separated from notouch, because the notouch calculation is much more to do //( one additional for-loop ) if( targetheight > 0 ) { --targetheight; } if( !touch ) { for( i = target.z+targetheight; i >= target.z; --i ) { bool blocked = false; //Console::instance()->send( QString( "i:%1\n" ).arg( i ) ); double dz; double gradient; double offset; if( (sgn_x == 0) && (sgn_y == 0) ) { dz = (double)i - (double)z; gradient = 1; //only to avoid problems, isnt used offset = 1; } else { dz = ( (double)i -(double)z ) / sqrt( ((double)target.x - (double)x)*((double)target.x - (double)x) + ((double)target.y - (double)y)*((double)target.y - (double)y) ); gradient = (double)m / (double)n; offset = 0.5*( (double)y + (double)target.y - gradient*( x + target.x ) ); } map_st map1, map2; SI32 j; bool posHigherThanMap; map1 = Map->seekMap( (*this) ); if( map1.z > z ) { posHigherThanMap = false; } else { posHigherThanMap = true; } //Console::instance()->send( QString( "after first things\n" ) ); QValueList< Coord_cl >::iterator pit = collisions.begin(); while( pit != collisions.end() ) { //Console::instance()->send( QString( "coordinate:%1,%2 dz:%3\n" ).arg( (*pit).x ).arg( (*pit).y ).arg( dz ) ); //lets see what z-coordinates we have to test //we do our calculations exakt, because its the only way to solve all problems //of floor //"minimum" ist am anfang der platte, "maximum" am ende //our line is y = gradient * x + offset //or x = ( y - offset ) / gradient //we now have to test, where the line cuts one position //start and endposition has to be done alone double z1 = -300; double z2 = -300; SI08 zmin, zmax; if( (sgn_x == 0) && (sgn_y == 0) ) { if( dz > 0 ) { zmin = z+1; zmax = i; } else { zmin = i+1; zmax = z; } } else if( sgn_x == 0 ) { //gradient only in y-direction z1 = (double)i - dz*( fabs( (double)target.y - (double)((*pit).y) ) -0.5 ); z2 = (double)i - dz*( fabs( (double)target.y - (double)((*pit).y) ) +0.5 ); //Console::instance()->send( QString( "i:%1,ty:%2,cy:%3\n" ).arg( i ).arg( target.y ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); if( z1 > z2 ) { zmin = (SI08)floor( z2 ); zmax = (SI08)ceilf( z1 ); } else { zmin = (SI08)floor( z1 ); zmax = (SI08)ceilf( z2 ); } /*another try, but i think its needed for all positions, not only start and end... //target if( (*pit).y == target.y ) { if( dz > 0 ) { zmax = QMIN( zmax, i ); //Console::instance()->send( QString( "TargetY, zmax:%1, i:%2\n" ).arg( zmax ).arg( i ) ); } else { zmin = QMAX( zmin, i+1 ); //Console::instance()->send( QString( "TargetY, zmin:%1, i:%2\n" ).arg( zmin ).arg( i ) ); } } //source if( (*pit).y == y ) { if( dz > 0 ) { zmin = QMAX( zmin, z ); //Console::instance()->send( QString( "SourceY, zmin:%1, i:%2\n" ).arg( zmax ).arg( i ) ); } else { zmax = QMIN( zmax, z ); //Console::instance()->send( QString( "SourceY, zmax:%1, i:%2\n" ).arg( zmax ).arg( i ) ); } }*/ if( dz > 0 ) { zmax = QMIN( zmax, i ); zmin = QMAX( zmin, z ); } else { zmin = QMAX( zmin, i+1 ); zmax = QMIN( zmax, z ); } } else if( sgn_y == 0 ) { //gradient only in y-direction z1 = (double)i - dz*( fabs( (double)target.x - (double)((*pit).x) ) -0.5 ); z2 = (double)i - dz*( fabs( (double)target.x - (double)((*pit).x) ) +0.5 ); //Console::instance()->send( QString( "i:%1,tx:%2,cx:%3\n" ).arg( i ).arg( target.x ).arg( (*pit).x ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); if( z1 > z2 ) { zmin = (SI08)floor( z2 ); zmax = (SI08)ceilf( z1 ); } else { zmin = (SI08)floor( z1 ); zmax = (SI08)ceilf( z2 ); } if( dz > 0 ) { zmax = QMIN( zmax, i ); zmin = QMAX( zmin, z ); } else { zmin = QMAX( zmin, i+1 ); zmax = QMIN( zmax, z ); } } else { //4 lines to test double gradx = ( (double)target.y*(double)z - (double)y*(double)i ) / ( (double)target.y*(double)x - (double)y*(double)target.x ); double grady = ( (double)target.x*(double)z - (double)x*(double)i ) / ( (double)y*(double)target.x - (double)target.y*(double)x ); //Console::instance()->send( QString( "gradx:%1,grady:%2\n" ).arg( gradx ).arg( grady ) ); //Console::instance()->send( QString( "Gradient:%1,Offset:%2\n" ).arg( gradient ).arg( offset ) ); double temp; temp = specialFloor( gradient*( (double)((*pit).x) - 0.5 ) + offset ); //Console::instance()->send( QString( "temp1:%1\n" ).arg( temp ) ); if( ( temp >= ((double)((*pit).y)-0.5) ) && ( temp <= ((double)((*pit).y)+0.5) ) ) { if( z1 > -300 ) { z2 = gradx * ( (double)((*pit).x)-0.5 ) + grady * temp; } else { z1 = gradx * ( (double)((*pit).x)-0.5 ) + grady * temp; } //Console::instance()->send( QString( "1:i:%1,tx:%2,ty:%3,cy:%4,cy:%5\n" ).arg( i ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); } temp = specialFloor( gradient*( (double)((*pit).x) + 0.5 ) + offset ); //Console::instance()->send( QString( "temp2:%1\n" ).arg( temp ) ); if( ( temp >= ((double)((*pit).y)-0.5) ) && ( temp <= ((double)((*pit).y)+0.5) ) ) { if( z1 > -300 ) { z2 = gradx * ( (double)((*pit).x)+0.5 ) + grady * temp; } else { z1 = gradx * ( (double)((*pit).x)+0.5 ) + grady * temp; } //Console::instance()->send( QString( "2:i:%1,tx:%2,ty:%3,cy:%4,cy:%5\n" ).arg( i ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); } temp = specialFloor( (double)((*pit).y) - 0.5 - offset ) / gradient; //Console::instance()->send( QString( "temp3:%1\n" ).arg( temp ) ); if( ( temp > ((double)((*pit).x)-0.5) ) && ( temp < ((double)((*pit).x)+0.5) ) ) { if( z1 > -300 ) { z2 = gradx * temp + grady * ((double)((*pit).y)-0.5); } else { z1 = gradx * temp + grady * ((double)((*pit).y)-0.5); } //Console::instance()->send( QString( "3:i:%1,tx:%2,ty:%3,cy:%4,cy:%5\n" ).arg( i ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); } temp = specialFloor( (double)((*pit).y) + 0.5 - offset ) / gradient; //Console::instance()->send( QString( "temp4:%1\n" ).arg( temp ) ); if( ( temp > ((double)((*pit).x)-0.5) ) && ( temp < ((double)((*pit).x)+0.5) ) ) { if( z1 > -300 ) { z2 = gradx * temp + grady * ((double)((*pit).y)+0.5); } else { z1 = gradx * temp + grady * ((double)((*pit).y)+0.5); } //Console::instance()->send( QString( "4:i:%1,tx:%2,ty:%3,cy:%4,cy:%5\n" ).arg( i ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); } //Console::instance()->send( QString( "z1:%1,z2:%2\n" ).arg( z1 ).arg( z2 ) ); if( z1 > z2 ) { zmin = (SI08)floor( z2 ); zmax = (SI08)ceilf( z1 ); } else { zmin = (SI08)floor( z1 ); zmax = (SI08)ceilf( z2 ); } if( z2 == -300 ) { zmin = (SI08)floor( z1 ); } if( dz > 0 ) { zmax = QMIN( zmax, i ); zmin = QMAX( zmin, z ); } else { zmin = QMAX( zmin, i+1 ); zmax = QMIN( zmax, z ); } //Console::instance()->send( QString( "zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); } /*SI08 zmin = (SI08)floor( i - dz*sqrt( ((double)target.x - (double)(*pit).x)*((double)target.x - (double)(*pit).x) + ((double)target.y - (double)(*pit).y)*((double)target.y - (double)(*pit).y) ) ); SI08 zmax; //Console::instance()->send( QString( "zmin:%1,dz:%2\n" ).arg( zmin ).arg( dz ) ); if( dz > 0 ) { zmin = QMAX( (SI08)floor( zmin - dz/2 ), z+1 ); zmax = QMIN( zmin + dz + 1, target.z+targetheight+1 ); //to prevent floor-mistakes } else { zmin = QMIN( (SI08)floor( zmin + dz/2 ), target.z+1 ); zmax = QMAX( zmin - dz + 1, z ); //to prevent floor-mistakes }*/ // Texture mapping map1 = Map->seekMap( *pit ); map2 = Map->seekMap( Coord_cl( (*pit).x + sgn_x, (*pit).y + sgn_y, (*pit).z, map ) ); //Console::instance()->send( QString( "maphoehe:%1\n" ).arg( map1.z ) ); StaticsIterator msi = Map->staticsIterator( *pit ); if( (map1.id != 2) && (map2.id != 2) ) { if( ( map1.z >= zmin ) && ( map1.z <= zmax ) ) { //its just in our way //Console::instance()->send( QString( "Map gescheitert\n" ) ); blocked = true; break; } //now we have to test, if this tile is under our line and the next above or //vice verse //in this case, both dont cut our line, but the mapconnection between them //should do if( ( ( map1.z < map2.z ) && ( map1.z < zmin ) && ( map2.z > zmax+dz ) ) || // 1) lineofsight collides with a map "wall" ( ( map1.z > map2.z ) && ( map1.z > zmin ) && ( map2.z < zmax-dz ) ) || ( ( ( map1.id >= 431 && map1.id <= 432 ) || // 3) lineofsight cuts a mountain ( map1.id >= 467 && map1.id <= 475 ) || ( map1.id >= 543 && map1.id <= 560 ) || ( map1.id >= 1754 && map1.id <= 1757 ) || ( map1.id >= 1787 && map1.id <= 1789 ) || ( map1.id >= 1821 && map1.id <= 1824 ) || ( map1.id >= 1851 && map1.id <= 1854 ) || ( map1.id >= 1881 && map1.id <= 1884 ) ) && ( posHigherThanMap ) && ( msi.atEnd() ) ) ) // mountains cut only if we are not beneath them { //Console::instance()->send( QString( "map1:%1,map2:%2\n" ).arg( map1.z ).arg( map2.z ) ); blocked = true; break; } } //Console::instance()->send( QString( "after map\n" ) ); // Statics tile_st tile; while( !msi.atEnd() ) { tile = TileCache::instance()->getTile( msi->itemid ); //if it is in our way //Console::instance()->send( QString( "tilepos:%1,zmax:%2" ).arg( msi->zoff ).arg( zmax ) ); //Console::instance()->send( QString( "zmin:%3\n" ).arg( zmin ) ); if( ( zmax >= msi->zoff ) && ( zmin <= ( msi->zoff + tile.height ) ) ) { //Console::instance()->send( QString( "statictile, id: %1\n" ).arg( msi->itemid ) ); if( tile.isNoShoot() ) { blocked = true; break; } } ++msi; } if( blocked ) { break; } //Console::instance()->send( QString( "after statics\n" ) ); // Items RegionIterator4Items rj( (*pit), 0 ); for( rj.Begin(); !rj.atEnd(); rj++ ) { P_ITEM pi = rj.GetData(); if( pi && pi->id() < 0x4000 ) { tile = TileCache::instance()->getTile( pi->id() ); if( ( zmax >= pi->pos().z ) && ( zmin <= ( pi->pos().z + tile.height ) ) && ( pi->visible() == 0 ) ) { //Console::instance()->send( QString( "item, id: %1" ).arg( pi->id() ) ); if( tile.isNoShoot() ) { blocked = true; break; } } } } if( blocked ) { break; } //Console::instance()->send( QString( "after items\n" ) ); // Multis QPtrListIterator< cItem > mit( multis ); P_ITEM pi; while( ( pi = mit.current() ) ) { MultiDefinition* def = MultiCache::instance()->getMulti( pi->id() - 0x4000 ); if ( !def ) continue; QValueVector<multiItem_st> multi = def->getEntries(); for( j = 0; j < multi.size(); ++j ) { if( ( multi[j].visible ) && ( pi->pos().x + multi[j].x == (*pit).x ) && ( pi->pos().y + multi[j].y == (*pit).y ) ) { tile = TileCache::instance()->getTile( multi[j].tile ); if( ( zmax >= pi->pos().z + multi[j].z ) && ( zmin <= pi->pos().z + multi[j].z + tile.height ) ) { if( tile.isNoShoot() ) { blocked = true; break; } } } } ++mit; } //Console::instance()->send( QString( "after multis\n" ) ); ++pit; } if( !blocked ) return true; } //there was no line to see through return false; } //now touch=true else { //Console::instance()->send( "touch\n" ); double dz_up, dz_down; double gradient; double offset; if( (sgn_x == 0) && (sgn_y == 0) ) { dz_up = ( (double)targetheight + (double)target.z ) - (double)z; dz_down = (double)target.z - ( (double)z - (double)15 ); gradient = 1; //only to prevent problems, isnt used offset = 1; } else { //Console::instance()->send( QString( "xdiff:%1,ydiff:%2\n" ).arg( (double)target.x - (double)x ).arg( (double)target.y - (double)y ) ); dz_up = ( ( (double)targetheight + (double)target.z ) - (double)z ) / sqrt( ((double)target.x - (double)x)*((double)target.x - (double)x) + ((double)target.y - (double)y)*((double)target.y - (double)y) ); dz_down = ( (double)target.z - ( (double)z - (double)15 ) ) / sqrt( ((double)target.x - (double)x)*((double)target.x - (double)x) + ((double)target.y - (double)y)*((double)target.y - (double)y) ); gradient = (double)m / (double)n; offset = 0.5*( (double)y + (double)target.y - gradient*( x + target.x ) ); } map_st map1, map2; SI32 j; bool posHigherThanMap; map1 = Map->seekMap( (*this) ); if( map1.z > z ) { posHigherThanMap = false; } else { posHigherThanMap = true; } //Console::instance()->send( QString( "after first things\n" ) ); QValueList< Coord_cl >::iterator pit = collisions.begin(); while( pit != collisions.end() ) { //Console::instance()->send( QString( "coordinate:%1,%2\n" ).arg( (*pit).x ).arg( (*pit).y ) ); //lets see what z-coordinates we have to test //anmerkung: touch kommt nur für chars vor, grösse von chars ist 15 //SI08 zmin = (SI08)floor( (double)z - (double)sourceheight + dz_down*sqrt( ((double)target.x - (double)(*pit).x)*((double)target.x - (double)(*pit).x) + ((double)target.y - (double)(*pit).y)*((double)target.y - (double)(*pit).y) ) ); //SI08 zmax = (SI08)floor( (double)z + dz_up*sqrt( ((double)target.x - (double)(*pit).x)*((double)target.x - (double)(*pit).x) + ((double)target.y - (double)(*pit).y)*((double)target.y - (double)(*pit).y) ) ); SI08 zmin, zmax; double z1_up = -300; double z2_up = -300; double z1_down = -300; double z2_down = -300; bool targetpos = false; //Console::instance()->send( QString( "dz_down:%3,dz_up:%4\n" ).arg( dz_down ).arg( dz_up ) ); if( (sgn_x == 0) && (sgn_y == 0) ) { if( dz_up > 0 ) { zmin = z+1; zmax = target.z; } else { zmin = target.z+1; zmax = z; } targetpos = true; if( (dz_up >= 0) && (dz_down >= 0) ) { if( zmin < target.z ) { zmax = target.z -1; } else { //we ignore this coordinate ++pit; continue; } } else if( (dz_up <= 0) && (dz_down <= 0) ) { if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else { ++pit; continue; } } else { //we may have to split the test into two if we would do it exactly //but i think we can throw away the test from down in this case if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else if( zmin < target.z ) { zmax = target.z -1; } else { ++pit; continue; } } } else if( sgn_x == 0 ) { z1_up = target.z + targetheight - dz_up*( fabs( (double)target.y - (double)((*pit).y) ) -0.5 ); z2_up = target.z + targetheight - dz_up*( fabs( (double)target.y - (double)((*pit).y) ) +0.5 ); z1_down = target.z - dz_down*( fabs( (double)target.y - (double)((*pit).y) ) -0.5 ); z2_down = target.z - dz_down*( fabs( (double)target.y - (double)((*pit).y) ) +0.5 ); //Console::instance()->send( QString( "ty:%2,cy:%3\n" ).arg( target.y ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1_up:%1,z2_up:%2,z1_down:%3,z2_down:%4\n" ).arg( z1_up ).arg( z2_up ).arg( z1_down ).arg( z2_down ) ); zmax = QMAX( ceil( z1_up ), ceil( z2_up ) ); zmin = QMIN( floor( z1_down ), floor( z2_down ) ); //Console::instance()->send( QString( "y:zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); if( dz_up > 0 ) { zmax = QMIN( zmax, target.z+targetheight ); } else { zmax = QMIN( zmax, z ); } //Console::instance()->send( QString( "y2:zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); if( dz_down > 0 ) { zmin = QMAX( zmin, z-14 ); } else { zmin = QMAX( zmin, target.z+1 ); } //Console::instance()->send( QString( "y3:zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); if( (*pit).y == target.y ) { targetpos = true; if( (dz_up >= 0) && (dz_down >= 0) ) { if( zmin < target.z ) { zmax = target.z -1; } else { //we ignore this coordinate ++pit; continue; } } else if( (dz_up <= 0) && (dz_down <= 0) ) { if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else { ++pit; continue; } } else { //we may have to split the test into two if we would do it exactly //but i think we can throw away the test from down in this case if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else if( zmin < target.z ) { zmax = target.z -1; } else { ++pit; continue; } } //Console::instance()->send( QString( "y4:zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); } } else if( sgn_y == 0 ) { z1_up = target.z + targetheight - dz_up*( fabs( (double)target.x - (double)((*pit).x) ) -0.5 ); z2_up = target.z + targetheight - dz_up*( fabs( (double)target.x - (double)((*pit).x) ) +0.5 ); z1_down = target.z - dz_down*( fabs( (double)target.x - (double)((*pit).x) ) -0.5 ); z2_down = target.z - dz_down*( fabs( (double)target.x - (double)((*pit).x) ) +0.5 ); //Console::instance()->send( QString( "tx:%2,cx:%3\n" ).arg( target.x ).arg( (*pit).x ) ); //Console::instance()->send( QString( "z1_up:%1,z2_up:%2,z1_down:%3,z2_down:%4\n" ).arg( z1_up ).arg( z2_up ).arg( z1_down ).arg( z2_down ) ); zmax = QMAX( ceil( z1_up ), ceil( z2_up ) ); zmin = QMIN( floor( z1_down ), floor( z2_down ) ); if( dz_up > 0 ) { zmax = QMIN( zmax, target.z+targetheight ); } else { zmax = QMIN( zmax, z ); } if( dz_down > 0 ) { zmin = QMAX( zmin, z-14 ); } else { zmin = QMAX( zmin, target.z+1 ); } if( (*pit).x == target.x ) { targetpos = true; if( (dz_up >= 0) && (dz_down >= 0) ) { if( zmin < target.z ) { zmax = target.z -1; } else { //we ignore this coordinate ++pit; continue; } } else if( (dz_up <= 0) && (dz_down <= 0) ) { if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else { ++pit; continue; } } else { //we may have to split the test into two if we would do it exactly //but i think we can throw away the test from down in this case if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else if( zmin < target.z ) { zmax = target.z -1; } else { ++pit; continue; } } } } else { double gradx_up = ( (double)target.y*(double)z - (double)y*(double)(target.z + targetheight) ) / ( (double)target.y*(double)x - (double)y*(double)target.x ); double grady_up = ( (double)target.x*(double)z - (double)x*(double)(target.z + targetheight) ) / ( (double)y*(double)target.x - (double)target.y*(double)x ); double gradx_down = ( (double)target.y*(double)(z-15) - (double)y*(double)(target.z) ) / ( (double)target.y*(double)x - (double)y*(double)target.x ); double grady_down = ( (double)target.x*(double)(z-15) - (double)x*(double)(target.z) ) / ( (double)y*(double)target.x - (double)target.y*(double)x ); //Console::instance()->send( QString( "gradx_up:%1,grady_up:%2,gradx_down:%3,grady_down:%4\n" ).arg( gradx_up ).arg( grady_up ).arg( gradx_down ).arg( grady_down ) ); //Console::instance()->send( QString( "Gradient:%1,Offset:%2\n" ).arg( gradient ).arg( offset ) ); double temp = specialFloor( gradient*( (double)((*pit).x) - 0.5 ) + offset ); //Console::instance()->send( QString( "temp1:%1\n" ).arg( temp ) ); if( ( temp >= ((double)((*pit).y)-0.5) ) && ( temp <= ((double)((*pit).y)+0.5) ) ) { if( z1_up > -300 ) { z2_up = gradx_up * ( (double)((*pit).x)-0.5 ) + grady_up * temp; z2_down = gradx_down * ( (double)((*pit).x)-0.5 ) + grady_down * temp; } else { z1_up = gradx_up * ( (double)((*pit).x)-0.5 ) + grady_up * temp; z1_down = gradx_down * ( (double)((*pit).x)-0.5 ) + grady_down * temp; } //Console::instance()->send( QString( "tx:%1,ty:%2,cy:%3,cy:%4\n" ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1_up:%1,z1_down:%2,z2_up:%3,z2_down:%4\n" ).arg( z1_up ).arg( z1_down ).arg( z2_up ).arg( z2_down ) ); } temp = specialFloor( gradient*( (double)((*pit).x) + 0.5 ) + offset ); //Console::instance()->send( QString( "temp2:%1\n" ).arg( temp ) ); if( ( temp >= ((double)((*pit).y)-0.5) ) && ( temp <= ((double)((*pit).y)+0.5) ) ) { if( z1_up > -300 ) { z2_up = gradx_up * ( (double)((*pit).x)+0.5 ) + grady_up * temp; z2_down = gradx_down * ( (double)((*pit).x)+0.5 ) + grady_down * temp; } else { z1_up = gradx_up * ( (double)((*pit).x)+0.5 ) + grady_up * temp; z1_down = gradx_down * ( (double)((*pit).x)+0.5 ) + grady_down * temp; } //Console::instance()->send( QString( "tx:%1,ty:%2,cy:%3,cy:%4\n" ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1_up:%1,z1_down:%2,z2_up:%3,z2_down:%4\n" ).arg( z1_up ).arg( z1_down ).arg( z2_up ).arg( z2_down ) ); } temp = specialFloor( (double)((*pit).y) - 0.5 - offset ) / gradient; //Console::instance()->send( QString( "temp3:%1\n" ).arg( temp ) ); if( ( temp > ((double)((*pit).x)-0.5) ) && ( temp < ((double)((*pit).x)+0.5) ) ) { if( z1_up > -300 ) { z2_up = gradx_up * temp + grady_up * ((double)((*pit).y)-0.5); z2_down = gradx_down * temp + grady_down * ((double)((*pit).y)-0.5); } else { z1_up = gradx_up * temp + grady_up * ((double)((*pit).y)-0.5); z1_down = gradx_down * temp + grady_down * ((double)((*pit).y)-0.5); } //Console::instance()->send( QString( "tx:%1,ty:%2,cy:%3,cy:%4\n" ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1_up:%1,z1_down:%2,z2_up:%3,z2_down:%4\n" ).arg( z1_up ).arg( z1_down ).arg( z2_up ).arg( z2_down ) ); } temp = specialFloor( (double)((*pit).y) + 0.5 - offset ) / gradient; //Console::instance()->send( QString( "temp4:%1\n" ).arg( temp ) ); if( ( temp > ((double)((*pit).x)-0.5) ) && ( temp < ((double)((*pit).x)+0.5) ) ) { if( z1_up > -300 ) { z2_up = gradx_up * temp + grady_up * ((double)((*pit).y)+0.5); z2_down = gradx_down * temp + grady_down * ((double)((*pit).y)+0.5); } else { z1_up = gradx_up * temp + grady_up * ((double)((*pit).y)+0.5); z1_down = gradx_down * temp + grady_down * ((double)((*pit).y)+0.5); } //Console::instance()->send( QString( "tx:%1,ty:%2,cy:%3,cy:%4\n" ).arg( target.x ).arg( target.y ).arg( (*pit).x ).arg( (*pit).y ) ); //Console::instance()->send( QString( "z1_up:%1,z1_down:%2,z2_up:%3,z2_down:%4\n" ).arg( z1_up ).arg( z1_down ).arg( z2_up ).arg( z2_down ) ); } //Console::instance()->send( QString( "ergebnis: z1_up:%1,z1_down:%2,z2_up:%3,z2_down:%4\n" ).arg( z1_up ).arg( z1_down ).arg( z2_up ).arg( z2_down ) ); if( z2_up == -300 ) { zmin = floor( z1_down ); zmax = ceil( z1_up ); } else { zmin = QMIN( floor( z1_down ), floor( z2_down ) ); zmax = QMAX( ceil( z1_up ), ceil( z2_up ) ); } //Console::instance()->send( QString( "zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); if( dz_up > 0 ) { zmax = QMIN( zmax, target.z+targetheight ); } else { zmax = QMIN( zmax, z ); } if( dz_down > 0 ) { zmin = QMAX( zmin, z-14 ); } else { zmin = QMAX( zmin, target.z+1 ); } //Console::instance()->send( QString( "zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); if( ((*pit).x == target.x) && ((*pit).y == target.y) ) { targetpos = true; if( (dz_up >= 0) && (dz_down >= 0) ) { if( zmin < target.z ) { zmax = target.z -1; } else { //we ignore this coordinate ++pit; continue; } } else if( (dz_up <= 0) && (dz_down <= 0) ) { if( zmax > target.z + targetheight+1) { zmin = target.z + targetheight + 2; } else { ++pit; continue; } } else { //we may have to split the test into two if we would do it exactly //but i think we can throw away the test from down in this case if( zmax > target.z + targetheight+1 ) { zmin = target.z + targetheight + 2; } else if( zmin < target.z ) { zmax = target.z -1; } else { ++pit; continue; } } } } //Console::instance()->send( QString( "zmin:%1,zmax:%2\n" ).arg( zmin ).arg( zmax ) ); // Texture mapping map1 = Map->seekMap( *pit ); map2 = Map->seekMap( Coord_cl( (*pit).x + sgn_x, (*pit).y + sgn_y, (*pit).z, map ) ); //Console::instance()->send( QString( "try2" ) ); StaticsIterator msi = Map->staticsIterator( *pit ); RegionIterator4Items rj( (*pit), 0 ); if( (map1.id != 2) && (map2.id != 2) ) { if( ( map1.z > zmin ) && ( map1.z < zmax ) ) { //its just in our way //Console::instance()->send( QString( "map cut 1\n" ) ); return false; } //now we have to test, if this tile is under our line and the next above or //vice verse //in this case, both dont cut our line, but the mapconnection between them //should do land_st tile = TileCache::instance()->getLand( map1.id ); if( ( ( map1.z < map2.z ) && ( map1.z < zmin ) && ( map2.z > zmax+dz_down ) && !targetpos ) || // 1) lineofsight collides with a map "wall" ( ( map1.z > map2.z ) && ( map1.z > zmin ) && ( map2.z < zmin+dz_down ) && !targetpos ) || ( tile.isBlocking() && posHigherThanMap && msi.atEnd() && rj.atEnd() ) ) { //Console::instance()->send( QString( "map1:%1,map2:%2,map1id:%3\n" ).arg( map1.z ).arg( map2.z ).arg( map1.id ) ); if( ( map1.z < map2.z ) && ( map1.z < zmin ) && ( map2.z > zmax+dz_down ) ) { //Console::instance()->send( QString( "mapcut1\n" ) ); } else if( ( map1.z > map2.z ) && ( map1.z > zmin ) && ( map2.z < zmin+dz_down ) ) { //Console::instance()->send( QString( "mapcut2\n" ) ); } else if( tile.isBlocking() && posHigherThanMap && msi.atEnd() && rj.atEnd() ) { //Console::instance()->send( QString( "mapcut3\n" ) ); } else { //Console::instance()->send( QString( "mapcut: this isnt possible\n" ) ); } return false; } } //Console::instance()->send( QString( "after map\n" ) ); // Statics tile_st tile; while( !msi.atEnd() ) { tile = TileCache::instance()->getTile( msi->itemid ); //Console::instance()->send( QString( "statictilepos:%1,zmax:%2,zmin:%3\n" ).arg( msi->zoff ).arg( zmax ).arg( zmin ) ); //if it is in our way if( ( zmax >= msi->zoff ) && ( zmin <= ( msi->zoff + tile.height ) ) ) { if( tile.isBlocking() || tile.isRoofOrFloorTile() ) { return false; } } ++msi; } //Console::instance()->send( QString( "after statics\n" ) ); // Items //Console::instance()->send( QString( "Items at: %1,%2,%3,%4\n" ).arg( (*pit).x ).arg( (*pit).y ).arg( (*pit).z ).arg( (*pit).map ) ); for( rj.Begin(); !rj.atEnd(); rj++ ) { //Console::instance()->send( QString( "foritem\n" ) ); P_ITEM pi = rj.GetData(); if( pi && pi->id() < 0x4000 ) { tile = TileCache::instance()->getTile( pi->id() ); //Console::instance()->send( QString( "itemtilepos:%1,zmax:%2,zmin:%3\n" ).arg( pi->pos().z ).arg( zmax ).arg( zmin ) ); if( ( zmax >= pi->pos().z ) && ( zmin <= ( pi->pos().z + tile.height ) ) && ( pi->visible() == 0 ) ) { if( tile.isBlocking() || tile.isRoofOrFloorTile() ) { //Console::instance()->send( QString( "Item:%1,Z:%2,Height:%3\n" ).arg( pi->id() ).arg( pi->pos().z ).arg( tile.height ) ); return false; } } } } //Console::instance()->send( QString( "after items\n" ) ); // Multis QPtrListIterator< cItem > mit( multis ); P_ITEM pi; while( ( pi = mit.current() ) ) { MultiDefinition* def = MultiCache::instance()->getMulti( pi->id() - 0x4000 ); if ( !def ) { ++mit; continue; } QValueVector<multiItem_st> multi = def->getEntries(); for( j = 0; j < multi.size(); ++j ) { if( ( multi[j].visible ) && ( pi->pos().x + multi[j].x == (*pit).x ) && ( pi->pos().y + multi[j].y == (*pit).y ) ) { tile = TileCache::instance()->getTile( multi[j].tile ); if( ( zmax >= pi->pos().z + multi[j].z ) && ( zmin <= pi->pos().z + multi[j].z + tile.height ) ) { if( tile.isBlocking() || tile.isRoofOrFloorTile() ) { return false; } } } } ++mit; } //Console::instance()->send( QString( "after multis\n" ) ); ++pit; } return true; } }
/* CXXCircle::CXXCircle (const CXXCircle &oldOne) : theAtomJ(oldOne.getAtomJ()), theBallJ(oldOne.getBallJ()), theParent(oldOne.getParent()), centreOfSecondSphere(oldOne.getCentreOfSecondSphere()), theNormal(oldOne.getNormal()), radiusOfSecondSphere(oldOne.getRadiusOfSecondSphere()), radiusOfSphere(oldOne.getRadiusOfSphere()), centreOfCircle(oldOne.centreOfCircle), centreToCircle(oldOne.getCentreToCircle()), referenceUnitRadius(oldOne.getReferenceUnitRadius()), radiusOfCircle(oldOne.getRadiusOfCircle()), theNodes(oldOne.getNodes()), nIntersectingCircles(oldOne.getNIntersectingCircles()), completelyEaten(oldOne.getEaten()) { for (unsigned i=0; i<oldOne.getNNodes(); i++){ theNodes[i].setParent(this); } theStarts.resize(oldOne.nSegments()); theStops.resize(oldOne.nSegments()); for (unsigned i=0; i<oldOne.nSegments(); i++){ theStarts[i] = oldOne.start(i); theStops[i] = oldOne.stop(i); } } */ int CXXCircle::meetsCircle(const CXXCircle &otherCircle, vector<CXXCoord, CXX::CXXAlloc<CXXCoord> > &nodeList) const{ // check if there is an intersection between this circle and another circle // return 0 if there is intersection // 2 if the this circle is entirely swallowedd by the atom that generates the otherCircle, // 1 if the converse of the above applies // and 3 otherwise CXXCoord intersectA, intersectB; // some simplifications: rj - centreToCircle of current (this) arc circle // rk - centreToCircle of newArc circle CXXCoord rj(getCentreToCircle()); CXXCoord rk(otherCircle.getCentreToCircle()); CXXCoord rjxrk; // following Totrovs vector match - plane intersection of the two circles. // PlaneIntersectioon points at intersection of two this- and new- circlePlanes // with plane spanned by the centre of the two VDW spheres and the centre of thisArc // some dummy variables double rjrk, rjSquared, rkSquared; double a, b, distSq, radiusOfSphereSq, x; rjSquared = rj*rj; rkSquared = rk*rk; rjrk = rj*rk; a = ((rjSquared - rjrk)*rkSquared)/(rjSquared*rkSquared - rjrk*rjrk); b = ((rkSquared - rjrk)*rjSquared)/(rjSquared*rkSquared - rjrk*rjrk); // with this now: CXXCoord planeIntersect((rj*a) + (rk*b)); // if the distance between the intersection point of the three planes is closer then //the radius of the VDW + probe sphere, then the two circle of this arc and new arc intersect.... // distance of intersectino point distSq = planeIntersect*planeIntersect; radiusOfSphereSq = radiusOfSphere*radiusOfSphere; // distance of (VDW + probe) sphere of thisAtom = radiusOfSphere therefore: if (distSq < radiusOfSphereSq) { // the CIRCLES corresponding to the new and the current (old) arc cross each other // the crossingpoints of the two CIRCLES are the points where the line defined by the // intersection of the two arcplanes cuts throught the new circle // the intersection line is perpendicular the plane spanned by rj and rk - that is parallel to: rjxrk = rj ^ rk; rjxrk.normalise(); //the intersection line is defined by this vector and one of its point - the planeIntersection vector: // => line planeIntersect + x*(rjxrk), x some real number // intersection points have x=+-0.5*length of the secante of circle therefore: x = sqrt(radiusOfSphereSq - distSq); rjxrk.scale(x); //We need to see whether the centreToCircle vectors of these circles indicate that the //corresponding torus is "behind" the centre of the first circle, or in front. This determines //Whether the first or the second calculated intersection point represents a point to start drawing. //It boils down to a sort of parity thing. Think about it ! CXXCoord unitCentreToCircle(centreToCircle); unitCentreToCircle.normalise(); int forwardOne = (theNormal*unitCentreToCircle > 0.?1:-1); CXXCoord otherCircleUnitCentreToCircle(otherCircle.getCentreToCircle()); otherCircleUnitCentreToCircle.normalise(); int forwardTwo = (otherCircle.getNormal()*otherCircleUnitCentreToCircle > 0.?1:-1); if (forwardOne*forwardTwo > 0){ intersectA = planeIntersect+rjxrk; intersectB = planeIntersect-rjxrk; } else { intersectB = planeIntersect+rjxrk; intersectA = planeIntersect-rjxrk; } nodeList[0] = intersectA + getCentreOfSphere(); nodeList[1] = intersectB + getCentreOfSphere(); return 0; } else { //We get here if the two circles don't intersect //Now check whether this circle falls somewhere inside the //sphere indicated by the other circle. If it does, then //(given it doesn't intersect), it must *always* be inside // otherwise it must *always* be outside if (otherCircle.accIsBehind(getCentreOfCircle()) == 0) return 2; if(accIsBehind(otherCircle.getCentreOfCircle()) == 0) return 1; return 3; } }
int main(int argc, char** argv) { if (argc == 1) { std::cout << "Usage: cpchop_depthtrend gridfilename=filename.grdecl [zresolution=1] [zlen=1] [ilen=5] [jlen=5] " << std::endl; std::cout << " [zlen=5] [imin=] [imax=] [jmin=] [jmax=] [upscale=true] [resettoorigin=true]" << std::endl; std::cout << " [seed=111] [z_tolerance=0.0] [minperm=1e-9] " << std::endl; exit(1); } Opm::parameter::ParameterGroup param(argc, argv); std::string gridfilename = param.get<std::string>("gridfilename"); Opm::CornerPointChopper ch(gridfilename); // The cells with i coordinate in [imin, imax) are included, similar for j. // The z limits may be changed inside the chopper to match actual min/max z. const int* dims = ch.dimensions(); int imin = param.getDefault("imin", 0); int imax = param.getDefault("imax", dims[0]); int jmin = param.getDefault("jmin", 0); int jmax = param.getDefault("jmax", dims[1]); double zmin = param.getDefault("zmin", ch.zLimits().first); double zmax = param.getDefault("zmax", ch.zLimits().second); int ilen = param.getDefault("ilen", imax - imin); int jlen = param.getDefault("jlen", jmax - jmin); double zresolution = param.getDefault("zresolution", 1.0); double zlen = param.getDefault("zlen", zresolution); bool upscale = param.getDefault("upscale", true); bool resettoorigin = param.getDefault("resettoorigin", true); boost::mt19937::result_type userseed = param.getDefault("seed", 0); int outputprecision = param.getDefault("outputprecision", 8); std::string filebase = param.getDefault<std::string>("filebase", ""); std::string resultfile = param.getDefault<std::string>("resultfile", ""); double minperm = param.getDefault("minperm", 1e-9); double minpermSI = Opm::unit::convert::from(minperm, Opm::prefix::milli*Opm::unit::darcy); double z_tolerance = param.getDefault("z_tolerance", 0.0); double residual_tolerance = param.getDefault("residual_tolerance", 1e-8); double linsolver_verbosity = param.getDefault("linsolver_verbosity", 0); double linsolver_type = param.getDefault("linsolver_type", 1); // Check for unused parameters (potential typos). if (param.anyUnused()) { std::cout << "***** WARNING: Unused parameters: *****\n"; param.displayUsage(); } // Check that we do not have any user input // that goes outside the coordinates described in // the cornerpoint file (runtime-exception will be thrown in case of error) ch.verifyInscribedShoebox(imin, ilen, imax, jmin, jlen, jmax, zmin, zlen, zmax); // Random number generator from boost. boost::mt19937 gen; // Seed the random number generators with the current time, unless specified on command line // Warning: Current code does not allow 0 for the seed!! if (userseed == 0) { gen.seed(time(NULL)); } else { gen.seed(userseed); } // Note that end is included in interval for uniform_int. boost::uniform_int<> disti(imin, imax - ilen); boost::uniform_int<> distj(jmin, jmax - jlen); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > ri(gen, disti); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rj(gen, distj); // Storage for results std::vector<double> zstarts; std::vector<double> porosities; std::vector<double> permxs; std::vector<double> permys; std::vector<double> permzs; /* z_start is the topmost point of the subsample to extract */ for (double zstart = 0.0; zstart <= zmax-zlen; zstart += zresolution) { /* Horizontally, we pick by random, even though default behaviour is to have ilen=imax-min so that there is no randomness */ int istart = ri(); int jstart = rj(); ch.chop(istart, istart + ilen, jstart, jstart + jlen, zstart, std::min(zstart + zlen,zmax), resettoorigin); std::string subsampledgrdecl = filebase; // Output grdecl-data to file if a filebase is supplied. if (filebase != "") { std::ostringstream oss; oss << 'Z' << std::setw(4) << std::setfill('0') << zstart; subsampledgrdecl += oss.str(); subsampledgrdecl += ".grdecl"; ch.writeGrdecl(subsampledgrdecl); } try { /* The upscaling may fail to converge on icky grids, lets just pass by those */ if (upscale) { Opm::EclipseGridParser subparser = ch.subparser(); subparser.convertToSI(); Opm::SinglePhaseUpscaler upscaler; upscaler.init(subparser, Opm::SinglePhaseUpscaler::Fixed, minpermSI, z_tolerance, residual_tolerance, linsolver_verbosity, linsolver_type, false); Opm::SinglePhaseUpscaler::permtensor_t upscaled_K = upscaler.upscaleSinglePhase(); upscaled_K *= (1.0/(Opm::prefix::milli*Opm::unit::darcy)); zstarts.push_back(zstart); porosities.push_back(upscaler.upscalePorosity()); permxs.push_back(upscaled_K(0,0)); permys.push_back(upscaled_K(1,1)); permzs.push_back(upscaled_K(2,2)); } } catch (...) { std::cerr << "Warning: Upscaling chopped subsample at z=" << zstart << "failed, proceeding to next subsample\n"; } } if (upscale) { // Make stream of output data, to be outputted to screen and optionally to file std::stringstream outputtmp; outputtmp << "################################################################################################" << std::endl; outputtmp << "# Results from depth trend analysis on subsamples" << std::endl; outputtmp << "#" << std::endl; time_t now = time(NULL); outputtmp << "# Finished: " << asctime(localtime(&now)); utsname hostname; uname(&hostname); outputtmp << "# Hostname: " << hostname.nodename << std::endl; outputtmp << "#" << std::endl; outputtmp << "# Options used:" << std::endl; outputtmp << "# gridfilename: " << gridfilename << std::endl; outputtmp << "# i; min,len,max: " << imin << " " << ilen << " " << imax << std::endl; outputtmp << "# j; min,len,max: " << jmin << " " << jlen << " " << jmax << std::endl; outputtmp << "# z; min,len,max: " << zmin << " " << zlen << " " << zmax << std::endl; outputtmp << "# zresolution: " << zresolution << std::endl; outputtmp << "################################################################################################" << std::endl; outputtmp << "# zstart porosity permx permy permz" << std::endl; const int fieldwidth = outputprecision + 8; for (size_t sample = 1; sample <= porosities.size(); ++sample) { outputtmp << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << zstarts[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << porosities[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permxs[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permys[sample-1] << '\t' << std::showpoint << std::setw(fieldwidth) << std::setprecision(outputprecision) << permzs[sample-1] << '\t' << std::endl; } if (resultfile != "") { std::cout << "Writing results to " << resultfile << std::endl; std::ofstream outfile; outfile.open(resultfile.c_str(), std::ios::out | std::ios::trunc); outfile << outputtmp.str(); outfile.close(); } std::cout << outputtmp.str(); } }