#7493 Export fracture statistics as StimPlan xml.

This commit is contained in:
Kristian Bendiksen 2021-03-24 15:06:42 +01:00
parent 9af2389ced
commit 3ec177eeb4
4 changed files with 200 additions and 3 deletions

View File

@ -61,8 +61,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.h
${CMAKE_CURRENT_LIST_DIR}/RifFractureGroupStatisticsExporter.h
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
@ -128,6 +127,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.cpp
${CMAKE_CURRENT_LIST_DIR}/RifFractureGroupStatisticsExporter.cpp
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp

View File

@ -0,0 +1,123 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifFractureGroupStatisticsExporter.h"
// #include "RiaEclipseUnitTools.h"
// #include "RimStimPlanModel.h"
#include "RigSlice2D.h"
#include "cafAssert.h"
#include <QFile>
#include <QTextStream>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifFractureGroupStatisticsExporter::writeAsStimPlanXml( const RigSlice2D& statistics,
const QString& filePath,
const std::vector<double>& gridXs,
const std::vector<double>& gridYs,
double time )
{
QFile data( filePath );
if ( !data.open( QFile::WriteOnly | QFile::Truncate ) )
{
return false;
}
QTextStream stream( &data );
appendHeaderToStream( stream );
appendGridDimensionsToStream( stream, gridXs, gridYs );
appendPropertiesToStream( stream, statistics, gridYs, time );
appendFooterToStream( stream );
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifFractureGroupStatisticsExporter::appendHeaderToStream( QTextStream& stream )
{
stream << "<?xml version=\"1.0\" ?>" << endl << "<contours>" << endl;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifFractureGroupStatisticsExporter::appendPropertiesToStream( QTextStream& stream,
const RigSlice2D& statistics,
const std::vector<double>& gridYs,
double time )
{
CAF_ASSERT( statistics.ny() == gridYs.size() );
// TODO:
QString propertyName = "conductivity";
QString propertyUnit = "cm";
stream << "<properties>" << endl;
stream << QString( "<property name=\"%1\" uom=\"%2\">" ).arg( propertyName ).arg( propertyUnit ) << endl;
stream << QString( "<time value=\"%1\">" ).arg( time ) << endl;
for ( size_t i = 0; i < gridYs.size(); i++ )
{
stream << "<depth>" << gridYs[i] << "</depth>" << endl;
stream << "<data>[";
for ( size_t x = 0; x < statistics.nx(); x++ )
{
stream << statistics.getValue( x, i ) << " ";
}
stream << "]</data>" << endl;
}
stream << "</time>" << endl;
stream << "</property>" << endl;
stream << "</properties>" << endl;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifFractureGroupStatisticsExporter::appendGridDimensionsToStream( QTextStream& stream,
const std::vector<double>& gridXs,
const std::vector<double>& gridYs )
{
stream << QString( "<grid xCount=\"%1\" yCount=\"%2\">" ).arg( gridXs.size() ).arg( gridYs.size() ) << endl;
stream << "<xs>[";
for ( auto x : gridXs )
stream << x << " ";
stream << "]</xs>" << endl;
stream << "<ys>[";
for ( auto y : gridYs )
stream << y << " ";
stream << "]</ys>" << endl;
stream << "</grid>" << endl;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifFractureGroupStatisticsExporter::appendFooterToStream( QTextStream& stream )
{
stream << "</contours>" << endl;
}

View File

@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <vector>
class QString;
class QTextStream;
class RigSlice2D;
//==================================================================================================
//
//==================================================================================================
class RifFractureGroupStatisticsExporter
{
public:
static bool writeAsStimPlanXml( const RigSlice2D& statistics,
const QString& filePath,
const std::vector<double>& gridXs,
const std::vector<double>& gridYs,
double time );
private:
static void appendHeaderToStream( QTextStream& stream );
static void appendGridDimensionsToStream( QTextStream& stream,
const std::vector<double>& gridXs,
const std::vector<double>& gridYs );
static void appendPropertiesToStream( QTextStream& stream,
const RigSlice2D& statistics,
const std::vector<double>& gridYs,
double time );
static void appendFooterToStream( QTextStream& stream );
};

View File

@ -27,6 +27,7 @@
#include "RigStimPlanFractureDefinition.h"
#include "RifCsvDataTableFormatter.h"
#include "RifFractureGroupStatisticsExporter.h"
#include "RifStimPlanXmlReader.h"
#include "cafAppEnum.h"
@ -144,6 +145,10 @@ void RimFractureGroupStatistics::computeStatistics()
auto [minX, maxX, minY, maxY] = findExtentsOfGrids( fractureGrids );
// TODO: take from an incoming xml?
double timeStep = 100.0;
double referenceDepth = 3000.0;
int numSamplesX = 100;
int numSamplesY = 150;
@ -158,6 +163,20 @@ void RimFractureGroupStatistics::computeStatistics()
.arg( sampleDistanceX )
.arg( sampleDistanceY ) );
std::vector<double> gridXs( numSamplesX );
std::vector<double> gridYs( numSamplesY );
for ( int y = 0; y < numSamplesY; y++ )
{
double posY = minY + y * sampleDistanceY;
gridYs[y] = referenceDepth + posY;
}
for ( int x = 0; x < numSamplesX; x++ )
{
double posX = minX + x * sampleDistanceX;
gridXs[x] = posX;
}
std::vector<std::vector<double>> samples( numSamplesX * numSamplesY );
sampleAllGrids( fractureGrids, samples, minX, minY, numSamplesX, numSamplesY, sampleDistanceX, sampleDistanceY );
@ -168,8 +187,13 @@ void RimFractureGroupStatistics::computeStatistics()
{
caf::AppEnum<RimFractureGroupStatistics::StatisticsType> t =
caf::AppEnum<RimFractureGroupStatistics::StatisticsType>::fromIndex( i );
std::shared_ptr<RigSlice2D> statistics = statisticsGrids[t.value()];
QString text = t.text();
writeStatisticsToCsv( "/tmp/" + text + ".csv", *statisticsGrids[t.value()] );
writeStatisticsToCsv( "/tmp/" + text + ".csv", *statistics );
QString xmlFilePath = "/tmp/fracture_group/" + text + ".xml";
RifFractureGroupStatisticsExporter::writeAsStimPlanXml( *statistics, xmlFilePath, gridXs, gridYs, timeStep );
}
}