Merge branch 'dev' into pre-proto

This commit is contained in:
Bjørnar Grip Fjær
2017-06-20 13:26:52 +02:00
47 changed files with 1460 additions and 395 deletions

View File

@@ -57,6 +57,7 @@
#include <QMessageBox>
#include "RicFishbonesTransmissibilityCalculationFeatureImp.h"
#include "RicExportFractureCompletionsImpl.h"
#include "RigActiveCellInfo.h"
CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature");
@@ -131,12 +132,12 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked)
}
}
exportSettings.fileName = QDir(defaultDir).filePath("Completions");
exportSettings.folder = defaultDir;
caf::PdmUiPropertyViewDialog propertyDialog(RiuMainWindow::instance(), &exportSettings, "Export Completion Data", "");
if (propertyDialog.exec() == QDialog::Accepted)
{
RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath());
RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.folder).absolutePath());
exportCompletions(wellPaths, simWells, exportSettings);
}
@@ -202,9 +203,10 @@ std::vector<RimEclipseWell*> RicWellPathExportCompletionDataFeature::selectedSim
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector<RimWellPath*>& wellPaths, const std::vector<RimEclipseWell*>& simWells, const RicExportCompletionDataSettingsUi& exportSettings)
void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector<RimWellPath*>& wellPaths,
const std::vector<RimEclipseWell*>& simWells,
const RicExportCompletionDataSettingsUi& exportSettings)
{
QFile exportFile(exportSettings.fileName());
if (exportSettings.caseToApply() == nullptr)
{
@@ -212,22 +214,27 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
return;
}
if (!exportFile.open(QIODevice::WriteOnly))
std::vector<RimWellPath*> usedWellPaths;
if (exportSettings.wellSelection == RicExportCompletionDataSettingsUi::ALL_WELLS)
{
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(exportSettings.fileName()));
return;
usedWellPaths = wellPaths;
}
else if (exportSettings.wellSelection == RicExportCompletionDataSettingsUi::CHECKED_WELLS)
{
for (auto wellPath : wellPaths)
{
if (wellPath->showWellPath)
{
usedWellPaths.push_back(wellPath);
}
}
}
{
bool unitSystemMismatch = false;
for (const RimWellPath* wellPath : wellPaths)
for (const RimWellPath* wellPath : usedWellPaths)
{
if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD && exportSettings.caseToApply->eclipseCaseData()->unitsType() != RigEclipseCaseData::UNITS_FIELD)
{
unitSystemMismatch = true;
break;
}
else if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC && exportSettings.caseToApply->eclipseCaseData()->unitsType() != RigEclipseCaseData::UNITS_METRIC)
if (wellPath->unitSystem() != exportSettings.caseToApply->eclipseCaseData()->unitsType())
{
unitSystemMismatch = true;
break;
@@ -249,63 +256,234 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
return;
}
}
std::map<IJKCellIndex, std::vector<RigCompletionData> > completionsPerEclipseCell;
// FractureTransmissibilityExportInformation
QTextStream stream(&exportFile);
RifEclipseDataTableFormatter formatter(stream);
QString fractureTransmisibillityExportInformationPath = QDir(exportSettings.folder).filePath("FractureTransmissibilityExportInformation");
QFile fractureTransmissibilityExportInformationFile(fractureTransmisibillityExportInformationPath);
if (!fractureTransmissibilityExportInformationFile.open(QIODevice::WriteOnly))
{
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(fractureTransmisibillityExportInformationPath));
return;
}
QTextStream fractureTransmissibilityExportInformationStream(&fractureTransmissibilityExportInformationFile);
std::map<IJKCellIndex, RigCompletionData> completionData;
for (auto wellPath : wellPaths)
for (auto wellPath : usedWellPaths)
{
// Generate completion data
if (exportSettings.includePerforations)
{
std::vector<RigCompletionData> perforationCompletionData = generatePerforationsCompdatValues(wellPath, exportSettings);
appendCompletionData(&completionData, perforationCompletionData);
appendCompletionData(&completionsPerEclipseCell, perforationCompletionData);
}
if (exportSettings.includeFishbones)
{
// std::vector<RigCompletionData> fishbonesCompletionData = RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneLateralsCompdatValues(wellPath, exportSettings);
// appendCompletionData(&completionData, fishbonesCompletionData);
// std::vector<RigCompletionData> fishbonesWellPathCompletionData = RicFishbonesTransmissibilityCalculationFeatureImp::generateFishbonesImportedLateralsCompdatValues(wellPath, exportSettings);
// appendCompletionData(&completionData, fishbonesWellPathCompletionData);
std::vector<RigCompletionData> fishbonesCompletionData = RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneCompdatValuesUsingAdjustedCellVolume(wellPath, exportSettings);
appendCompletionData(&completionData, fishbonesCompletionData);
appendCompletionData(&completionsPerEclipseCell, fishbonesCompletionData);
}
if (exportSettings.includeFractures())
{
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(wellPath, exportSettings, &stream);
appendCompletionData(&completionData, fractureCompletionData);
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(wellPath, exportSettings, &fractureTransmissibilityExportInformationStream);
appendCompletionData(&completionsPerEclipseCell, fractureCompletionData);
}
}
for (auto simWell : simWells)
{
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(exportSettings.caseToApply(), simWell, exportSettings.timeStep(), &stream);
appendCompletionData(&completionData, fractureCompletionData);
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(exportSettings.caseToApply(), simWell, exportSettings.timeStep(), &fractureTransmissibilityExportInformationStream);
appendCompletionData(&completionsPerEclipseCell, fractureCompletionData);
}
// Merge map into a vector of values
std::vector<RigCompletionData> completions;
for (auto& data : completionData)
//std::map < IJKCellIndex, std::map<QString, RigCompletionData >> combinedCompletionDataPerEclipseCell;
//Should be moved to map instead of vector
for (auto& data : completionsPerEclipseCell)
{
completions.push_back(data.second);
//completions.push_back(RigCompletionData::combine(data.second));
completions.push_back(combineEclipseCellCompletions(data.second, exportSettings));
}
const QString eclipseCaseName = exportSettings.caseToApply->caseUserDescription();
if (exportSettings.fileSplit == RicExportCompletionDataSettingsUi::UNIFIED_FILE)
{
const QString fileName = QString("UnifiedCompletions_%1").arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, completions, exportSettings.includeWpimult);
}
else if (exportSettings.fileSplit == RicExportCompletionDataSettingsUi::SPLIT_ON_WELL)
{
for (auto wellPath : usedWellPaths)
{
std::vector<RigCompletionData> wellCompletions;
for (auto completion : completions)
{
if (completion.wellName() == wellPath->completions()->wellNameForExport())
{
wellCompletions.push_back(completion);
}
}
QString fileName = QString("%1_unifiedCompletions_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, wellCompletions, exportSettings.includeWpimult);
}
}
else if (exportSettings.fileSplit == RicExportCompletionDataSettingsUi::SPLIT_ON_WELL_AND_COMPLETION_TYPE)
{
for (auto wellPath : usedWellPaths)
{
{
std::vector<RigCompletionData> fishbonesCompletions = getCompletionsForWellAndCompletionType(completions, wellPath->completions()->wellNameForExport(), RigCompletionData::FISHBONES);
QString fileName = QString("%1_Fishbones_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, fishbonesCompletions, exportSettings.includeWpimult);
}
{
std::vector<RigCompletionData> perforationCompletions = getCompletionsForWellAndCompletionType(completions, wellPath->completions()->wellNameForExport(), RigCompletionData::PERFORATION);
QString fileName = QString("%1_Perforations_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, perforationCompletions, exportSettings.includeWpimult);
}
}
}
}
//==================================================================================================
///
//==================================================================================================
RigCompletionData RicWellPathExportCompletionDataFeature::combineEclipseCellCompletions(const std::vector<RigCompletionData>& completions,
const RicExportCompletionDataSettingsUi& settings)
{
CVF_ASSERT(!completions.empty());
QString wellName = completions[0].wellName();
IJKCellIndex cellIndexIJK = completions[0].cellIndex();
RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid();
size_t cellIndex = grid->cellIndexFromIJK(cellIndexIJK.i, cellIndexIJK.j, cellIndexIJK.k);
RigCompletionData::CompletionType completionType = completions[0].completionType();
//completion type, skin factor, well bore diameter and cell direction are taken from (first) main bore,
//if no main bore they are taken from first completion
double skinfactor = completions[0].skinFactor();
double wellBoreDiameter = completions[0].diameter();
CellDirection cellDirection = completions[0].direction();
for (const RigCompletionData& completion : completions)
{
if (completion.isMainBore())
{
skinfactor = completion.skinFactor();
wellBoreDiameter = completion.diameter();
cellDirection = completion.direction();
break;
}
}
RigCompletionData resultCompletion(wellName, cellIndexIJK);
double totalTrans = 0.0;
for (const RigCompletionData& completion : completions)
{
if (completion.completionType() != completions[0].completionType())
{
RiaLogging::error(QString("Cannot combine completions of different types in same cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
return resultCompletion; //Returning empty completion, should not be exported
}
if (completion.wellName() != completions[0].wellName())
{
RiaLogging::error(QString("Cannot combine completions from different wells in same cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
return resultCompletion; //Returning empty completion, should not be exported
}
if (completion.transmissibility() == HUGE_VAL)
{
RiaLogging::error(QString("Transmissibility calculation has failed for cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
return resultCompletion; //Returning empty completion, should not be exported
}
totalTrans = totalTrans + completion.transmissibility();
}
if (settings.computeTransmissibility() && !settings.includeWpimult) //TODO: replace with explicitTransmissibilityExport setting
{
resultCompletion.setCombinedValuesExplicitTrans(totalTrans, completionType);
}
if (settings.includeWpimult) //TODO: replace with implicitTransmissibilityExportByWPImult
{
//calculate trans for main bore - but as Eclipse will do it!
double transmissibilityEclipseCalculation = RicWellPathExportCompletionDataFeature::calculateTransmissibilityAsEclipseDoes(settings.caseToApply(),
skinfactor,
wellBoreDiameter / 2,
cellIndex,
cellDirection);
double wpimult = totalTrans / transmissibilityEclipseCalculation;
resultCompletion.setCombinedValuesImplicitTransWPImult(wpimult, cellDirection, skinfactor, wellBoreDiameter, completionType);
}
return resultCompletion;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::printCompletionsToFile(const QString& exportFolder, const QString& fileName, std::vector<RigCompletionData>& completions, bool includeWpimult)
{
//TODO: Check that completion is ready for export
//TODO: Use wpimult instead of count for export!
QString filePath = QDir(exportFolder).filePath(fileName);
QFile exportFile(filePath);
if (!exportFile.open(QIODevice::WriteOnly))
{
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(filePath));
return;
}
QTextStream stream(&exportFile);
RifEclipseDataTableFormatter formatter(stream);
// Sort by well name / cell index
std::sort(completions.begin(), completions.end());
// Print completion data
generateCompdatTable(formatter, completions);
if (exportSettings.includeWpimult)
if (includeWpimult)
{
generateWpimultTable(formatter, completions);
}
RiaLogging::info(QString("Successfully exported completion data to %1").arg(exportSettings.fileName()));
RiaLogging::info(QString("Successfully exported completion data to %1").arg(filePath));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicWellPathExportCompletionDataFeature::getCompletionsForWellAndCompletionType(const std::vector<RigCompletionData>& completions,
const QString& wellName,
RigCompletionData::CompletionType completionType)
{
std::vector<RigCompletionData> filteredCompletions;
for (auto completion : completions)
{
if (completion.wellName() == wellName && completion.completionType() == completionType)
{
filteredCompletions.push_back(completion);
}
}
return filteredCompletions;
}
//--------------------------------------------------------------------------------------------------
@@ -420,7 +598,11 @@ void RicWellPathExportCompletionDataFeature::generateWpimultTable(RifEclipseData
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicWellPathExportCompletionDataFeature::generatePerforationsCompdatValues(const RimWellPath* wellPath, const RicExportCompletionDataSettingsUi& settings)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
std::vector<RigCompletionData> completionData;
const RigActiveCellInfo* activeCellInfo = settings.caseToApply->eclipseCaseData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS);
for (const RimPerforationInterval* interval : wellPath->perforationIntervalCollection()->perforations())
{
@@ -430,13 +612,28 @@ std::vector<RigCompletionData> RicWellPathExportCompletionDataFeature::generateP
std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), perforationPoints);
for (auto& cell : intersectedCells)
{
bool cellIsActive = activeCellInfo->isActive(cell.cellIndex);
if (!cellIsActive) continue;
size_t i, j, k;
settings.caseToApply->eclipseCaseData()->mainGrid()->ijkFromCellIndex(cell.cellIndex, &i, &j, &k);
RigCompletionData completion(wellPath->completions()->wellNameForExport(), IJKCellIndex(i, j, k));
completion.addMetadata("Perforation", QString("StartMD: %1 - EndMD: %2").arg(interval->startMD()).arg(interval->endMD()));
double diameter = interval->diameter();
CellDirection direction = calculateDirectionInCell(settings.caseToApply, cell.cellIndex, cell.internalCellLengths);
completion.setFromPerforation(diameter, direction);
double transmissibility = RicWellPathExportCompletionDataFeature::calculateTransmissibility(settings.caseToApply,
wellPath,
cell.internalCellLengths,
interval->skinFactor(),
interval->diameter(unitSystem) / 2,
cell.cellIndex);
completion.setTransAndWPImultBackgroundDataFromPerforation(transmissibility,
interval->skinFactor(),
interval->diameter(unitSystem),
direction);
completionData.push_back(completion);
}
}
@@ -612,18 +809,18 @@ void RicWellPathExportCompletionDataFeature::assignBranchAndSegmentNumbers(const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::appendCompletionData(std::map<IJKCellIndex, RigCompletionData>* completionData, const std::vector<RigCompletionData>& data)
void RicWellPathExportCompletionDataFeature::appendCompletionData(std::map<IJKCellIndex, std::vector<RigCompletionData> >* completionData, const std::vector<RigCompletionData>& data)
{
for (auto& completion : data)
{
auto it = completionData->find(completion.cellIndex());
if (it != completionData->end())
{
it->second = RigCompletionData::combine(it->second, completion);
it->second.push_back(completion);
}
else
{
completionData->insert(std::pair<IJKCellIndex, RigCompletionData>(completion.cellIndex(), completion));
completionData->insert(std::pair<IJKCellIndex, std::vector<RigCompletionData> >(completion.cellIndex(), std::vector<RigCompletionData> {completion}));
}
}
}
@@ -670,7 +867,7 @@ double RicWellPathExportCompletionDataFeature::calculateTransmissibility(RimEcli
double wellRadius,
size_t cellIndex,
size_t volumeScaleConstant,
QString directionForVolumeScaling)
CellDirection directionForVolumeScaling)
{
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
@@ -699,9 +896,9 @@ double RicWellPathExportCompletionDataFeature::calculateTransmissibility(RimEcli
if (volumeScaleConstant != 1)
{
if (directionForVolumeScaling == "DX") dx = dx / volumeScaleConstant;
if (directionForVolumeScaling == "DY") dy = dy / volumeScaleConstant;
if (directionForVolumeScaling == "DZ") dz = dz / volumeScaleConstant;
if (directionForVolumeScaling == CellDirection::DIR_I) dx = dx / volumeScaleConstant;
if (directionForVolumeScaling == CellDirection::DIR_J) dy = dy / volumeScaleConstant;
if (directionForVolumeScaling == CellDirection::DIR_K) dz = dz / volumeScaleConstant;
}
double transx = RigTransmissibilityEquations::wellBoreTransmissibilityComponent(internalCellLengths.x(), permy, permz, dy, dz, wellRadius, skinFactor, darcy);
@@ -710,3 +907,56 @@ double RicWellPathExportCompletionDataFeature::calculateTransmissibility(RimEcli
return RigTransmissibilityEquations::totalConnectionFactor(transx, transy, transz);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicWellPathExportCompletionDataFeature::calculateTransmissibilityAsEclipseDoes(RimEclipseCase* eclipseCase,
double skinFactor,
double wellRadius,
size_t cellIndex,
CellDirection direction)
{
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "DX");
cvf::ref<RigResultAccessor> dxAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "DX");
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "DY");
cvf::ref<RigResultAccessor> dyAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "DY");
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "DZ");
cvf::ref<RigResultAccessor> dzAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "DZ");
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "PERMX");
cvf::ref<RigResultAccessor> permxAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "PERMX");
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "PERMY");
cvf::ref<RigResultAccessor> permyAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "PERMY");
eclipseCase->results(RifReaderInterface::MATRIX_RESULTS)->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "PERMZ");
cvf::ref<RigResultAccessor> permzAccessObject = RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, RifReaderInterface::MATRIX_RESULTS, 0, "PERMZ");
double dx = dxAccessObject->cellScalarGlobIdx(cellIndex);
double dy = dyAccessObject->cellScalarGlobIdx(cellIndex);
double dz = dzAccessObject->cellScalarGlobIdx(cellIndex);
double permx = permxAccessObject->cellScalarGlobIdx(cellIndex);
double permy = permxAccessObject->cellScalarGlobIdx(cellIndex);
double permz = permxAccessObject->cellScalarGlobIdx(cellIndex);
RiaEclipseUnitTools::UnitSystem units = eclipseCaseData->unitsType();
double darcy = RiaEclipseUnitTools::darcysConstant(units);
double trans = cvf::UNDEFINED_DOUBLE;
if (direction == CellDirection::DIR_I)
{
trans = RigTransmissibilityEquations::wellBoreTransmissibilityComponent(dx, permy, permz, dy, dz, wellRadius, skinFactor, darcy);
}
else if (direction == CellDirection::DIR_J)
{
trans = RigTransmissibilityEquations::wellBoreTransmissibilityComponent(dy, permx, permz, dx, dz, wellRadius, skinFactor, darcy);
}
else if (direction == CellDirection::DIR_K)
{
trans = RigTransmissibilityEquations::wellBoreTransmissibilityComponent(dz, permy, permx, dy, dx, wellRadius, skinFactor, darcy);
}
return trans;
}