Python: Add cell filter reference to perforation intervals

Lets a script attach a cell filter to a RimPerforationInterval as a
typed reference so subsequent work can gate completion-export
connections by the filter's cell mask. Pure metadata in this commit:
no consumer of RimPerforationInterval is modified, the field exists
purely as an API surface.

Add a non-scriptable caf::PdmPtrField<RimCellFilter*> m_cellFilter to
RimPerforationInterval with public cellFilter()/setCellFilter()
accessors and a "Cell Filter" group in the property panel between the
existing geometry/flow group and the Date Settings group. The field is
deliberately non-scriptable: a scriptable PdmPtrField round-trips in
Python as an opaque "ClassName:0xADDR" string rather than a resolved
object, defeating the point. Two CAF object methods on
RimcPerforationInterval expose the relationship:

- AddFilter (perf.add_filter(filter)) sets the pointer; replaces any
  existing filter (single filter per perforation).
- cell_filter (perf.cell_filter()) resolves to the referenced
  RimCellFilter object on read, mirroring the valve.template() pattern.

Composition stays in RimCombinedFilter: a script that wants AND/OR
across multiple filters attaches a combined filter as the single
filter on the perforation.

The Python example in PythonExamples builds a case-level AND combined
filter (PERMX 100..20000 AND K=5..10), creates a modeled well path
with two perforation intervals, and shares the same filter between
them. test_perforation_filter.py covers single-set, replace-on-second-
add, and shared-pointer round-trips.
This commit is contained in:
Kristian Bendiksen committed 2026-05-15 08:37:46 +02:00
1 parent 3a1ff7a1e3
commit c9456bba62
6 files changed
+324

No files matched your search

@@ -18,6 +18,7 @@
#include "RimcPerforationInterval.h"
#include "RimCellFilter.h"
#include "RimEclipseCase.h"
#include "RimPerforationCollection.h"
#include "RimPerforationInterval.h"
@@ -80,3 +81,55 @@ QString RimcPerforationInterval_addValve::classKeywordReturnedType() const
{
return RimWellPathValve::classKeywordStatic();
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimPerforationInterval, RimcPerforationInterval_addFilter, "AddFilter" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcPerforationInterval_addFilter::RimcPerforationInterval_addFilter( caf::PdmObjectHandle* self )
: caf::PdmVoidObjectMethod( self )
{
CAF_PDM_InitObject( "Add Cell Filter", "", "", "Set the cell filter associated with this perforation interval (replaces any existing filter)" );
CAF_PDM_InitScriptableFieldNoDefault( &m_filter, "Filter", "", "", "", "Cell Filter" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcPerforationInterval_addFilter::execute()
{
auto* perfInterval = self<RimPerforationInterval>();
perfInterval->setCellFilter( m_filter() );
perfInterval->updateConnectedEditors();
return nullptr;
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimPerforationInterval, RimcPerforationInterval_cellFilter, "cell_filter" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcPerforationInterval_cellFilter::RimcPerforationInterval_cellFilter( caf::PdmObjectHandle* self )
: PdmObjectMethod( self, PdmObjectMethod::NullPointerType::NULL_IS_VALID, PdmObjectMethod::ResultType::PERSISTENT_TRUE )
{
CAF_PDM_InitObject( "Cell Filter", "", "", "Cell filter associated with this perforation interval, or null if none" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcPerforationInterval_cellFilter::execute()
{
return self<RimPerforationInterval>()->cellFilter();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimcPerforationInterval_cellFilter::classKeywordReturnedType() const
{
return RimCellFilter::classKeywordStatic();
}
@@ -25,6 +25,7 @@
#include <QString>
class RimCellFilter;
class RimValveTemplate;
//==================================================================================================
@@ -46,3 +47,33 @@ private:
caf::PdmField<double> m_endMd;
caf::PdmField<int> m_valveCount;
};
//==================================================================================================
/// Set the cell filter associated with this perforation interval. Replaces any existing filter.
//==================================================================================================
class RimcPerforationInterval_addFilter : public caf::PdmVoidObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcPerforationInterval_addFilter( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
private:
caf::PdmPtrField<RimCellFilter*> m_filter;
};
//==================================================================================================
/// Returns the cell filter associated with this perforation interval, or null if none.
//==================================================================================================
class RimcPerforationInterval_cellFilter : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcPerforationInterval_cellFilter( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
QString classKeywordReturnedType() const override;
};