diff --git a/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.cpp b/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.cpp index 945244f3e4..62bd6770ee 100644 --- a/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.cpp +++ b/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.cpp @@ -23,6 +23,7 @@ #include "Rim3dView.h" #include "RimCase.h" #include "RimEclipseResultCase.h" +#include "RimFractureTemplate.h" #include "RimProject.h" #include "cafPdmObjectHandle.h" @@ -85,6 +86,22 @@ std::expected RicfForwarding::findView( int viewId ) return std::unexpected( QString( "Could not find view with ID %1" ).arg( viewId ) ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::expected RicfForwarding::findFractureTemplate( int templateId ) +{ + RimProject* project = RimProject::current(); + if ( !project ) return std::unexpected( "No project is available." ); + + for ( RimFractureTemplate* fractureTemplate : project->allFractureTemplates() ) + { + if ( fractureTemplate && fractureTemplate->id() == templateId ) return fractureTemplate; + } + + return std::unexpected( QString( "Could not find fracture template with ID %1" ).arg( templateId ) ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.h b/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.h index d161fc4c27..8cf954db34 100644 --- a/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.h +++ b/ApplicationLibCode/CommandFileInterface/RicfCommandForwarding.h @@ -26,6 +26,7 @@ class RimCase; class Rim3dView; +class RimFractureTemplate; namespace caf { @@ -48,6 +49,9 @@ std::expected findView( RimCase* rimCase, int viewId ); /// Find a 3D view by id anywhere in the project. A negative id is not accepted. std::expected findView( int viewId ); +/// Find a fracture template by id. +std::expected findFractureTemplate( int templateId ); + /// Convert the result of a Rimc method execution to a script response, logging errors with the command name. caf::PdmScriptResponse toScriptResponse( const std::expected& result, const QString& commandName ); diff --git a/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.cpp b/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.cpp index 4f160ec39b..9954236b8c 100644 --- a/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.cpp +++ b/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.cpp @@ -19,41 +19,17 @@ #include "RicfCreateMultipleFractures.h" #include "RicfApplicationTools.h" -#include "RicfCommandFileExecutor.h" +#include "RicfCommandForwarding.h" -#include "FractureCommands/RicCreateMultipleFracturesFeature.h" -#include "FractureCommands/RicCreateMultipleFracturesOptionItemUi.h" -#include "FractureCommands/RicCreateMultipleFracturesUi.h" - -#include "RimDialogData.h" #include "RimEclipseCase.h" -#include "RimEclipseCaseCollection.h" #include "RimFractureTemplate.h" -#include "RimOilField.h" -#include "RimProject.h" #include "RimWellPath.h" +#include "RimcEclipseCase.h" -#include "RiaLogging.h" -#include "RiaQStringFormatter.h" -#include "RiaWellNameComparer.h" - -#include "cafCmdFeatureManager.h" #include "cafPdmFieldScriptingCapability.h" CAF_PDM_SOURCE_INIT( RicfCreateMultipleFractures, "createMultipleFractures" ); -namespace caf -{ -template <> -void AppEnum::setUp() -{ - addItem( MultipleFractures::Action::APPEND_FRACTURES, "APPEND_FRACTURES", "Append Fractures" ); - addItem( MultipleFractures::Action::REPLACE_FRACTURES, "REPLACE_FRACTURES", "Replace Fractures" ); - - setDefault( MultipleFractures::Action::NONE ); -} -} // namespace caf - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -78,110 +54,43 @@ RicfCreateMultipleFractures::RicfCreateMultipleFractures() //-------------------------------------------------------------------------------------------------- caf::PdmScriptResponse RicfCreateMultipleFractures::execute() { - using TOOLS = RicfApplicationTools; + const QString commandName = classKeyword(); - RimProject* project = RimProject::current(); - RiuCreateMultipleFractionsUi* settings = project->dialogData()->multipleFractionsData(); - - // Get case and fracture template - auto gridCase = TOOLS::caseFromId( m_caseId ); - auto fractureTemplate = fractureTemplateFromId( m_templateId ); - std::vector wellPaths; - - // Find well paths + if ( m_caseId() < 0 || m_templateId() < 0 ) { - QStringList wellsNotFound; - wellPaths = TOOLS::wellPathsFromNames( TOOLS::toQStringList( m_wellPathNames ), &wellsNotFound ); - if ( !wellsNotFound.empty() ) - { - QString error = QString( "createMultipleFractures: These well paths were not found: %1" ).arg( wellsNotFound.join( ", " ) ); - RiaLogging::error( error.toStdString() ); - return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error ); - } + return RicfForwarding::errorResponse( "Mandatory argument(s) missing: caseId and templateId are required", commandName ); } - if ( !gridCase ) + QStringList wellsNotFound; + std::vector wellPaths = + RicfApplicationTools::wellPathsFromNames( RicfApplicationTools::toQStringList( m_wellPathNames ), &wellsNotFound ); + if ( !wellsNotFound.empty() ) { - QString error = QString( "createMultipleFractures: Could not find case with ID %1" ).arg( m_caseId() ); - RiaLogging::error( error.toStdString() ); - return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error ); + return RicfForwarding::errorResponse( "These well paths were not found: " + wellsNotFound.join( ", " ), commandName ); + } + if ( wellPaths.empty() ) return RicfForwarding::errorResponse( "No wellpaths found", commandName ); + + auto rimCase = RicfForwarding::findCase( m_caseId() ); + if ( !rimCase ) return RicfForwarding::errorResponse( rimCase.error(), commandName ); + + auto* eclipseCase = dynamic_cast( rimCase.value() ); + if ( !eclipseCase ) + { + return RicfForwarding::errorResponse( QString( "Case with ID %1 is not an Eclipse case" ).arg( m_caseId() ), commandName ); } - if ( !fractureTemplate ) - { - QString error = QString( "createMultipleFractures: Could not find fracture template with ID %1" ).arg( m_templateId() ); - RiaLogging::error( error.toStdString() ); - return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error ); - } + auto fractureTemplate = RicfForwarding::findFractureTemplate( m_templateId() ); + if ( !fractureTemplate ) return RicfForwarding::errorResponse( fractureTemplate.error(), commandName ); - if ( wellPaths.empty() ) - { - QString error( "createMultipleFractures: No wellpaths found" ); - RiaLogging::error( error.toStdString() ); - return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error ); - } + RimEclipseCase_createMultipleFractures method( eclipseCase ); + method.setWellPaths( wellPaths ); + method.setFractureTemplate( fractureTemplate.value() ); + method.setMinDistFromWellTd( m_minDistFromWellTd() ); + method.setMaxFracturesPerWell( m_maxFracturesPerWell() ); + method.setTopLayer( m_topLayer() ); + method.setBaseLayer( m_baseLayer() ); + method.setSpacing( m_spacing() ); + method.setAction( m_action() ); - if ( !validateArguments() ) - { - QString error( "createMultipleFractures: Mandatory argument(s) missing" ); - RiaLogging::error( error.toStdString() ); - return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error ); - } - - RicCreateMultipleFracturesOptionItemUi* options = new RicCreateMultipleFracturesOptionItemUi(); - caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); - auto feature = - dynamic_cast( commandManager->getCommandFeature( "RicCreateMultipleFracturesFeature" ) ); - - // Default layers - int topLayer = m_topLayer; - int baseLayer = m_baseLayer; - if ( feature && ( topLayer < 0 || baseLayer < 0 ) ) - { - auto ijkRange = feature->ijkRangeForGrid( gridCase ); - if ( topLayer < 0 ) topLayer = static_cast( ijkRange.min().z() ); - if ( baseLayer < 0 ) baseLayer = static_cast( ijkRange.max().z() ); - } - options->setValues( topLayer, baseLayer, fractureTemplate, m_spacing ); - - settings->clearWellPaths(); - for ( auto wellPath : wellPaths ) - { - settings->addWellPath( wellPath ); - } - - settings->setValues( gridCase, m_minDistFromWellTd, m_maxFracturesPerWell ); - settings->clearOptions(); - settings->insertOptionItem( nullptr, options ); - - if ( feature ) - { - if ( m_action == MultipleFractures::Action::APPEND_FRACTURES ) feature->appendFractures(); - if ( m_action == MultipleFractures::Action::REPLACE_FRACTURES ) feature->replaceFractures(); - } - return caf::PdmScriptResponse(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RicfCreateMultipleFractures::validateArguments() const -{ - bool valid = m_caseId >= 0 && m_templateId >= 0; - - return valid; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimFractureTemplate* RicfCreateMultipleFractures::fractureTemplateFromId( int templateId ) const -{ - for ( RimFractureTemplate* t : RimProject::current()->allFractureTemplates() ) - { - if ( t->id() == templateId ) return t; - } - - RiaLogging::error( std::format( "createMultipleFractures: Could not find fracture template with ID {}", templateId ) ); - return nullptr; + return RicfForwarding::toScriptResponse( method.execute(), commandName ); } diff --git a/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.h b/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.h index d516b6b0a8..08d3a3b6b3 100644 --- a/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.h +++ b/ApplicationLibCode/CommandFileInterface/RicfCreateMultipleFractures.h @@ -20,18 +20,10 @@ #include "RicfCommandObject.h" +#include "FractureCommands/RicCreateMultipleFracturesFeature.h" #include "cafAppEnum.h" -#include "cafPdmField.h" -namespace MultipleFractures -{ -enum class Action -{ - NONE, - APPEND_FRACTURES, - REPLACE_FRACTURES -}; -} +#include "cafPdmField.h" class RimEclipseCase; class RimFractureTemplate; @@ -52,9 +44,6 @@ public: caf::PdmScriptResponse execute() override; private: - bool validateArguments() const; - RimFractureTemplate* fractureTemplateFromId( int templateId ) const; - caf::PdmField m_caseId; caf::PdmField> m_wellPathNames; caf::PdmField m_minDistFromWellTd; diff --git a/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.cpp b/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.cpp index 3a5903af76..808cb2d99e 100644 --- a/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.cpp +++ b/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.cpp @@ -17,10 +17,14 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RicCreateMultipleFracturesFeature.h" + #include "RicFractureNameGenerator.h" #include "RiaApplication.h" +#include "cafAppEnum.h" +#include "cafPdmScriptEnumNameRegistry.h" + #include "RicCreateMultipleFracturesUi.h" #include "RigActiveCellInfo.h" @@ -45,6 +49,28 @@ #include #include +namespace caf +{ +template <> +void AppEnum::setUp() +{ + addItem( MultipleFractures::Action::APPEND_FRACTURES, "APPEND_FRACTURES", "Append Fractures" ); + addItem( MultipleFractures::Action::REPLACE_FRACTURES, "REPLACE_FRACTURES", "Replace Fractures" ); + + setDefault( MultipleFractures::Action::NONE ); +} +} // namespace caf + +namespace +{ +// Pin the Python StrEnum class name for the action used by RimEclipseCase_createMultipleFractures +struct RegisterScriptEnumNames +{ + RegisterScriptEnumNames() { caf::PdmScriptEnumNameRegistry::registerName( "MultipleFracturesAction" ); } +}; +const RegisterScriptEnumNames s_registerScriptEnumNames; +} // namespace + CAF_CMD_SOURCE_INIT( RicCreateMultipleFracturesFeature, "RicCreateMultipleFracturesFeature" ); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.h b/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.h index 2a47537294..6f404d36b4 100644 --- a/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.h +++ b/ApplicationLibCode/Commands/FractureCommands/RicCreateMultipleFracturesFeature.h @@ -29,6 +29,16 @@ class RiuCreateMultipleFractionsUi; class RimEclipseCase; +namespace MultipleFractures +{ +enum class Action +{ + NONE, + APPEND_FRACTURES, + REPLACE_FRACTURES +}; +} + namespace caf { class PdmUiPropertyViewDialog; diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.cpp b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.cpp index f22c7fb327..a07bb3a461 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.cpp +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.cpp @@ -27,6 +27,8 @@ #include "CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h" #include "ExportCommands/RicEclipseCellResultToFileImpl.h" #include "ExportCommands/RicExportLgrFeature.h" +#include "FractureCommands/RicCreateMultipleFracturesOptionItemUi.h" +#include "FractureCommands/RicCreateMultipleFracturesUi.h" #include "RicCreateTemporaryLgrFeature.h" #include "RicDeleteTemporaryLgrsFeature.h" @@ -47,8 +49,10 @@ #include "RimCase.h" #include "RimCellFilter.h" +#include "RimDialogData.h" #include "RimEclipseCase.h" #include "RimEclipseResultCase.h" +#include "RimFractureTemplate.h" #include "RimOilField.h" #include "RimProject.h" #include "RimRoffCase.h" @@ -1166,3 +1170,157 @@ std::expected RimEclipseCase_exportLgrForComplet return nullptr; } + +CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_createMultipleFractures, "createMultipleFractures" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase_createMultipleFractures::RimEclipseCase_createMultipleFractures( caf::PdmObjectHandle* self ) + : caf::PdmVoidObjectMethod( self ) +{ + CAF_PDM_InitObject( "Create Multiple Fractures", "", "", "Create multiple fractures along the given well paths using a fracture template" ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths, "WellPaths", "Well Paths", "", "", "Well paths to create fractures for" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_fractureTemplate, "FractureTemplate", "Fracture Template", "", "", "Template used for the created fractures" ); + CAF_PDM_InitScriptableField( &m_minDistFromWellTd, + "MinDistFromWellTd", + 100.0, + "Min Distance From Well TD", + "", + "", + "Minimum distance from the well total depth" ); + CAF_PDM_InitScriptableField( &m_maxFracturesPerWell, "MaxFracturesPerWell", 100, "Max Fractures per Well" ); + CAF_PDM_InitScriptableField( &m_topLayer, "TopLayer", -1, "Top Layer", "", "", "Zero-based K index of the top layer. -1 uses the top of the grid." ); + CAF_PDM_InitScriptableField( &m_baseLayer, + "BaseLayer", + -1, + "Base Layer", + "", + "", + "Zero-based K index of the base layer. -1 uses the bottom of the grid." ); + CAF_PDM_InitScriptableField( &m_spacing, "Spacing", 300.0, "Spacing", "", "", "Distance between fractures" ); + CAF_PDM_InitScriptableField( &m_action, + "Action", + caf::AppEnum( MultipleFractures::Action::APPEND_FRACTURES ), + "Action", + "", + "", + "Append to or replace the existing fractures on the well paths" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setWellPaths( const std::vector& wellPaths ) +{ + m_wellPaths.setValue( wellPaths ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setFractureTemplate( RimFractureTemplate* fractureTemplate ) +{ + m_fractureTemplate = fractureTemplate; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setMinDistFromWellTd( double minDist ) +{ + m_minDistFromWellTd = minDist; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setMaxFracturesPerWell( int maxFractures ) +{ + m_maxFracturesPerWell = maxFractures; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setTopLayer( int topLayer ) +{ + m_topLayer = topLayer; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setBaseLayer( int baseLayer ) +{ + m_baseLayer = baseLayer; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setSpacing( double spacing ) +{ + m_spacing = spacing; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase_createMultipleFractures::setAction( MultipleFractures::Action action ) +{ + m_action = action; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::expected RimEclipseCase_createMultipleFractures::execute() +{ + auto* eclipseCase = self(); + if ( !eclipseCase ) return std::unexpected( "No case is available." ); + + std::vector wellPaths = m_wellPaths.ptrReferencedObjectsByType(); + if ( wellPaths.empty() ) return std::unexpected( "No well paths specified." ); + + RimFractureTemplate* fractureTemplate = m_fractureTemplate(); + if ( !fractureTemplate ) return std::unexpected( "No fracture template specified." ); + + if ( m_action() == MultipleFractures::Action::NONE ) return std::unexpected( "Action must be APPEND_FRACTURES or REPLACE_FRACTURES." ); + + auto* feature = dynamic_cast( + caf::CmdFeatureManager::instance()->getCommandFeature( "RicCreateMultipleFracturesFeature" ) ); + if ( !feature ) return std::unexpected( "The create multiple fractures feature is not available." ); + + RimProject* project = RimProject::current(); + RiuCreateMultipleFractionsUi* settings = project->dialogData()->multipleFractionsData(); + + // Default layers + int topLayer = m_topLayer(); + int baseLayer = m_baseLayer(); + if ( topLayer < 0 || baseLayer < 0 ) + { + auto ijkRange = feature->ijkRangeForGrid( eclipseCase ); + if ( topLayer < 0 ) topLayer = static_cast( ijkRange.min().z() ); + if ( baseLayer < 0 ) baseLayer = static_cast( ijkRange.max().z() ); + } + + auto* options = new RicCreateMultipleFracturesOptionItemUi(); + options->setValues( topLayer, baseLayer, fractureTemplate, m_spacing() ); + + settings->clearWellPaths(); + for ( RimWellPath* wellPath : wellPaths ) + { + settings->addWellPath( wellPath ); + } + + settings->setValues( eclipseCase, m_minDistFromWellTd(), m_maxFracturesPerWell() ); + settings->clearOptions(); + settings->insertOptionItem( nullptr, options ); + + if ( m_action() == MultipleFractures::Action::APPEND_FRACTURES ) feature->appendFractures(); + if ( m_action() == MultipleFractures::Action::REPLACE_FRACTURES ) feature->replaceFractures(); + + return nullptr; +} diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.h b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.h index 235fb11dd9..3a9c256894 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.h +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseCase.h @@ -23,6 +23,7 @@ #include "CompletionExportCommands/RicExportCompletionDataSettingsUi.h" #include "ExportCommands/RicLgrSplitType.h" +#include "FractureCommands/RicCreateMultipleFracturesFeature.h" #include "cafAppEnum.h" #include "cafPdmField.h" @@ -34,6 +35,7 @@ #include class RimCellFilter; +class RimFractureTemplate; class RimWellPath; //================================================================================================== @@ -341,3 +343,35 @@ private: QStringList m_wellsIntersectingOtherLgrs; }; + +//================================================================================================== +/// Create multiple fractures along the given well paths using a fracture template. +//================================================================================================== +class RimEclipseCase_createMultipleFractures : public caf::PdmVoidObjectMethod +{ + CAF_PDM_HEADER_INIT; + +public: + RimEclipseCase_createMultipleFractures( caf::PdmObjectHandle* self ); + + void setWellPaths( const std::vector& wellPaths ); + void setFractureTemplate( RimFractureTemplate* fractureTemplate ); + void setMinDistFromWellTd( double minDist ); + void setMaxFracturesPerWell( int maxFractures ); + void setTopLayer( int topLayer ); + void setBaseLayer( int baseLayer ); + void setSpacing( double spacing ); + void setAction( MultipleFractures::Action action ); + + std::expected execute() override; + +private: + caf::PdmPtrArrayField m_wellPaths; + caf::PdmPtrField m_fractureTemplate; + caf::PdmField m_minDistFromWellTd; + caf::PdmField m_maxFracturesPerWell; + caf::PdmField m_topLayer; + caf::PdmField m_baseLayer; + caf::PdmField m_spacing; + caf::PdmField> m_action; +}; diff --git a/GrpcInterface/Python/rips/case.py b/GrpcInterface/Python/rips/case.py index 30c26acc37..8c5a3fb48c 100644 --- a/GrpcInterface/Python/rips/case.py +++ b/GrpcInterface/Python/rips/case.py @@ -506,52 +506,6 @@ def export_msw(self, well_path: str) -> Any: ) -@add_method(Case) -def create_multiple_fractures( - self, - template_id: int, - well_path_names: Union[str, List[str]], - min_dist_from_well_td: float, - max_fractures_per_well: int, - top_layer: int, - base_layer: int, - spacing: float, - action: str, -) -> Any: - """ - Create Multiple Fractures in one go - - **Parameters**:: - - Parameter | Description | Type - -----------------------| ----------------------------------------- | ----- - template_id | Id of the template | Integer - well_path_names | List of well path names | List of Strings - min_dist_from_well_td | Minimum distance from well TD | Double - max_fractures_per_well | Max number of fractures per well | Integer - top_layer | Top grid k-level for fractures | Integer - base_layer | Base grid k-level for fractures | Integer - spacing | Spacing between fractures | Double - action | 'APPEND_FRACTURES' or 'REPLACE_FRACTURES' | String enum - - """ - if isinstance(well_path_names, str): - well_path_names = [well_path_names] - return self._execute_command( - createMultipleFractures=Cmd.CreateMultipleFracRequest( - caseId=self.id, - templateId=template_id, - wellPathNames=well_path_names, - minDistFromWellTd=min_dist_from_well_td, - maxFracturesPerWell=max_fractures_per_well, - topLayer=top_layer, - baseLayer=base_layer, - spacing=spacing, - action=action, - ) - ) - - @add_method(Case) def create_lgr_for_completion( self, diff --git a/GrpcInterface/Python/rips/tests/test_commands.py b/GrpcInterface/Python/rips/tests/test_commands.py index 951971fcff..e13a1e33ac 100644 --- a/GrpcInterface/Python/rips/tests/test_commands.py +++ b/GrpcInterface/Python/rips/tests/test_commands.py @@ -75,26 +75,61 @@ def test_create_and_export_lgr_for_completions(rips_instance, initialize_test): def test_create_multiple_fractures(rips_instance, initialize_test): - case = rips_instance.project.load_case( - dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + project = rips_instance.project.open( + dataroot.PATH + "/TEST10K_FLT_LGR_NNC/small-completion-export-fractures.rsp" ) - - well_files = [dataroot.PATH + "/TEST10K_FLT_LGR_NNC/wellpath_a.dev"] - rips_instance.project.import_well_paths(well_path_files=well_files) - - fracture_instances = rips_instance.project.descendants(rips.WellPathFracture) - assert len(fracture_instances) == 0 + case = project.cases()[0] + template = project.descendants(rips.FractureTemplate)[0] + well_path = project.well_paths()[0] case.create_multiple_fractures( - template_id=0, - well_path_names="Well Path A", + well_paths=[well_path], + fracture_template=template, min_dist_from_well_td=100.0, max_fractures_per_well=5, top_layer=1, base_layer=30, spacing=100.0, - action="REPLACE_FRACTURES", + action=rips.MultipleFracturesAction.REPLACE_FRACTURES, ) - fracture_instances = rips_instance.project.descendants(rips.WellPathFracture) + fracture_instances = project.descendants(rips.WellPathFracture) assert len(fracture_instances) > 0 + + +def test_create_multiple_fractures_object_method(rips_instance, initialize_test): + project = rips_instance.project.open( + dataroot.PATH + "/TEST10K_FLT_LGR_NNC/small-completion-export-fractures.rsp" + ) + case = project.cases()[0] + template = project.descendants(rips.FractureTemplate)[0] + well_paths = project.well_paths() + assert len(well_paths) > 0 + + before = len(project.descendants(rips.WellPathFracture)) + + case.create_multiple_fractures( + well_paths=well_paths[:1], + fracture_template=template, + min_dist_from_well_td=100.0, + max_fractures_per_well=3, + spacing=100.0, + action=rips.MultipleFracturesAction.APPEND_FRACTURES, + ) + after_append = len(project.descendants(rips.WellPathFracture)) + assert after_append > before + + case.create_multiple_fractures( + well_paths=well_paths[:1], + fracture_template=template, + max_fractures_per_well=1, + spacing=100.0, + action=rips.MultipleFracturesAction.REPLACE_FRACTURES, + ) + after_replace = len(project.descendants(rips.WellPathFracture)) + assert after_replace < after_append + + with pytest.raises(rips.RipsError): + case.create_multiple_fractures(well_paths=well_paths[:1]) + with pytest.raises(rips.RipsError): + case.create_multiple_fractures(fracture_template=template)