changed: move permeability upscaling to a function

- was duplicated in upscale_relperm / upscale_relperm_benchmark
This commit is contained in:
Arne Morten Kvarving
2015-09-14 11:34:31 +02:00
parent 3749f061ff
commit 2e3d2b91c6
4 changed files with 270 additions and 524 deletions
+3 -263
View File
@@ -189,7 +189,6 @@ try
// Variables used for timing/profiling:
clock_t start, finish;
double timeused = 0.0, timeused_tesselation = 0.0;
double timeused_upscale_wallclock = 0.0;
clock_t global_start = clock(); // Timing used for benchmarking
@@ -295,11 +294,9 @@ try
finish = clock(); timeused = (double(finish)-double(start))/CLOCKS_PER_SEC;
if (helper.isMaster) cout << " (" << timeused <<" secs)" << endl;
const double maxPermContrast = atof(options["maxPermContrast"].c_str());
const double minPerm = atof(options["minPerm"].c_str());
const double maxPerm = atof(options["maxPerm"].c_str());
const double minPoro = atof(options["minPoro"].c_str());
const double saturationThreshold = atof(options["saturationThreshold"].c_str());
start = clock();
helper.sanityCheckInput(deck, minPerm, maxPerm, minPoro);
@@ -454,9 +451,6 @@ try
helper.upscaleCapillaryPressure(options, dP);
MonotCubicInterpolator CapPressureVsWaterSaturation(helper.WaterSaturationVsCapPressure.get_fVector(),
helper.WaterSaturationVsCapPressure.get_xVector());
clock_t start_upscaling = clock();
/*****************************************************************************
@@ -469,7 +463,6 @@ try
*/
helper.upscaleSinglePhasePermeability();
typedef SinglePhaseUpscaler::permtensor_t Matrix;
/*****************************************************************
* Step 8:
@@ -487,262 +480,9 @@ try
* c: Calculate relperm tensors from all the phase perm tensors.
*/
// Put correct number of zeros in, just to be able to access RelPerm[index] later
helper.WaterSaturation.resize(helper.points, 0.0);
for (size_t i = 0; i < (helper.upscaleBothPhases?2:1); ++i)
helper.PhasePerm[i].resize(helper.points, std::vector<double>(helper.tensorElementCount));
// Make vector of capillary pressure points corresponding to uniformly distribued
// saturation points between Swor and Swir.
for (int pointidx = 1; pointidx <= helper.points; ++pointidx) {
// pointidx=1 corresponds to Swir, pointidx=points to Swor.
double saturation = helper.Swir + (helper.Swor-helper.Swir)/(helper.points-1)*(pointidx-1);
helper.pressurePoints.push_back(CapPressureVsWaterSaturation.evaluate(saturation));
}
// Preserve max and min pressures
helper.pressurePoints[0]=helper.Pcmax;
helper.pressurePoints[helper.pressurePoints.size()-1]=helper.Pcmin;
// Fill with zeros initially (in case of non-mpi)
helper.node_vs_pressurepoint.resize(helper.points);
#if HAVE_MPI
// Distribute work load over mpi nodes.
for (int idx=0; idx < points; ++idx) {
// Ensure master node gets equal or less work than the other nodes, since
// master node also computes single phase perm.
node_vs_pressurepoint[idx] = (mpi_nodecount-1) - idx % mpi_nodecount;
/*if (helper.isMaster) {
cout << "Pressure point " << idx << " assigned to node " << node_vs_pressurepoint[idx] << endl;
}*/
}
#endif
clock_t start_upscale_wallclock = clock();
double waterVolumeLF;
// Now loop through the vector of capillary pressure points that
// this node should compute.
for (int pointidx = 0; pointidx < helper.points; ++pointidx) {
// Should "I" (mpi-wise) compute this pressure point?
if (helper.node_vs_pressurepoint[pointidx] == mpi_rank) {
double Ptestvalue = helper.pressurePoints[pointidx];
double accPhasePerm = 0.0;
double accPhase2Perm = 0.0;
double maxPhasePerm = 0.0;
double maxPhase2Perm = 0.0;
vector<double> phasePermValues, phase2PermValues;
vector<vector<double> > phasePermValuesDiag, phase2PermValuesDiag;
phasePermValues.resize(helper.satnums.size());
phasePermValuesDiag.resize(helper.satnums.size());
if (helper.upscaleBothPhases) {
phase2PermValues.resize(helper.satnums.size());
phase2PermValuesDiag.resize(helper.satnums.size());
}
waterVolumeLF = 0.0;
for (unsigned int i = 0; i < ecl_idx.size(); ++i) {
unsigned int cell_idx = ecl_idx[i];
double cellPhasePerm = minPerm;
double cellPhase2Perm = minPerm;
vector<double> cellPhasePermDiag, cellPhase2PermDiag;
cellPhasePermDiag.push_back(minPerm);
cellPhasePermDiag.push_back(minPerm);
cellPhasePermDiag.push_back(minPerm);
if (helper.upscaleBothPhases) {
cellPhase2PermDiag.push_back(minPerm);
cellPhase2PermDiag.push_back(minPerm);
cellPhase2PermDiag.push_back(minPerm);
}
if (helper.satnums[cell_idx] > 0) { // handle "no rock" cells with satnum zero
// cout << endl << "Cell no. " << cell_idx << endl;
double PtestvalueCell;
if (includeGravity) {
PtestvalueCell = Ptestvalue - dP[cell_idx];
}
else {
PtestvalueCell = Ptestvalue;
}
if (! helper.anisotropic_input) {
double Jvalue = sqrt(helper.perms[0][cell_idx] * milliDarcyToSqMetre/helper.poros[cell_idx]) * PtestvalueCell;
//cout << "JvalueCell: " << Jvalue << endl;
double WaterSaturationCell
= helper.InvJfunctions[int(helper.satnums[cell_idx])-1].evaluate(Jvalue);
waterVolumeLF += WaterSaturationCell * helper.cellPoreVolumes[cell_idx];
// Compute cell relative permeability. We use a lower cutoff-value as we
// easily divide by zero here. When water saturation is
// zero, we get 'inf', which is circumvented by the cutoff value.
cellPhasePerm =
helper.Krfunctions[0][0][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[0][cell_idx];
if (helper.upscaleBothPhases) {
cellPhase2Perm =
helper.Krfunctions[0][1][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[0][cell_idx];
}
}
else {
double WaterSaturationCell = helper.SwPcfunctions[int(helper.satnums[cell_idx])-1].evaluate(PtestvalueCell);
//cout << PtestvalueCell << "\t" << helper.WaterSaturationCell << endl;
waterVolumeLF += WaterSaturationCell * helper.cellPoreVolumes[cell_idx];
cellPhasePermDiag[0] = helper.Krfunctions[0][0][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[0][cell_idx];
cellPhasePermDiag[1] = helper.Krfunctions[1][0][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[1][cell_idx];
cellPhasePermDiag[2] = helper.Krfunctions[2][0][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[2][cell_idx];
if (helper.upscaleBothPhases) {
cellPhase2PermDiag[0] = helper.Krfunctions[0][1][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[0][cell_idx];
cellPhase2PermDiag[1] = helper.Krfunctions[1][1][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[1][cell_idx];
cellPhase2PermDiag[2] = helper.Krfunctions[2][1][int(helper.satnums[cell_idx])-1].evaluate(WaterSaturationCell) *
helper.perms[2][cell_idx];
}
}
phasePermValues[cell_idx] = cellPhasePerm;
phasePermValuesDiag[cell_idx] = cellPhasePermDiag;
maxPhasePerm = max(maxPhasePerm, cellPhasePerm);
maxPhasePerm = max(maxPhasePerm, *max_element(cellPhasePermDiag.begin(),
cellPhasePermDiag.end()));
if (helper.upscaleBothPhases) {
phase2PermValues[cell_idx] = cellPhase2Perm;
phase2PermValuesDiag[cell_idx] = cellPhase2PermDiag;
maxPhase2Perm = max(maxPhase2Perm, cellPhase2Perm);
maxPhase2Perm = max(maxPhase2Perm, *max_element(cellPhase2PermDiag.begin(),
cellPhase2PermDiag.end()));
}
}
}
// Now we can determine the smallest permitted permeability we can calculate for
// We have both a fixed bottom limit, as well as a possible higher limit determined
// by a maximum allowable permeability.
double minPhasePerm = max(maxPhasePerm/maxPermContrast, minPerm);
double minPhase2Perm;
if (helper.upscaleBothPhases) minPhase2Perm = max(maxPhase2Perm/maxPermContrast, minPerm);
// Now remodel the phase permeabilities obeying minPhasePerm
Matrix cellperm(3,3,nullptr);
zero(cellperm);
for (unsigned int i = 0; i < ecl_idx.size(); ++i) {
unsigned int cell_idx = ecl_idx[i];
zero(cellperm);
if (! helper.anisotropic_input) {
double cellPhasePerm = max(minPhasePerm, phasePermValues[cell_idx]);
accPhasePerm += cellPhasePerm;
double kval = max(minPhasePerm, cellPhasePerm);
cellperm(0,0) = kval;
cellperm(1,1) = kval;
cellperm(2,2) = kval;
}
else { // anisotropic_input
// Truncate values lower than minPhasePerm upwards.
phasePermValuesDiag[cell_idx][0] = max(minPhasePerm, phasePermValuesDiag[cell_idx][0]);
phasePermValuesDiag[cell_idx][1] = max(minPhasePerm, phasePermValuesDiag[cell_idx][1]);
phasePermValuesDiag[cell_idx][2] = max(minPhasePerm, phasePermValuesDiag[cell_idx][2]);
accPhasePerm += phasePermValuesDiag[cell_idx][0]; // not correct anyway
cellperm(0,0) = phasePermValuesDiag[cell_idx][0];
cellperm(1,1) = phasePermValuesDiag[cell_idx][1];
cellperm(2,2) = phasePermValuesDiag[cell_idx][2];
}
helper.upscaler.setPermeability(i, cellperm);
}
// Output average phase perm, this is just a reality check so that we are not way off.
//cout << ", Arith. mean phase perm = " << accPhasePerm/float(tesselatedCells) << " mD, ";
// Call single-phase upscaling code
Matrix phasePermTensor = helper.upscaler.upscaleSinglePhase();
// Now upscale phase permeability for phase 2
Matrix phase2PermTensor;
if (helper.upscaleBothPhases) {
zero(cellperm);
for (unsigned int i = 0; i < ecl_idx.size(); ++i) {
unsigned int cell_idx = ecl_idx[i];
zero(cellperm);
if (! helper.anisotropic_input) {
double cellPhase2Perm = max(minPhase2Perm, phase2PermValues[cell_idx]);
accPhase2Perm += cellPhase2Perm;
double kval = max(minPhase2Perm, cellPhase2Perm);
cellperm(0,0) = kval;
cellperm(1,1) = kval;
cellperm(2,2) = kval;
}
else { // anisotropic_input
// Truncate values lower than minPhasePerm upwards.
phase2PermValuesDiag[cell_idx][0] = max(minPhase2Perm, phase2PermValuesDiag[cell_idx][0]);
phase2PermValuesDiag[cell_idx][1] = max(minPhase2Perm, phase2PermValuesDiag[cell_idx][1]);
phase2PermValuesDiag[cell_idx][2] = max(minPhase2Perm, phase2PermValuesDiag[cell_idx][2]);
accPhase2Perm += phase2PermValuesDiag[cell_idx][0]; // not correct anyway
cellperm(0,0) = phase2PermValuesDiag[cell_idx][0];
cellperm(1,1) = phase2PermValuesDiag[cell_idx][1];
cellperm(2,2) = phase2PermValuesDiag[cell_idx][2];
}
helper.upscaler.setPermeability(i, cellperm);
}
phase2PermTensor = helper.upscaler.upscaleSinglePhase();
}
//cout << phasePermTensor << endl;
// Here we recalculate the upscaled water saturation,
// although it is already known when we asked for the
// pressure point to compute for. Nonetheless, we
// recalculate here to avoid any minor roundoff-error and
// interpolation error (this means that the saturation
// points are not perfectly uniformly distributed)
helper.WaterSaturation[pointidx] = waterVolumeLF/helper.poreVolume;
#ifdef HAVE_MPI
cout << "Rank " << mpi_rank << ": ";
#endif
cout << Ptestvalue << "\t" << helper.WaterSaturation[pointidx];
// Store and print phase-perm-result
for (int voigtIdx=0; voigtIdx < helper.tensorElementCount; ++voigtIdx) {
helper.PhasePerm[0][pointidx][voigtIdx] = getVoigtValue(phasePermTensor, voigtIdx);
cout << "\t" << getVoigtValue(phasePermTensor, voigtIdx);
if (helper.upscaleBothPhases){
helper.PhasePerm[1][pointidx][voigtIdx] = getVoigtValue(phase2PermTensor, voigtIdx);
cout << "\t" << getVoigtValue(phase2PermTensor, voigtIdx);
}
}
cout << endl;
}
}
clock_t finish_upscale_wallclock = clock();
timeused_upscale_wallclock = (double(finish_upscale_wallclock)-double(start_upscale_wallclock))/CLOCKS_PER_SEC;
helper.collectResults();
// Average time pr. upscaling point:
#ifdef HAVE_MPI
// Sum the upscaling time used by all processes
double timeused_total;
MPI_Reduce(&timeused_upscale_wallclock, &timeused_total, 1, MPI_DOUBLE,
MPI_SUM, 0, MPI_COMM_WORLD);
double avg_upscaling_time_pr_point = timeused_total/(double)points;
#else
double avg_upscaling_time_pr_point = timeused_upscale_wallclock / (double)helper.points;
#endif
double timeused_upscale_wallclock, avg_upscaling_time_pr_point;
std::tie(timeused_upscale_wallclock, avg_upscaling_time_pr_point) =
helper.upscalePermeability(options, dP, mpi_rank);
/*
* Step 8c: Make relperm values from phaseperms