//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigMainGrid::calculateFaults(const RigActiveCellInfo* activeCellInfo) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(m_cells.size()); // Spread fault idx'es on the cells from the faults for (size_t fIdx = 0 ; fIdx < m_faults.size(); ++fIdx) { m_faults[fIdx]->accumulateFaultsPrCell(m_faultsPrCellAcc.p(), static_cast<int>(fIdx)); } // Find the geometrical faults that is in addition: Has no user defined (eclipse) fault assigned. // Separate the grid faults that has an inactive cell as member RigFault* unNamedFault = new RigFault; unNamedFault->setName(RimDefines::undefinedGridFaultName()); int unNamedFaultIdx = static_cast<int>(m_faults.size()); m_faults.push_back(unNamedFault); RigFault* unNamedFaultWithInactive = new RigFault; unNamedFaultWithInactive->setName(RimDefines::undefinedGridFaultWithInactiveName()); int unNamedFaultWithInactiveIdx = static_cast<int>(m_faults.size()); m_faults.push_back(unNamedFaultWithInactive); const std::vector<cvf::Vec3d>& vxs = m_mainGrid->nodes(); for (int gcIdx = 0 ; gcIdx < static_cast<int>(m_cells.size()); ++gcIdx) { if ( m_cells[gcIdx].isInvalid()) { continue; } size_t neighborReservoirCellIdx; size_t neighborGridCellIdx; size_t i, j, k; RigGridBase* hostGrid = NULL; bool firstNO_FAULTFaceForCell = true; bool isCellActive = true; for (char faceIdx = 0; faceIdx < 6; ++faceIdx) { cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::FaceType(faceIdx); // For faces that has no used defined Fault assigned: if (m_faultsPrCellAcc->faultIdx(gcIdx, face) == RigFaultsPrCellAccumulator::NO_FAULT) { // Find neighbor cell if (firstNO_FAULTFaceForCell) // To avoid doing this for every face, and only when detecting a NO_FAULT { hostGrid = m_cells[gcIdx].hostGrid(); hostGrid->ijkFromCellIndex(m_cells[gcIdx].gridLocalCellIndex(), &i,&j, &k); isCellActive = activeCellInfo->isActive(gcIdx); firstNO_FAULTFaceForCell = false; } if(!hostGrid->cellIJKNeighbor(i, j, k, face, &neighborGridCellIdx)) { continue; } neighborReservoirCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); if (m_cells[neighborReservoirCellIdx].isInvalid()) { continue; } bool isNeighborCellActive = activeCellInfo->isActive(neighborReservoirCellIdx); double tolerance = 1e-6; caf::SizeTArray4 faceIdxs; m_cells[gcIdx].faceIndices(face, &faceIdxs); caf::SizeTArray4 nbFaceIdxs; m_cells[neighborReservoirCellIdx].faceIndices(StructGridInterface::oppositeFace(face), &nbFaceIdxs); bool sharedFaceVertices = true; if (sharedFaceVertices && vxs[faceIdxs[0]].pointDistance(vxs[nbFaceIdxs[0]]) > tolerance ) sharedFaceVertices = false; if (sharedFaceVertices && vxs[faceIdxs[1]].pointDistance(vxs[nbFaceIdxs[3]]) > tolerance ) sharedFaceVertices = false; if (sharedFaceVertices && vxs[faceIdxs[2]].pointDistance(vxs[nbFaceIdxs[2]]) > tolerance ) sharedFaceVertices = false; if (sharedFaceVertices && vxs[faceIdxs[3]].pointDistance(vxs[nbFaceIdxs[1]]) > tolerance ) sharedFaceVertices = false; if (sharedFaceVertices) { continue; } // To avoid doing this calculation for the opposite face int faultIdx = unNamedFaultIdx; if (!(isCellActive && isNeighborCellActive)) faultIdx = unNamedFaultWithInactiveIdx; m_faultsPrCellAcc->setFaultIdx(gcIdx, face, faultIdx); m_faultsPrCellAcc->setFaultIdx(neighborReservoirCellIdx, StructGridInterface::oppositeFace(face), faultIdx); // Add as fault face only if the grid index is less than the neighbors if (static_cast<size_t>(gcIdx) < neighborReservoirCellIdx) { RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborReservoirCellIdx); if(isCellActive && isNeighborCellActive) { unNamedFault->faultFaces().push_back(ff); } else { unNamedFaultWithInactive->faultFaces().push_back(ff); } } else { CVF_FAIL_MSG("Found fault with global neighbor index less than the native index. "); // Should never occur. because we flag the opposite face in the faultsPrCellAcc } } } } distributeNNCsToFaults(); }
//-------------------------------------------------------------------------------------------------- /// The file pointer is pointing at the line following the FAULTS keyword. /// Parse content of this keyword until end of file or /// end of keyword when a single line with '/' is found //-------------------------------------------------------------------------------------------------- void RifEclipseInputFileTools::readFaults(QFile &data, qint64 filePos, cvf::Collection<RigFault>* faults, bool* isEditKeywordDetected) { if (!data.seek(filePos)) { return; } // qDebug() << "Reading faults from\n " << data.fileName(); RigFault* fault = nullptr; do { QString line = data.readLine(); line = line.trimmed(); if (line.startsWith("--", Qt::CaseInsensitive)) { // Skip comment lines continue; } else if (line.startsWith("/", Qt::CaseInsensitive)) { // Detected end of keyword data section return; } else if (line.startsWith(editKeyword, Qt::CaseInsensitive)) { // End parsing when edit keyword is detected if (isEditKeywordDetected) { *isEditKeywordDetected = true; } return; } // Replace tab with space to be able to split the string using space as splitter line.replace("\t", " "); // Remove character ' used to mark start and end of fault name, possibly also around face definition; 'I+' line.remove("'"); QStringList entries = line.split(" ", QString::SkipEmptyParts); if (entries.size() < 8) { continue; } QString name = entries[0]; int i1, i2, j1, j2, k1, k2; i1 = entries[1].toInt(); i2 = entries[2].toInt(); j1 = entries[3].toInt(); j2 = entries[4].toInt(); k1 = entries[5].toInt(); k2 = entries[6].toInt(); QString faceString = entries[7]; cvf::StructGridInterface::FaceEnum cellFaceEnum = RifEclipseInputFileTools::faceEnumFromText(faceString); // Adjust from 1-based to 0-based cell indices // Guard against invalid cell ranges by limiting lowest possible range value to zero cvf::CellRange cellrange(CVF_MAX(i1 - 1, 0), CVF_MAX(j1 - 1, 0), CVF_MAX(k1 - 1, 0), CVF_MAX(i2 - 1, 0), CVF_MAX(j2 - 1, 0), CVF_MAX(k2 - 1, 0)); if (!(fault && fault->name() == name)) { if (findFaultByName(*faults, name) == cvf::UNDEFINED_SIZE_T) { RigFault* newFault = new RigFault; newFault->setName(name); faults->push_back(newFault); } size_t faultIndex = findFaultByName(*faults, name); if (faultIndex == cvf::UNDEFINED_SIZE_T) { CVF_ASSERT(faultIndex != cvf::UNDEFINED_SIZE_T); continue; } fault = faults->at(faultIndex); } CVF_ASSERT(fault); fault->addCellRangeForFace(cellFaceEnum, cellrange); } while (!data.atEnd()); }