diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index 4e6ed3d9ba..768818d63e 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -25,7 +25,7 @@ #include "RimProject.h" #include "RimWellPath.h" #include "RimFishbonesMultipleSubs.h" -#include "RimCaseAndFileExportSettings.h" +#include "RimExportCompletionDataSettings.h" #include "RiuMainWindow.h" @@ -78,7 +78,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) QString projectFolder = app->currentProjectPath(); QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder); - RimCaseAndFileExportSettings exportSettings; + RimExportCompletionDataSettings exportSettings; exportSettings.fileName = QDir(defaultDir).filePath("Completions"); @@ -91,7 +91,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) { RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath()); - exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply); + exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply, exportSettings.includeWpimult()); } } @@ -106,9 +106,15 @@ void RicWellPathExportCompletionDataFeature::setupActionLook(QAction* actionToSe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply) +void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult) { QFile exportFile(fileName); + + if (caseToApply == nullptr) + { + RiaLogging::error("Export Completions Data: Cannot export completions data without specified eclipse case"); + return; + } if (!exportFile.open(QIODevice::WriteOnly)) { @@ -120,55 +126,90 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat const RigEclipseCaseData* caseData = caseToApply->eclipseCaseData(); std::vector wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + std::map lateralsPerCell; RifEclipseOutputTableFormatter formatter(stream); - std::vector header = { - RifEclipseOutputTableColumn{"Well", LEFT}, - RifEclipseOutputTableColumn{"I", LEFT}, - RifEclipseOutputTableColumn{"J", LEFT}, - RifEclipseOutputTableColumn{"K1", LEFT}, - RifEclipseOutputTableColumn{"K2", LEFT}, - RifEclipseOutputTableColumn{"Status", LEFT}, - RifEclipseOutputTableColumn{"SAT", LEFT}, - RifEclipseOutputTableColumn{"TR", LEFT}, - RifEclipseOutputTableColumn{"DIAM", LEFT}, - RifEclipseOutputTableColumn{"KH", LEFT}, - RifEclipseOutputTableColumn{"S", LEFT}, - RifEclipseOutputTableColumn{"Df", LEFT}, - RifEclipseOutputTableColumn{"DIR", LEFT}, - RifEclipseOutputTableColumn{"r0", LEFT} - }; - formatter.keyword("COMPDAT"); - formatter.header(header); - - for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + // COMPDAT { - for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K1", LEFT}, + RifEclipseOutputTableColumn{"K2", LEFT}, + RifEclipseOutputTableColumn{"Status", LEFT}, + RifEclipseOutputTableColumn{"SAT", LEFT}, + RifEclipseOutputTableColumn{"TR", LEFT}, + RifEclipseOutputTableColumn{"DIAM", LEFT}, + RifEclipseOutputTableColumn{"KH", LEFT}, + RifEclipseOutputTableColumn{"S", LEFT}, + RifEclipseOutputTableColumn{"Df", LEFT}, + RifEclipseOutputTableColumn{"DIR", LEFT}, + RifEclipseOutputTableColumn{"r0", LEFT} + }; + + formatter.keyword("COMPDAT"); + formatter.header(header); + + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) { - for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) + for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) { - std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); - - std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); - - std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); - - std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); - - formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); - for (auto cellRange : cellRanges) + for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) { - // Add cell indices - formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); - // Remaining data, to be computed - formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); - formatter.rowCompleted(); + std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); + + std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); + + if (includeWpimult) + { + // Only need this data if WPIMULT should be included in file + addLateralToCells(&lateralsPerCell, lateralCells); + } + + std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); + + std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); + + formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); + for (auto cellRange : cellRanges) + { + // Add cell indices + formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); + // Remaining data, to be computed + formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); + formatter.rowCompleted(); + } } } } + formatter.flush(); + } + + // WPIMULT + if (includeWpimult) + { + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"Mult", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K", LEFT}, + }; + formatter.keyword("WPIMULT"); + formatter.header(header); + + for (auto lateralsInCell : lateralsPerCell) + { + size_t i, j, k; + caseData->mainGrid()->ijkFromCellIndex(lateralsInCell.first, &i, &j, &k); + formatter.add(wellPath->name()).add(lateralsInCell.second).addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k); + formatter.rowCompleted(); + } + + formatter.flush(); } - formatter.flush(); } //-------------------------------------------------------------------------------------------------- @@ -351,4 +392,23 @@ std::vector RicWellPathExportCompletionDataFeature::filterWellPathCells( return filteredCells; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells) +{ + for (size_t cell : lateralCells) + { + std::map::iterator it = lateralsPerCell->find(cell); + if (it == lateralsPerCell->end()) + { + (*lateralsPerCell)[cell] = 1; + } + else + { + (*lateralsPerCell)[cell] = it->second + 1; + } + } +} + } // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index cba7d2507e..230304f8bf 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -57,13 +57,14 @@ protected: virtual void setupActionLook(QAction* actionToSetup) override; private: - static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply); + static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult); static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); static std::vector findIntersectingCells(const RigEclipseCaseData* grid, const std::vector& coords); static void setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners); static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); + static void addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells); }; diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index c1fc5e076b..4168f948db 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -74,6 +74,9 @@ void RifEclipseOutputTableFormatter::outputBuffer() m_out << " /" << "\n"; } } + // If we finished a table, output an "empty" line after it + if (!m_columns.empty()) m_out << "/\n"; + m_columns.clear(); m_buffer.clear(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index be2d6a1cd9..ba156e920a 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -8,6 +8,7 @@ set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.h ${CEE_CURRENT_LIST_DIR}RimCaseCollection.h ${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.h +${CEE_CURRENT_LIST_DIR}RimExportCompletionDataSettings.h ${CEE_CURRENT_LIST_DIR}RimCellFilter.h ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.h ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.h @@ -101,6 +102,7 @@ set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.cpp ${CEE_CURRENT_LIST_DIR}RimCaseCollection.cpp ${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.cpp +${CEE_CURRENT_LIST_DIR}RimExportCompletionDataSettings.cpp ${CEE_CURRENT_LIST_DIR}RimCellFilter.cpp ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.cpp ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp new file mode 100644 index 0000000000..656e0680bf --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimExportCompletionDataSettings.h" + +CAF_PDM_SOURCE_INIT(RimExportCompletionDataSettings, "RimExportCompletionDataSettings"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimExportCompletionDataSettings::RimExportCompletionDataSettings() +{ + CAF_PDM_InitObject("RimExportCompletionDataSettings", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&includeWpimult, "IncludeWPIMULT", "Include WPIMLUT", "", "", ""); +} diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h new file mode 100644 index 0000000000..3728ab04e3 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCaseAndFileExportSettings.h" + +#include "cafPdmField.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimExportCompletionDataSettings : public RimCaseAndFileExportSettings +{ + CAF_PDM_HEADER_INIT; +public: + + RimExportCompletionDataSettings(); + + caf::PdmField includeWpimult; +};