//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void Rim3dOverlayInfoConfig::updateVisCellStatsIfNeeded() { RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p()); RimGeoMechView * geoMechView = dynamic_cast<RimGeoMechView*>(m_viewDef.p()); if (!m_isVisCellStatUpToDate) { cvf::ref<RigStatisticsCalculator> calc; if (geoMechView) { RigFemResultAddress resAddress = geoMechView->cellResultResultDefinition()->resultAddress(); calc = new RigFemNativeVisibleCellsStatCalc(geoMechView->geoMechCase()->geoMechData(), resAddress, geoMechView->currentTotalCellVisibility().p()); } else if (eclipseView) { size_t scalarIndex = eclipseView->cellResult()->scalarResultIndex(); calc = new RigEclipseNativeVisibleCellsStatCalc(eclipseView->currentGridCellResults()->cellResults(), scalarIndex, eclipseView->currentTotalCellVisibility().p()); } m_visibleCellStatistics = new RigStatisticsDataCache(calc.p()); m_isVisCellStatUpToDate = true; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipsePropertyFilterCollection::updateIconState() { bool activeIcon = true; RimEclipseView* view = NULL; this->firstAncestorOrThisOfType(view); RimViewController* viewController = view->viewController(); if (viewController && (viewController->isPropertyFilterOveridden() || viewController->isVisibleCellsOveridden())) { activeIcon = false; } if (!isActive) { activeIcon = false; } updateUiIconFromState(activeIcon); for (size_t i = 0; i < propertyFilters.size(); i++) { RimEclipsePropertyFilter* cellFilter = propertyFilters[i]; cellFilter->updateActiveState(); cellFilter->updateIconState(); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void Rim3dOverlayInfoConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { caf::PdmUiGroup* visGroup = uiOrdering.addNewGroup("Visibility"); visGroup->add(&m_showAnimProgress); visGroup->add(&m_showCaseInfo); visGroup->add(&m_showResultInfo); RimGeoMechView * geoMechView = dynamic_cast<RimGeoMechView*>(m_viewDef.p()); if (!geoMechView) { visGroup->add(&m_showVolumeWeightedMean); } visGroup->add(&m_showHistogram); caf::PdmUiGroup* statGroup = uiOrdering.addNewGroup("Statistics Options"); RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p()); if (!eclipseView || !eclipseView->cellResult()->isFlowDiagOrInjectionFlooding()) { statGroup->add(&m_statisticsTimeRange); } statGroup->add(&m_statisticsCellRange); uiOrdering.skipRemainingFields(true); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogExtractionCurve::setPropertiesFromView(Rim3dView* view) { m_case = view ? view->ownerCase() : nullptr; RimGeoMechCase* geomCase = dynamic_cast<RimGeoMechCase*>(m_case.value()); RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value()); m_eclipseResultDefinition->setEclipseCase(eclipseCase); m_geomResultDefinition->setGeoMechCase(geomCase); RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>(view); if (eclipseView) { m_eclipseResultDefinition->simpleCopy(eclipseView->cellResult()); m_timeStep = eclipseView->currentTimeStep(); } RimGeoMechView* geoMechView = dynamic_cast<RimGeoMechView*>(view); if (geoMechView) { m_geomResultDefinition->setResultAddress(geoMechView->cellResultResultDefinition()->resultAddress()); m_timeStep = geoMechView->currentTimeStep(); } clearGeneratedSimWellPaths(); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigActiveCellInfo* RimCellRangeFilterCollection::activeCellInfo() const { RimEclipseView* eclipseView = this->eclipseView(); if (eclipseView) { return eclipseView->currentActiveCellInfo(); } return NULL; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::DrawableGeo> RivWellFracturePartMgr::createStimPlanMeshDrawable(RimStimPlanFractureTemplate* stimPlanFracTemplate, const RimEclipseView& activeView) { if (!stimPlanFracTemplate->fractureGrid()) return nullptr; auto displayCoordTransform = activeView.displayCoordTransform(); if (displayCoordTransform.isNull()) return nullptr; std::vector<RigFractureCell> stimPlanCells = stimPlanFracTemplate->fractureGrid()->fractureCells(); std::vector<cvf::Vec3f> stimPlanMeshVertices; QString resultNameFromColors = activeView.fractureColors()->uiResultName(); QString resultUnitFromColors = activeView.fractureColors()->unit(); std::vector<double> prCellResults = stimPlanFracTemplate->fractureGridResults( resultNameFromColors, resultUnitFromColors, stimPlanFracTemplate->activeTimeStepIndex()); m_visibleFracturePolygons.clear(); for (size_t cIdx = 0; cIdx < stimPlanCells.size(); ++cIdx) { if (prCellResults[cIdx] > 1e-7) { const RigFractureCell& stimPlanCell = stimPlanCells[cIdx]; std::vector<cvf::Vec3d> stimPlanCellPolygon = stimPlanCell.getPolygon(); for (const cvf::Vec3d& cellCorner : stimPlanCellPolygon) { stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner)); } m_visibleFracturePolygons.push_back(stimPlanCellPolygon); } } if (stimPlanMeshVertices.empty()) { return nullptr; } cvf::Mat4d fractureXf = m_rimFracture->transformMatrix(); std::vector<cvf::Vec3f> stimPlanMeshVerticesDisplayCoords = transformToFractureDisplayCoords(stimPlanMeshVertices, fractureXf, *displayCoordTransform); cvf::Vec3fArray* stimPlanMeshVertexList; stimPlanMeshVertexList = new cvf::Vec3fArray; stimPlanMeshVertexList->assign(stimPlanMeshVerticesDisplayCoords); cvf::ref<cvf::DrawableGeo> stimPlanMeshGeo = new cvf::DrawableGeo; stimPlanMeshGeo->setVertexArray(stimPlanMeshVertexList); cvf::ref<cvf::UIntArray> indices = RivFaultGeometryGenerator::lineIndicesFromQuadVertexArray(stimPlanMeshVertexList); cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES); prim->setIndices(indices.p()); stimPlanMeshGeo->addPrimitiveSet(prim.p()); return stimPlanMeshGeo; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimSimWellInView::pipeRadius() { RimEclipseView* reservoirView; firstAncestorOrThisOfTypeAsserted(reservoirView); RigEclipseCaseData* rigReservoir = reservoirView->eclipseCase()->eclipseCaseData(); double characteristicCellSize = rigReservoir->mainGrid()->characteristicIJCellSize(); double pipeRadius = reservoirView->wellCollection()->pipeScaleFactor() * this->pipeScaleFactor() * characteristicCellSize; return pipeRadius; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivWellFracturePartMgr::appendFracturePerforationLengthParts(const RimEclipseView& activeView, cvf::ModelBasicList* model) { if (!m_rimFracture->isChecked()) return; if (!m_rimFracture->fractureTemplate()) return; if (m_rimFracture->fractureTemplate()->orientationType() != RimFractureTemplate::ALONG_WELL_PATH) return; auto displayCoordTransform = activeView.displayCoordTransform(); if (displayCoordTransform.isNull()) return; double characteristicCellSize = activeView.ownerCase()->characteristicCellSize(); double wellPathRadius = 1.0; { RimWellPath* rimWellPath = nullptr; m_rimFracture->firstAncestorOrThisOfType(rimWellPath); if (rimWellPath) { wellPathRadius = rimWellPath->wellPathRadius(characteristicCellSize); } } { RimSimWellInView* simWell = nullptr; m_rimFracture->firstAncestorOrThisOfType(simWell); if (simWell) { wellPathRadius = simWell->pipeRadius(); } } std::vector<cvf::Vec3d> displayCoords = displayCoordTransform->transformToDisplayCoords(m_rimFracture->perforationLengthCenterLineCoords()); if (!displayCoords.empty()) { cvf::ref<RivObjectSourceInfo> objectSourceInfo = new RivObjectSourceInfo(m_rimFracture); double perforationRadius = wellPathRadius * 1.2; cvf::Collection<cvf::Part> parts; RivPipeGeometryGenerator geoGenerator; geoGenerator.cylinderWithCenterLineParts( &parts, displayCoords, RiaColorTables::wellPathComponentColors()[RiaDefines::PERFORATION_INTERVAL], perforationRadius); for (auto part : parts) { part->setSourceInfo(objectSourceInfo.p()); model->addPart(part.p()); } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigMainGrid* RimCellRangeFilterCollection::mainGrid() const { RimEclipseView* eclipseView = this->eclipseView(); if (eclipseView && eclipseView->eclipseCase() && eclipseView->eclipseCase()->reservoirData() && eclipseView->eclipseCase()->reservoirData()->mainGrid()) { return eclipseView->eclipseCase()->reservoirData()->mainGrid(); } return NULL; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const QString RivWellFracturePartMgr::resultInfoText(const RimEclipseView& activeView, cvf::Vec3d domainIntersectionPoint) const { QString text; if (m_rimFracture.isNull()) return text; auto* ellipseFractureTemplate = dynamic_cast<RimEllipseFractureTemplate*>(m_rimFracture->fractureTemplate()); auto* stimPlanTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate()); if (ellipseFractureTemplate) { text.append("Result value: CONDUCTIVITY "); text.append(QString::number(ellipseFractureTemplate->conductivity()) + "\n"); } else if (stimPlanTemplate) { const RigFractureCell* cell = getFractureCellAtDomainCoord(domainIntersectionPoint); if (cell) { QString resultNameFromColors = activeView.fractureColors()->uiResultName(); QString resultUnitFromColors = activeView.fractureColors()->unit(); double resultValue = stimPlanTemplate->resultValueAtIJ( resultNameFromColors, resultUnitFromColors, stimPlanTemplate->activeTimeStepIndex(), cell->getI(), cell->getJ()); QString resultValueText = QString("%1").arg(resultValue); QString iText = QString::number(cell->getI()); QString jText = QString::number(cell->getJ()); RimStimPlanColors* stimPlanColors = activeView.fractureColors(); if (stimPlanColors) { // Conductivity text.append("Result value: "); QString resultName = stimPlanTemplate->mapUiResultNameToFileResultName(stimPlanColors->uiResultName()); text.append(resultName + " "); text.append(resultValueText + "\n"); } // Cell index text.append("Cell Index: "); text.append(iText + ", " + jText + "\n"); } } return text; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseCase* RicPasteFeatureImpl::findEclipseCase(caf::PdmObjectHandle* objectHandle) { if (dynamic_cast<RimEclipseCase*>(objectHandle)) { return dynamic_cast<RimEclipseCase*>(objectHandle); } else if (dynamic_cast<RimEclipseView*>(objectHandle)) { RimEclipseView* reservoirView = dynamic_cast<RimEclipseView*>(objectHandle); return reservoirView->eclipseCase(); } return nullptr; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { this->updateUiIconFromToggleField(); if (&faultColor == changedField || &showFault == changedField) { RimEclipseView* reservoirView = NULL; this->firstAncestorOfType(reservoirView); if (reservoirView) { reservoirView->scheduleCreateDisplayModelAndRedraw(); } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseCase::removeResult(const QString& resultName) { size_t i; for (i = 0; i < reservoirViews().size(); i++) { RimEclipseView* reservoirView = reservoirViews()[i]; CVF_ASSERT(reservoirView); RimEclipseCellColors* result = reservoirView->cellResult; CVF_ASSERT(result); bool rebuildDisplayModel = false; // Set cell result variable to none if displaying if (result->resultVariable() == resultName) { result->setResultVariable(RimDefines::undefinedResultName()); result->loadResult(); rebuildDisplayModel = true; } std::list< caf::PdmPointer< RimEclipsePropertyFilter > >::iterator it; RimEclipsePropertyFilterCollection* propFilterCollection = reservoirView->propertyFilterCollection(); for (size_t filter = 0; filter < propFilterCollection->propertyFilters().size(); filter++) { RimEclipsePropertyFilter* propertyFilter = propFilterCollection->propertyFilters()[filter]; if (propertyFilter->resultDefinition->resultVariable() == resultName) { propertyFilter->resultDefinition->setResultVariable(RimDefines::undefinedResultName()); propertyFilter->resultDefinition->loadResult(); propertyFilter->setToDefaultValues(); rebuildDisplayModel = true; } } if (rebuildDisplayModel) { reservoirViews()[i]->createDisplayModelAndRedraw(); } // TODO // CellEdgeResults are not considered, as they do not support display of input properties yet } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool Rim3dOverlayInfoConfig::hasInvalidStatisticsCombination() { if (m_viewDef->propertyFilterCollection() && m_viewDef->propertyFilterCollection()->hasActiveDynamicFilters() && m_statisticsCellRange() == VISIBLE_CELLS && m_statisticsTimeRange() == ALL_TIMESTEPS ) { RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p()); if (!(eclipseView && eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())) // If isFlowDiagOrInjFlooding then skip this check as ALL_TIMESTEPS is overridden to CURRENT behind the scenes { return true; } } return false; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseCase::initAfterRead() { size_t j; for (j = 0; j < reservoirViews().size(); j++) { RimEclipseView* riv = reservoirViews()[j]; CVF_ASSERT(riv); riv->setEclipseCase(this); } if (caseUserDescription().isEmpty() && !caseName().isEmpty()) { caseUserDescription = caseName; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseView* RimEclipseCase::createAndAddReservoirView() { RimEclipseView* riv = new RimEclipseView(); riv->setEclipseCase(this); riv->cellEdgeResult()->resultVariable = "MULT"; riv->cellEdgeResult()->enableCellEdgeColors = false; caf::PdmDocument::updateUiIconStateRecursively(riv); size_t i = reservoirViews().size(); riv->name = QString("View %1").arg(i + 1); reservoirViews().push_back(riv); return riv; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiuRelativePermeabilityPlotUpdater::queryDataAndUpdatePlot(const RimEclipseView& eclipseView, size_t gridIndex, size_t gridLocalCellIndex, RiuRelativePermeabilityPlotPanel* plotPanel) { CVF_ASSERT(plotPanel); RimEclipseResultCase* eclipseResultCase = dynamic_cast<RimEclipseResultCase*>(eclipseView.eclipseCase()); RigEclipseCaseData* eclipseCaseData = eclipseResultCase ? eclipseResultCase->eclipseCaseData() : nullptr; if (eclipseResultCase && eclipseCaseData && eclipseResultCase->flowDiagSolverInterface()) { size_t activeCellIndex = CellLookupHelper::mapToActiveCellIndex(eclipseCaseData, gridIndex, gridLocalCellIndex); if (activeCellIndex != cvf::UNDEFINED_SIZE_T) { //cvf::Trace::show("Updating RelPerm plot for active cell index: %d", static_cast<int>(activeCellIndex)); std::vector<RigFlowDiagSolverInterface::RelPermCurve> relPermCurveArr = eclipseResultCase->flowDiagSolverInterface()->calculateRelPermCurves(activeCellIndex); // Make sure we load the results that we'll query below RigCaseCellResultsData* cellResultsData = eclipseCaseData->results(RiaDefines::MATRIX_MODEL); cellResultsData->findOrLoadScalarResult(RiaDefines::DYNAMIC_NATIVE, "SWAT"); cellResultsData->findOrLoadScalarResult(RiaDefines::DYNAMIC_NATIVE, "SGAS"); cellResultsData->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "SATNUM"); // Fetch SWAT and SGAS cell values for the selected cell const size_t timeStepIndex = static_cast<size_t>(eclipseView.currentTimeStep()); cvf::ref<RigResultAccessor> swatAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SWAT", RiaDefines::DYNAMIC_NATIVE); cvf::ref<RigResultAccessor> sgasAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SGAS", RiaDefines::DYNAMIC_NATIVE); cvf::ref<RigResultAccessor> satnumAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SATNUM", RiaDefines::STATIC_NATIVE); const double cellSWAT = swatAccessor.notNull() ? swatAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL; const double cellSGAS = sgasAccessor.notNull() ? sgasAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL; const double cellSATNUM = satnumAccessor.notNull() ? satnumAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL; //cvf::Trace::show("cellSWAT = %f cellSGAS = %f cellSATNUM = %f", cellSWAT, cellSGAS, cellSATNUM); QString cellRefText = constructCellReferenceText(eclipseCaseData, gridIndex, gridLocalCellIndex, cellSATNUM); QString caseName = eclipseResultCase->caseUserDescription; plotPanel->setPlotData(eclipseCaseData->unitsType(), relPermCurveArr, cellSWAT, cellSGAS, caseName, cellRefText); return true; } } return false; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicPasteEclipseViewsFeature::onActionTriggered(bool isChecked) { PdmObjectHandle* destinationObject = dynamic_cast<PdmObjectHandle*>(SelectionManager::instance()->selectedItem()); RimEclipseCase* eclipseCase = RicPasteFeatureImpl::findEclipseCase(destinationObject); assert(eclipseCase); PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); if (objectGroup.objects.size() == 0) return; std::vector<caf::PdmPointer<RimEclipseView> > eclipseViews; objectGroup.objectsByType(&eclipseViews); // Add cases to case group for (size_t i = 0; i < eclipseViews.size(); i++) { RimEclipseView* rimReservoirView = dynamic_cast<RimEclipseView*>(eclipseViews[i]->xmlCapability()->copyByXmlSerialization(PdmDefaultObjectFactory::instance())); CVF_ASSERT(rimReservoirView); QString nameOfCopy = QString("Copy of ") + rimReservoirView->name; rimReservoirView->name = nameOfCopy; eclipseCase->reservoirViews().push_back(rimReservoirView); rimReservoirView->setEclipseCase(eclipseCase); // Resolve references after reservoir view has been inserted into Rim structures // Intersections referencing a well path/ simulation well requires this // TODO: initAfterReadRecursively can probably be removed rimReservoirView->initAfterReadRecursively(); rimReservoirView->resolveReferencesRecursively(); rimReservoirView->loadDataAndUpdate(); caf::PdmDocument::updateUiIconStateRecursively(rimReservoirView); eclipseCase->updateConnectedEditors(); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<RivCrossSectionHexGridIntf> RivCrossSectionPartMgr::createHexGridInterface() { RimEclipseView* eclipseView; m_rimCrossSection->firstAnchestorOrThisOfType(eclipseView); if (eclipseView) { RigMainGrid* grid = NULL; grid = eclipseView->eclipseCase()->reservoirData()->mainGrid(); return new RivEclipseCrossSectionGrid(grid, eclipseView->currentActiveCellInfo(), m_rimCrossSection->showInactiveCells()); } RimGeoMechView* geoView; m_rimCrossSection->firstAnchestorOrThisOfType(geoView); if (geoView) { RigFemPart* femPart = geoView->geoMechCase()->geoMechData()->femParts()->part(0); return new RivFemCrossSectionGrid(femPart); } return NULL; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellInView::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { RimEclipseView* reservoirView = nullptr; this->firstAncestorOrThisOfType(reservoirView); if (reservoirView) { if (&showWellLabel == changedField || &showWellHead == changedField || &showWellPipe == changedField || &showWellSpheres == changedField || &wellPipeColor == changedField) { reservoirView->scheduleCreateDisplayModelAndRedraw(); schedule2dIntersectionViewUpdate(); } else if (&showWell == changedField || &showWellCells == changedField || &showWellCellFence == changedField) { reservoirView->scheduleGeometryRegen(VISIBLE_WELL_CELLS); reservoirView->scheduleCreateDisplayModelAndRedraw(); schedule2dIntersectionViewUpdate(); } else if ( &pipeScaleFactor == changedField || &wellHeadScaleFactor == changedField) { reservoirView->scheduleSimWellGeometryRegen(); reservoirView->scheduleCreateDisplayModelAndRedraw(); schedule2dIntersectionViewUpdate(); } } RimSimWellInViewCollection* wellColl = nullptr; this->firstAncestorOrThisOfType(wellColl); if (wellColl) { wellColl->updateStateForVisibilityCheckboxes(); RiuMainWindow::instance()->refreshDrawStyleActions(); } if (changedField == &wellPipeColor) { RimSimWellInViewCollection::updateWellAllocationPlots(); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicImportInputEclipseCaseOpmFeature::onActionTriggered(bool isChecked) { RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory("INPUT_FILES"); QString fileName = QFileDialog::getOpenFileName(RiuMainWindow::instance(), "Import Eclipse Input file", defaultDir, "Eclipse Input Files (*.GRDECL);;All Files (*.*)"); if (fileName.isEmpty()) return; // Remember the path to next time app->setLastUsedDialogDirectory("INPUT_FILES", QFileInfo(fileName).absolutePath()); RimProject* proj = app->project(); RimEclipseCaseCollection* analysisModels = proj->activeOilField() ? proj->activeOilField()->analysisModels() : NULL; if (analysisModels) { // This code originates from RiaApplication::openInputEclipseCaseFromFileNames RimEclipseInputCaseOpm* rimInputReservoir = new RimEclipseInputCaseOpm(); proj->assignCaseIdToCase(rimInputReservoir); rimInputReservoir->importNewEclipseGridAndProperties(fileName); analysisModels->cases.push_back(rimInputReservoir); RimEclipseView* riv = rimInputReservoir->createAndAddReservoirView(); riv->cellResult()->setResultType(RimDefines::INPUT_PROPERTY); riv->hasUserRequestedAnimation = true; riv->loadDataAndUpdate(); if (!riv->cellResult()->hasResult()) { riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } analysisModels->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup) { RimProject* proj = RiaApplication::instance()->project(); CVF_ASSERT(proj); std::vector<RimEclipseResultCase*> resultCases; for (size_t i = 0; i < objectGroup.objects.size(); i++) { RimEclipseResultCase* eclCase = dynamic_cast<RimEclipseResultCase*>(objectGroup.objects[i]); if (eclCase) { RimEclipseResultCase* eclCaseCopy = dynamic_cast<RimEclipseResultCase*>(eclCase->copyByXmlSerialization(PdmDefaultObjectFactory::instance())); resultCases.push_back(eclCaseCopy); } } if (resultCases.size() == 0) { return; } RimEclipseResultCase* mainResultCase = NULL; std::vector< std::vector<int> > mainCaseGridDimensions; // Read out main grid and main grid dimensions if present in case group if (gridCaseGroup->mainCase()) { mainResultCase = dynamic_cast<RimEclipseResultCase*>(gridCaseGroup->mainCase()); CVF_ASSERT(mainResultCase); mainResultCase->readGridDimensions(mainCaseGridDimensions); } std::vector<RimEclipseResultCase*> insertedCases; // Add cases to case group for (size_t i = 0; i < resultCases.size(); i++) { RimEclipseResultCase* rimResultReservoir = resultCases[i]; proj->assignCaseIdToCase(rimResultReservoir); if (gridCaseGroup->contains(rimResultReservoir)) { continue; } insertedCases.push_back(rimResultReservoir); } // Load stuff for (size_t i = 0; i < insertedCases.size(); i++) { RimEclipseResultCase* rimResultReservoir = insertedCases[i]; if (!mainResultCase) { rimResultReservoir->openEclipseGridFile(); rimResultReservoir->readGridDimensions(mainCaseGridDimensions); mainResultCase = rimResultReservoir; } else { std::vector< std::vector<int> > caseGridDimensions; rimResultReservoir->readGridDimensions(caseGridDimensions); bool identicalGrid = RigGridManager::isGridDimensionsEqual(mainCaseGridDimensions, caseGridDimensions); if (!identicalGrid) { continue; } if (!rimResultReservoir->openAndReadActiveCellData(mainResultCase->reservoirData())) { CVF_ASSERT(false); } } RimOilField* activeOilField = proj ? proj->activeOilField() : NULL; RimEclipseCaseCollection* analysisModels = (activeOilField) ? activeOilField->analysisModels() : NULL; if (analysisModels) analysisModels->insertCaseInCaseGroup(gridCaseGroup, rimResultReservoir); caf::PdmDocument::updateUiIconStateRecursively(rimResultReservoir); gridCaseGroup->updateConnectedEditors(); for (size_t rvIdx = 0; rvIdx < rimResultReservoir->reservoirViews.size(); rvIdx++) { RimEclipseView* riv = rimResultReservoir->reservoirViews()[rvIdx]; riv->loadDataAndUpdate(); } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicfExportSimWellFractureCompletions::execute() { RimProject* project = RiaApplication::instance()->project(); RicExportCompletionDataSettingsUi* exportSettings = project->dialogData()->exportCompletionData(); exportSettings->timeStep = m_timeStep; exportSettings->fileSplit = m_fileSplit; exportSettings->compdatExport = m_compdatExport; { bool foundCase = false; for (RimEclipseCase* c : RiaApplication::instance()->project()->activeOilField()->analysisModels->cases()) { if (c->caseId() == m_caseId()) { exportSettings->caseToApply = c; foundCase = true; break; } } if (!foundCase) { RiaLogging::error(QString("exportSimWellCompletions: Could not find case with ID %1").arg(m_caseId())); return; } } QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::COMPLETIONS); if (exportFolder.isNull()) { exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("completions"); } exportSettings->folder = exportFolder; std::vector<RimEclipseView*> views; for (Rim3dView* v : exportSettings->caseToApply->views()) { RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>(v); if (eclipseView && eclipseView->name() == m_viewName()) { views.push_back(eclipseView); } } if (views.empty()) { RiaLogging::error(QString("exportSimWellCompletions: Could not find any views named \"%1\" in the case with ID %2").arg(m_viewName).arg(m_caseId())); return; } std::vector<RimSimWellInView*> simWells; if (m_simWellNames().empty()) { for (RimEclipseView* view : views) { for (auto simWell : view->wellCollection()->wells) { if (simWell->showWell()) { simWells.push_back(simWell); } } } } else { for (const QString& wellPathName : m_simWellNames()) { for (RimEclipseView* view : views) { RimSimWellInView* simWell = view->wellCollection()->findWell(wellPathName); if (simWell) { simWells.push_back(simWell); } else { RiaLogging::warning(QString("exportSimWellCompletions: Could not find well with name %1 in view \"%2\" on case with ID %2").arg(wellPathName).arg(m_viewName).arg(m_caseId())); } } } } std::vector<RimWellPath*> wellPaths; RicWellPathExportCompletionDataFeatureImpl::exportCompletions(wellPaths, simWells, *exportSettings); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model, const RimEclipseView& eclView) { if (!m_rimFracture->isChecked() || !eclView.fractureColors()->isChecked()) return; if (!m_rimFracture->fractureTemplate()) return; m_visibleFracturePolygons.clear(); double characteristicCellSize = eclView.ownerCase()->characteristicCellSize(); cvf::Collection<cvf::Part> parts; RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate()); if (stimPlanFracTemplate) { if (eclView.fractureColors()->stimPlanResultColorType() == RimStimPlanColors::SINGLE_ELEMENT_COLOR) { auto part = createStimPlanElementColorSurfacePart(eclView); if (part.notNull()) parts.push_back(part.p()); } else { auto part = createStimPlanColorInterpolatedSurfacePart(eclView); if (part.notNull()) parts.push_back(part.p()); } if (eclView.fractureColors()->showStimPlanMesh()) { auto part = createStimPlanMeshPart(eclView); if (part.notNull()) parts.push_back(part.p()); } } else { auto part = createEllipseSurfacePart(eclView); if (part.notNull()) parts.push_back(part.p()); } double distanceToCenterLine = 1.0; { RimWellPathCollection* wellPathColl = nullptr; m_rimFracture->firstAncestorOrThisOfType(wellPathColl); if (wellPathColl) { distanceToCenterLine = wellPathColl->wellPathRadiusScaleFactor() * characteristicCellSize; } RimSimWellInView* simWell = nullptr; m_rimFracture->firstAncestorOrThisOfType(simWell); if (simWell) { distanceToCenterLine = simWell->pipeRadius(); } } // Make sure the distance is slightly smaller than the pipe radius to make the pipe is visible through the fracture distanceToCenterLine *= 0.1; if (distanceToCenterLine < 0.03) { distanceToCenterLine = 0.03; } auto fractureMatrix = m_rimFracture->transformMatrix(); if (m_rimFracture->fractureTemplate() && m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH) { cvf::Vec3d partTranslation = distanceToCenterLine * cvf::Vec3d(fractureMatrix.col(2)); for (auto& part : parts) { RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, part.p(), partTranslation); } } else { for (auto& part : parts) { model->addPart(part.p()); } } if (m_rimFracture->fractureTemplate()) { // Position the containment mask outside the fracture parts // Always duplicate the containment mask parts { auto maskOfFractureAreasOutsideGrid = createMaskOfFractureOutsideGrid(eclView); if (maskOfFractureAreasOutsideGrid.notNull()) { double scaleFactor = 0.03; if (m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH) { scaleFactor = 2 * distanceToCenterLine; } cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2)); RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation( model, maskOfFractureAreasOutsideGrid.p(), partTranslation); } } if (m_rimFracture->fractureTemplate()->fractureContainment()->isEnabled()) { // Position the containment mask outside the fracture parts // Always duplicate the containment mask parts auto containmentMask = createContainmentMaskPart(eclView); if (containmentMask.notNull()) { double scaleFactor = 0.03; if (m_rimFracture->fractureTemplate() && m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH) { scaleFactor = 2 * distanceToCenterLine; } cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2)); RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, containmentMask.p(), partTranslation); } } } appendFracturePerforationLengthParts(eclView, model); }
//-------------------------------------------------------------------------------------------------- /// Create mask for the parts outside the grid cells of the reservoir //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::Part> RivWellFracturePartMgr::createMaskOfFractureOutsideGrid(const RimEclipseView& activeView) { cvf::Mat4d frMx = m_rimFracture->transformMatrix(); std::vector<cvf::Vec3f> maskTriangles; auto displCoordTrans = activeView.displayCoordTransform(); for (const auto& visibleFracturePolygon : m_visibleFracturePolygons) { std::vector<cvf::Vec3d> borderOfFractureCellPolygonLocalCsd; cvf::BoundingBox frBBox; for (const auto& pv : visibleFracturePolygon) { cvf::Vec3d pvd(pv); borderOfFractureCellPolygonLocalCsd.push_back(pvd); pvd.transformPoint(frMx); frBBox.add(pvd); } std::vector<std::vector<cvf::Vec3d>> clippedPolygons; std::vector<size_t> cellCandidates; activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates); if (cellCandidates.empty()) { clippedPolygons.push_back(borderOfFractureCellPolygonLocalCsd); } else { // Check if fracture polygon is fully inside the grid bool allPointsInsideGrid = true; for (const auto& v : borderOfFractureCellPolygonLocalCsd) { auto pointInDomainCoords = v.getTransformedPoint(frMx); bool pointInsideGrid = false; RigMainGrid* mainGrid = activeView.mainGrid(); std::array<cvf::Vec3d, 8> corners; for (size_t cellIndex : cellCandidates) { mainGrid->cellCornerVertices(cellIndex, corners.data()); if (RigHexIntersectionTools::isPointInCell(pointInDomainCoords, corners.data())) { pointInsideGrid = true; break; } } if (!pointInsideGrid) { allPointsInsideGrid = false; break; } } if (!allPointsInsideGrid) { std::vector<std::vector<cvf::Vec3d>> allEclCellPolygons; for (size_t resCellIdx : cellCandidates) { // Calculate Eclipse cell intersection with fracture plane std::array<cvf::Vec3d, 8> corners; activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data()); std::vector<std::vector<cvf::Vec3d>> eclCellPolygons; bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons); if (!hasIntersection || eclCellPolygons.empty()) continue; // Transform eclCell - plane intersection onto fracture cvf::Mat4d invertedTransformMatrix = frMx.getInverted(); for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons) { for (cvf::Vec3d& v : eclCellPolygon) { v.transformPoint(invertedTransformMatrix); } allEclCellPolygons.push_back(eclCellPolygon); } } { std::vector<std::vector<cvf::Vec3d>> polys = RigCellGeometryTools::subtractPolygons(borderOfFractureCellPolygonLocalCsd, allEclCellPolygons); for (const auto& polygon : polys) { clippedPolygons.push_back(polygon); } } } } for (auto& clippedPolygon : clippedPolygons) { for (auto& point : clippedPolygon) { point.transformPoint(frMx); } } // Create triangles from the clipped polygons cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2)); for (const auto& clippedPolygon : clippedPolygons) { cvf::EarClipTesselator tess; tess.setNormal(fractureNormal); cvf::Vec3dArray cvfNodes(clippedPolygon); tess.setGlobalNodeArray(cvfNodes); std::vector<size_t> polyIndexes; for (size_t idx = 0; idx < clippedPolygon.size(); ++idx) polyIndexes.push_back(idx); tess.setPolygonIndices(polyIndexes); std::vector<size_t> triangleIndices; tess.calculateTriangles(&triangleIndices); for (size_t idx : triangleIndices) { maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx]))); } } } if (maskTriangles.size() >= 3) { cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo; maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles)); cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES); primitives->setIndexCount(maskTriangles.size()); maskTriangleGeo->addPrimitiveSet(primitives.p()); maskTriangleGeo->computeNormals(); cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart"); containmentMaskPart->setDrawable(maskTriangleGeo.p()); containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture)); cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY)); caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE); cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect(); containmentMaskPart->setEffect(eff.p()); return containmentMaskPart; } return nullptr; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::Part> RivWellFracturePartMgr::createContainmentMaskPart(const RimEclipseView& activeView) { std::vector<cvf::Vec3d> borderPolygonLocalCS = fractureBorderPolygon(); cvf::Mat4d frMx = m_rimFracture->transformMatrix(); cvf::BoundingBox frBBox; std::vector<cvf::Vec3d> borderPolygonLocalCsd; for (const auto& pv : borderPolygonLocalCS) { cvf::Vec3d pvd(pv); borderPolygonLocalCsd.push_back(pvd); pvd.transformPoint(frMx); frBBox.add(pvd); } std::vector<size_t> cellCandidates; activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates); auto displCoordTrans = activeView.displayCoordTransform(); std::vector<cvf::Vec3f> maskTriangles; RimEclipseCase* eclipseCase = nullptr; activeView.firstAncestorOrThisOfType(eclipseCase); auto reservoirCellIndicesOpenForFlow = RimFractureContainmentTools::reservoirCellIndicesOpenForFlow(eclipseCase, m_rimFracture); for (size_t resCellIdx : cellCandidates) { if (!m_rimFracture->isEclipseCellOpenForFlow(activeView.mainGrid(), reservoirCellIndicesOpenForFlow, resCellIdx)) { // Calculate Eclipse cell intersection with fracture plane std::array<cvf::Vec3d, 8> corners; activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data()); std::vector<std::vector<cvf::Vec3d>> eclCellPolygons; bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons); if (!hasIntersection || eclCellPolygons.empty()) continue; // Transform eclCell - plane intersection onto fracture cvf::Mat4d invertedTransformMatrix = frMx.getInverted(); for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons) { for (cvf::Vec3d& v : eclCellPolygon) { v.transformPoint(invertedTransformMatrix); } } cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2)); for (const std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons) { // Clip Eclipse cell polygon with fracture border std::vector<std::vector<cvf::Vec3d>> clippedPolygons = RigCellGeometryTools::intersectPolygons(eclCellPolygon, borderPolygonLocalCsd); for (auto& clippedPolygon : clippedPolygons) { for (auto& v : clippedPolygon) { v.transformPoint(frMx); } } // Create triangles from the clipped polygons for (auto& clippedPolygon : clippedPolygons) { cvf::EarClipTesselator tess; tess.setNormal(fractureNormal); cvf::Vec3dArray cvfNodes(clippedPolygon); tess.setGlobalNodeArray(cvfNodes); std::vector<size_t> polyIndexes; for (size_t idx = 0; idx < clippedPolygon.size(); ++idx) polyIndexes.push_back(idx); tess.setPolygonIndices(polyIndexes); std::vector<size_t> triangleIndices; tess.calculateTriangles(&triangleIndices); for (size_t idx : triangleIndices) { maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx]))); } } } } } if (maskTriangles.size() >= 3) { cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo; maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles)); cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES); primitives->setIndexCount(maskTriangles.size()); maskTriangleGeo->addPrimitiveSet(primitives.p()); maskTriangleGeo->computeNormals(); cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart"); containmentMaskPart->setDrawable(maskTriangleGeo.p()); containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture)); cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY)); caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE); cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect(); containmentMaskPart->setEffect(eff.p()); return containmentMaskPart; } return nullptr; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanElementColorSurfacePart(const RimEclipseView& activeView) { CVF_ASSERT(m_rimFracture); RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate()); CVF_ASSERT(stimPlanFracTemplate); if (!stimPlanFracTemplate->fractureGrid()) return nullptr; auto displayCoordTransform = activeView.displayCoordTransform(); if (displayCoordTransform.isNull()) return nullptr; std::vector<cvf::Vec3f> stimPlanMeshVertices; cvf::ref<cvf::Vec2fArray> textureCoords = new cvf::Vec2fArray; const cvf::ScalarMapper* scalarMapper = nullptr; { std::vector<RigFractureCell> stimPlanCells = stimPlanFracTemplate->fractureGrid()->fractureCells(); RimRegularLegendConfig* legendConfig = nullptr; if (activeView.fractureColors() && activeView.fractureColors()->isChecked() && activeView.fractureColors()->activeLegend()) { legendConfig = activeView.fractureColors()->activeLegend(); scalarMapper = legendConfig->scalarMapper(); QString resultNameFromColors = activeView.fractureColors()->uiResultName(); QString resultUnitFromColors = activeView.fractureColors()->unit(); std::vector<double> prCellResults = stimPlanFracTemplate->fractureGridResults( resultNameFromColors, resultUnitFromColors, stimPlanFracTemplate->activeTimeStepIndex()); textureCoords->reserve(prCellResults.size() * 4); for (size_t cIdx = 0; cIdx < stimPlanCells.size(); ++cIdx) { if (prCellResults[cIdx] > 1e-7) { const RigFractureCell& stimPlanCell = stimPlanCells[cIdx]; std::vector<cvf::Vec3d> stimPlanCellPolygon = stimPlanCell.getPolygon(); for (const cvf::Vec3d& cellCorner : stimPlanCellPolygon) { stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner)); textureCoords->add(scalarMapper->mapToTextureCoord(prCellResults[cIdx])); } } } textureCoords->squeeze(); } else { for (const auto& stimPlanCell : stimPlanCells) { for (const auto& cellCorner : stimPlanCell.getPolygon()) { stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner)); } } } } if (stimPlanMeshVertices.empty()) { return nullptr; } cvf::Mat4d fractureXf = m_rimFracture->transformMatrix(); std::vector<cvf::Vec3f> nodeDisplayCoords = transformToFractureDisplayCoords(stimPlanMeshVertices, fractureXf, *displayCoordTransform); std::vector<cvf::uint> triIndicesToInclude; size_t cellCount = stimPlanMeshVertices.size() / 4; for (cvf::uint i = 0; i < cellCount; i++) { triIndicesToInclude.push_back(i * 4 + 0); triIndicesToInclude.push_back(i * 4 + 1); triIndicesToInclude.push_back(i * 4 + 2); triIndicesToInclude.push_back(i * 4 + 0); triIndicesToInclude.push_back(i * 4 + 2); triIndicesToInclude.push_back(i * 4 + 3); } // Show selected result on the surface geometry and filter out triangles that have result values near 0 if (scalarMapper) { if (triIndicesToInclude.empty()) { return nullptr; } cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triIndicesToInclude, nodeDisplayCoords); geo->setTextureCoordArray(textureCoords.p()); cvf::ref<cvf::Part> surfacePart = createScalarMapperPart(geo.p(), scalarMapper, m_rimFracture, activeView.isLightingDisabled()); return surfacePart; } else { // No result is mapped, show the entire StimPlan surface with default color return createSingleColorSurfacePart(triIndicesToInclude, nodeDisplayCoords, activeView.fractureColors()->defaultColor()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanColorInterpolatedSurfacePart(const RimEclipseView& activeView) { CVF_ASSERT(m_rimFracture); RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate()); CVF_ASSERT(stimPlanFracTemplate); auto displayCoordTransform = activeView.displayCoordTransform(); if (displayCoordTransform.isNull()) return nullptr; // Note that the filtering and result mapping code below couples closely to the triangulation and vertex layout returned by // triangleGeometry() If this ever changes, the entire code must be revisited std::vector<cvf::uint> triangleIndices; std::vector<cvf::Vec3f> nodeDisplayCoords; { std::vector<cvf::Vec3f> nodeCoords; stimPlanFracTemplate->fractureTriangleGeometry(&nodeCoords, &triangleIndices); if (triangleIndices.empty() || nodeCoords.empty()) { return nullptr; } cvf::Mat4d fractureXf = m_rimFracture->transformMatrix(); nodeDisplayCoords = transformToFractureDisplayCoords(nodeCoords, fractureXf, *displayCoordTransform); } RimRegularLegendConfig* legendConfig = nullptr; if (activeView.fractureColors() && activeView.fractureColors()->isChecked()) { legendConfig = activeView.fractureColors()->activeLegend(); } // Show selected result on the surface geometry and filter out triangles that have result values near 0 if (legendConfig) { // Construct array with per node result values that correspond to the node coordinates of the triangle mesh // Since some time steps don't have result vales, we initialize the array to well known values before populating it std::vector<double> perNodeResultValues(nodeDisplayCoords.size(), HUGE_VAL); { size_t idx = 0; const std::vector<std::vector<double>> dataToPlot = stimPlanFracTemplate->resultValues(activeView.fractureColors()->uiResultName(), activeView.fractureColors()->unit(), stimPlanFracTemplate->activeTimeStepIndex()); for (const std::vector<double>& dataAtY : dataToPlot) { for (double val : dataAtY) { perNodeResultValues[idx++] = val; } } } CVF_ASSERT(perNodeResultValues.size() == nodeDisplayCoords.size()); std::vector<cvf::uint> triIndicesToInclude; for (size_t i = 0; i < triangleIndices.size(); i += 6) { // Include all triangles where at least one of the vertices in the triangle pair has a value above threshold bool includeThisTrianglePair = false; for (size_t j = 0; j < 6; j++) { if (perNodeResultValues[triangleIndices[i + j]] > 1e-7) { includeThisTrianglePair = true; } } if (includeThisTrianglePair) { for (size_t j = 0; j < 6; j++) { triIndicesToInclude.push_back(triangleIndices[i + j]); } } } if (triIndicesToInclude.empty()) { return nullptr; } cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triIndicesToInclude, nodeDisplayCoords); const cvf::ScalarMapper* scalarMapper = legendConfig->scalarMapper(); CVF_ASSERT(scalarMapper); cvf::ref<cvf::Vec2fArray> textureCoords = new cvf::Vec2fArray(nodeDisplayCoords.size()); textureCoords->setAll(cvf::Vec2f(0.5f, 1.0f)); for (size_t i = 0; i < perNodeResultValues.size(); i++) { const double val = perNodeResultValues[i]; if (val < HUGE_VAL && val == val) { textureCoords->set(i, scalarMapper->mapToTextureCoord(val)); } } geo->setTextureCoordArray(textureCoords.p()); cvf::ref<cvf::Part> surfacePart = createScalarMapperPart(geo.p(), scalarMapper, m_rimFracture, activeView.isLightingDisabled()); return surfacePart; } else { // No result is mapped, show the entire StimPlan surface with default color return createSingleColorSurfacePart(triangleIndices, nodeDisplayCoords, activeView.fractureColors()->defaultColor()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref<cvf::Part> RivWellFracturePartMgr::createEllipseSurfacePart(const RimEclipseView& activeView) { auto displayCoordTransform = activeView.displayCoordTransform(); if (displayCoordTransform.isNull()) return nullptr; if (m_rimFracture) { std::vector<cvf::uint> triangleIndices; std::vector<cvf::Vec3f> nodeDisplayCoords; { std::vector<cvf::Vec3f> nodeCoords; m_rimFracture->fractureTemplate()->fractureTriangleGeometry(&nodeCoords, &triangleIndices); cvf::Mat4d fractureXf = m_rimFracture->transformMatrix(); nodeDisplayCoords = transformToFractureDisplayCoords(nodeCoords, fractureXf, *displayCoordTransform); } if (triangleIndices.empty() || nodeDisplayCoords.empty()) { return nullptr; } cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triangleIndices, nodeDisplayCoords); CVF_ASSERT(geo.notNull()); cvf::ref<cvf::Part> surfacePart = new cvf::Part(0, "FractureSurfacePart_ellipse"); surfacePart->setDrawable(geo.p()); surfacePart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture)); cvf::Color4f fractureColor = cvf::Color4f(activeView.fractureColors()->defaultColor()); RimRegularLegendConfig* legendConfig = nullptr; if (activeView.fractureColors() && activeView.fractureColors()->isChecked()) { legendConfig = activeView.fractureColors()->activeLegend(); } if (legendConfig && legendConfig->scalarMapper()) { cvf::Color3ub resultColor = cvf::Color3ub(RiaColorTables::undefinedCellColor()); if (activeView.fractureColors()->uiResultName() == RiaDefines::conductivityResultName()) { RimEllipseFractureTemplate* ellipseFractureTemplate = dynamic_cast<RimEllipseFractureTemplate*>(m_rimFracture->fractureTemplate()); if (ellipseFractureTemplate) { double conductivity = ellipseFractureTemplate->conductivity(); resultColor = legendConfig->scalarMapper()->mapToColor(conductivity); } } fractureColor.set(cvf::Color3f::fromByteColor(resultColor.r(), resultColor.g(), resultColor.b())); } caf::SurfaceEffectGenerator surfaceGen(fractureColor, caf::PO_1); cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect(); surfacePart->setEffect(eff.p()); return surfacePart; } return nullptr; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimEclipseCellColors* cellResultColors) { CVF_ASSERT(cellResultColors); updateNNCColors(cellResultColors); RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultColors->porosityModel()); RimEclipseView* eclipseView = cellResultColors->reservoirView(); RigCaseData* eclipseCase = eclipseView->eclipseCase()->reservoirData(); // Faults if (m_nativeFaultFaces.notNull()) { if (cellResultColors->isTernarySaturationSelected()) { RivTernaryTextureCoordsCreator texturer(cellResultColors, cellResultColors->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), m_nativeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); const RivTernaryScalarMapper* mapper = cellResultColors->ternaryLegendConfig()->scalarMapper(); RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled()); } else { RivTextureCoordsCreator texturer(cellResultColors, timeStepIndex, m_grid->gridIndex(), m_nativeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { return; } texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); const cvf::ScalarMapper* mapper = cellResultColors->legendConfig()->scalarMapper(); RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled()); } } if (m_oppositeFaultFaces.notNull()) { if (cellResultColors->isTernarySaturationSelected()) { RivTernaryTextureCoordsCreator texturer(cellResultColors, cellResultColors->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), m_oppositeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); const RivTernaryScalarMapper* mapper = cellResultColors->ternaryLegendConfig()->scalarMapper(); RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled()); } else { RivTextureCoordsCreator texturer(cellResultColors, timeStepIndex, m_grid->gridIndex(), m_oppositeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { return; } texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); const cvf::ScalarMapper* mapper = cellResultColors->legendConfig()->scalarMapper(); RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled()); } } }