///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) Statoil ASA // Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiuFemResultTextBuilder.h" #include "RigGeoMechCaseData.h" #include "RimGeoMechView.h" #include "RimGeoMechCase.h" #include "RigFemPartCollection.h" #include "RigFemPart.h" #include "RigFemPartGrid.h" #include "RimGeoMechCellColors.h" #include "RigFemPartResultsCollection.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuFemResultTextBuilder::RiuFemResultTextBuilder(RimGeoMechView* reservoirView, int gridIndex, int cellIndex, int timeStepIndex) { CVF_ASSERT(reservoirView); m_reservoirView = reservoirView; m_gridIndex = gridIndex; m_cellIndex = cellIndex; m_timeStepIndex = timeStepIndex; m_intersectionPoint = cvf::Vec3d::UNDEFINED; m_face = cvf::StructGridInterface::NO_FACE; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuFemResultTextBuilder::setIntersectionPoint(cvf::Vec3d intersectionPoint) { m_intersectionPoint = intersectionPoint; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuFemResultTextBuilder::setFace(cvf::StructGridInterface::FaceType face) { m_face = face; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuFemResultTextBuilder::mainResultText() { QString text; text = closestNodeResultText(m_reservoirView->cellResult()); if (!text.isEmpty()) text += "\n"; QString topoText = this->topologyText("\n"); text += topoText; text += "\n"; appendDetails(text, gridResultDetails()); return text; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuFemResultTextBuilder::topologyText(QString itemSeparator) { QString text; if (m_reservoirView->geoMechCase()) { RigGeoMechCaseData* geomData = m_reservoirView->geoMechCase()->geoMechData(); if (geomData) { RigFemPart* femPart = geomData->femParts()->part(m_gridIndex); int elementId = femPart->elmId(m_cellIndex); text += QString("Element : Id[%1]").arg(elementId); size_t i = 0; size_t j = 0; size_t k = 0; if (geomData->femParts()->part(m_gridIndex)->structGrid()->ijkFromCellIndex(m_cellIndex, &i, &j, &k)) { // Adjust to 1-based Eclipse indexing i++; j++; k++; cvf::Vec3d domainCoord = m_intersectionPoint; // + geomCase->femParts()->displayModelOffset(); //cvf::StructGridInterface::FaceEnum faceEnum(m_face); //QString faceText = faceEnum.text(); //text += QString("Face : %1").arg(faceText) + itemSeparator; //text += QString("Fem Part %1").arg(m_gridIndex) + itemSeparator; text += QString(", ijk[%1, %2, %3]").arg(i).arg(j).arg(k) + itemSeparator; QString formattedText; formattedText.sprintf("Intersection point : [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); text += formattedText; } } } return text; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuFemResultTextBuilder::gridResultDetails() { QString text; if (m_reservoirView->geoMechCase() && m_reservoirView->geoMechCase()->geoMechData()) { RigGeoMechCaseData* eclipseCaseData = m_reservoirView->geoMechCase()->geoMechData(); this->appendTextFromResultColors(eclipseCaseData, m_gridIndex, m_cellIndex, m_timeStepIndex, m_reservoirView->cellResult(), &text); if (!text.isEmpty()) { text.prepend("-- Element result details --\n"); } } return text; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuFemResultTextBuilder::appendTextFromResultColors(RigGeoMechCaseData* geomData, int gridIndex, int cellIndex, int timeStepIndex, RimGeoMechCellColors* resultColors, QString* resultInfoText) { if (!resultColors) { return; } if (resultColors->hasResult()) { const std::vector& scalarResults = geomData->femPartResults()->resultValues(resultColors->resultAddress(), gridIndex, timeStepIndex); if (scalarResults.size()) { caf::AppEnum resPosAppEnum = resultColors->resultPositionType(); resultInfoText->append(resPosAppEnum.uiText() + ", "); resultInfoText->append(resultColors->resultFieldUiName()+ ", ") ; resultInfoText->append(resultColors->resultComponentUiName() + ":\n"); RigFemPart* femPart = geomData->femParts()->part(gridIndex); RigElementType elmType = femPart->elementType(cellIndex); const int* elmentConn = femPart->connectivities(cellIndex); int elmNodeCount = RigFemTypes::elmentNodeCount(elmType); const int* lElmNodeToIpMap = RigFemTypes::localElmNodeToIntegrationPointMapping(elmType); for (int lNodeIdx = 0; lNodeIdx < elmNodeCount; ++lNodeIdx) { float scalarValue = std::numeric_limits::infinity(); int nodeIdx = elmentConn[lNodeIdx]; if (resultColors->resultPositionType() == RIG_NODAL) { scalarValue = scalarResults[nodeIdx]; } else { size_t resIdx = femPart->elementNodeResultIdx(cellIndex, lNodeIdx); scalarValue = scalarResults[resIdx]; } if (resultColors->resultPositionType() == RIG_INTEGRATION_POINT) { resultInfoText->append(QString("\tIP:%1 \t: %2 \tAss. Node: \t%3").arg(lElmNodeToIpMap[lNodeIdx] + 1 ).arg(scalarValue).arg(femPart->nodes().nodeIds[nodeIdx])); } else { resultInfoText->append(QString("\tN:%1 \t: %2").arg(femPart->nodes().nodeIds[nodeIdx]).arg(scalarValue)); } cvf::Vec3f nodeCoord = femPart->nodes().coordinates[nodeIdx]; resultInfoText->append(QString("\t( %3, %4, %5)\n").arg(nodeCoord[0]).arg(nodeCoord[1]).arg(nodeCoord[2])); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuFemResultTextBuilder::appendDetails(QString& text, const QString& details) { if (!details.isEmpty()) { text += "\n"; text += details; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuFemResultTextBuilder::closestNodeResultText(RimGeoMechCellColors* resultColors) { QString text; if (!resultColors) { return text; } if (resultColors->hasResult()) { if (! (m_reservoirView->geoMechCase() && m_reservoirView->geoMechCase()->geoMechData())) return text; RigGeoMechCaseData* geomData = m_reservoirView->geoMechCase()->geoMechData(); const std::vector& scalarResults = geomData->femPartResults()->resultValues(resultColors->resultAddress(), m_gridIndex, m_timeStepIndex); if (scalarResults.size()) { RigFemPart* femPart = geomData->femParts()->part(m_gridIndex); RigElementType elmType = femPart->elementType(m_cellIndex); const int* elmentConn = femPart->connectivities(m_cellIndex); int elmNodeCount = RigFemTypes::elmentNodeCount(elmType); // Find the closest node int closestLocalNode = -1; float minDist = std::numeric_limits::infinity(); for (int lNodeIdx = 0; lNodeIdx < elmNodeCount; ++lNodeIdx) { int nodeIdx = elmentConn[lNodeIdx]; cvf::Vec3f nodePos = femPart->nodes().coordinates[nodeIdx]; float dist = (nodePos - cvf::Vec3f(m_intersectionPoint)).lengthSquared(); if (dist < minDist) { closestLocalNode = lNodeIdx; minDist = dist; } } // Create a text showing the results from the closest node if (closestLocalNode >= 0) { float scalarValue = std::numeric_limits::infinity(); int nodeIdx = elmentConn[closestLocalNode]; if (resultColors->resultPositionType() == RIG_NODAL) { scalarValue = scalarResults[nodeIdx]; } else { size_t resIdx = femPart->elementNodeResultIdx(m_cellIndex, closestLocalNode); scalarValue = scalarResults[resIdx]; } text.append(QString("Closest result: N[%1], %2\n").arg(femPart->nodes().nodeIds[nodeIdx]).arg(scalarValue)); } } } return text; }