//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RigCaseCellResultsData::cellScalarValuesHistogram(size_t scalarResultIndex)
{
    CVF_ASSERT(scalarResultIndex < resultCount());

    // Extend array and cache vars

    if (scalarResultIndex >= m_histograms.size() )
    {
        m_histograms.resize(resultCount());
        m_p10p90.resize(resultCount(), std::make_pair(HUGE_VAL, HUGE_VAL));
    }

    if (m_histograms[scalarResultIndex].size())
    {
        return m_histograms[scalarResultIndex];

    }

    double min;
    double max;
    size_t nBins = 100;
    this->minMaxCellScalarValues( scalarResultIndex, min, max );
    RigHistogramCalculator histCalc(min, max, nBins, &m_histograms[scalarResultIndex]);

    if (scalarResultIndex == m_combinedTransmissibilityResultIndex)
    {
        size_t tranX, tranY, tranZ;
        if (findTransmissibilityResults(tranX, tranY, tranZ))
        {
            for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++)
            {
                histCalc.addData(m_cellScalarResults[tranX][tsIdx]);
                histCalc.addData(m_cellScalarResults[tranY][tsIdx]);
                histCalc.addData(m_cellScalarResults[tranZ][tsIdx]);
            } 
        }
    }
    else
    {
        for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++)
        {
            std::vector<double>& values = m_cellScalarResults[scalarResultIndex][tsIdx];

            histCalc.addData(values);
        } 
    }

    m_p10p90[scalarResultIndex].first = histCalc.calculatePercentil(0.1);
    m_p10p90[scalarResultIndex].second = histCalc.calculatePercentil(0.9);

    return m_histograms[scalarResultIndex];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigReservoirCellResults::minMaxCellScalarValues( size_t scalarResultIndex, double& min, double& max )
{
    min = HUGE_VAL;
    max = -HUGE_VAL;
	
    CVF_ASSERT(scalarResultIndex < resultCount());

    // Extend array and cache vars

    if (scalarResultIndex >= m_maxMinValues.size() )
    {
        m_maxMinValues.resize(scalarResultIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL));
    }

    if (m_maxMinValues[scalarResultIndex].first != HUGE_VAL)
    {
        min = m_maxMinValues[scalarResultIndex].first;
        max = m_maxMinValues[scalarResultIndex].second;

        return;
    }

    size_t i;
    for (i = 0; i < timeStepCount(scalarResultIndex); i++)
    {
        double tsmin, tsmax;
        minMaxCellScalarValues(scalarResultIndex, i, tsmin, tsmax);
        if (tsmin < min) min = tsmin;
        if (tsmax > max) max = tsmax;
    }

    m_maxMinValues[scalarResultIndex].first = min;
    m_maxMinValues[scalarResultIndex].second= max;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, double& pos, double& neg)
{
    pos = HUGE_VAL;
    neg = -HUGE_VAL;

    CVF_ASSERT(scalarResultIndex < resultCount());

    // Extend array and cache vars

    if (scalarResultIndex >= m_posNegClosestToZero.size() )
    {
        m_posNegClosestToZero.resize(scalarResultIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL));
    }

    if (m_posNegClosestToZero[scalarResultIndex].first != HUGE_VAL)
    {
        pos = m_posNegClosestToZero[scalarResultIndex].first;
        neg = m_posNegClosestToZero[scalarResultIndex].second;

        return;
    }

    size_t i;
    for (i = 0; i < timeStepCount(scalarResultIndex); i++)
    {
        double tsNeg, tsPos;
        posNegClosestToZero(scalarResultIndex, i, tsPos, tsNeg);
        if (tsNeg > neg && tsNeg < 0) neg = tsNeg;
        if (tsPos < pos && tsPos > 0) pos = tsPos;
    }

    m_posNegClosestToZero[scalarResultIndex].first = pos;
    m_posNegClosestToZero[scalarResultIndex].second= neg;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
std::vector<double>& RigCaseCellResultsData::cellScalarResults(size_t scalarResultIndex, size_t timeStepIndex)
{
    CVF_TIGHT_ASSERT(scalarResultIndex < resultCount());
    CVF_TIGHT_ASSERT(timeStepIndex < m_cellScalarResults[scalarResultIndex].size());

    return m_cellScalarResults[scalarResultIndex][timeStepIndex];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
double RigReservoirCellResults::cellScalarResult(size_t timeStepIndex, size_t scalarResultIndex, size_t resultValueIndex)
{
    if (scalarResultIndex < resultCount() &&
        timeStepIndex < m_cellScalarResults[scalarResultIndex].size() &&
        resultValueIndex != cvf::UNDEFINED_SIZE_T &&
        resultValueIndex < m_cellScalarResults[scalarResultIndex][timeStepIndex].size())
    {
        return m_cellScalarResults[scalarResultIndex][timeStepIndex][resultValueIndex];
    }
    else
    {
        return HUGE_VAL;
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RigReservoirCellResults::cellScalarValuesHistogram(size_t scalarResultIndex)
{
    CVF_ASSERT(scalarResultIndex < resultCount());

    // Extend array and cache vars

    if (scalarResultIndex >= m_histograms.size() )
    {
        m_histograms.resize(resultCount());
        m_p10p90.resize(resultCount(), std::make_pair(HUGE_VAL, HUGE_VAL));
    }

    if (m_histograms[scalarResultIndex].size())
    {
        return m_histograms[scalarResultIndex];

    }

    double min;
    double max;
    size_t nBins = 100;
    this->minMaxCellScalarValues( scalarResultIndex, min, max );
    RigHistogramCalculator histCalc(min, max, nBins, &m_histograms[scalarResultIndex]);

    for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++)
    {
        std::vector<double>& values = m_cellScalarResults[scalarResultIndex][tsIdx];

        histCalc.addData(values);
    } 

    m_p10p90[scalarResultIndex].first = histCalc.calculatePercentil(0.1);
    m_p10p90[scalarResultIndex].second = histCalc.calculatePercentil(0.9);

    return m_histograms[scalarResultIndex];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigReservoirCellResults::minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max)
{
    min = HUGE_VAL;
    max = -HUGE_VAL;

    CVF_ASSERT(scalarResultIndex < resultCount());
    CVF_ASSERT(timeStepIndex < m_cellScalarResults[scalarResultIndex].size() );

    if (scalarResultIndex >= m_maxMinValuesPrTs.size())
    {
        m_maxMinValuesPrTs.resize(scalarResultIndex+1);
    }

    if (timeStepIndex >= m_maxMinValuesPrTs[scalarResultIndex].size())
    {
        m_maxMinValuesPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL));
    }

    if (m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL)
    {
        min = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first;
        max = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second;

        return;
    }

    std::vector<double>& values = m_cellScalarResults[scalarResultIndex][timeStepIndex];

    size_t i;
    for (i = 0; i < values.size(); i++)
    {
        if (values[i] < min)
        {
            min = values[i];
        }

        if (values[i] > max)
        {
            max = values[i];
        }
    }

    m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first = min;
    m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second= max;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
std::vector< std::vector<double> > & RigReservoirCellResults::cellScalarResults( size_t scalarResultIndex )
{
	CVF_TIGHT_ASSERT(scalarResultIndex < resultCount());

	return m_cellScalarResults[scalarResultIndex];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
size_t RigReservoirCellResults::timeStepCount(size_t scalarResultIndex) const
{
    CVF_TIGHT_ASSERT(scalarResultIndex < resultCount());

    return m_cellScalarResults[scalarResultIndex].size();
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigCaseCellResultsData::minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max)
{
    min = HUGE_VAL;
    max = -HUGE_VAL;

    CVF_ASSERT(scalarResultIndex < resultCount());

    if (timeStepIndex >= m_cellScalarResults[scalarResultIndex].size())
    {
        return;
    }

    if (scalarResultIndex >= m_maxMinValuesPrTs.size())
    {
        m_maxMinValuesPrTs.resize(scalarResultIndex+1);
    }

    if (timeStepIndex >= m_maxMinValuesPrTs[scalarResultIndex].size())
    {
        m_maxMinValuesPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL));
    }

    if (m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL)
    {
        min = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first;
        max = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second;

        return;
    }

    if (scalarResultIndex == m_combinedTransmissibilityResultIndex)
    {
        size_t tranX, tranY, tranZ;
        if (!findTransmissibilityResults(tranX, tranY, tranZ)) return;

        double tranMin; 
        double tranMax; 

        minMaxCellScalarValues(tranX, timeStepIndex, tranMin, tranMax);
        min = CVF_MIN(tranMin, min);
        max = CVF_MAX(tranMax, max);

        minMaxCellScalarValues(tranY, timeStepIndex, tranMin, tranMax);
        min = CVF_MIN(tranMin, min);
        max = CVF_MAX(tranMax, max);

        minMaxCellScalarValues(tranZ, timeStepIndex, tranMin, tranMax);
        min = CVF_MIN(tranMin, min);
        max = CVF_MAX(tranMax, max);

        return;
    }

    std::vector<double>& values = m_cellScalarResults[scalarResultIndex][timeStepIndex];

    size_t i;
    for (i = 0; i < values.size(); i++)
    {
        if (values[i] == HUGE_VAL)
        {
            continue;
        }

        if (values[i] < min)
        {
            min = values[i];
        }

        if (values[i] > max)
        {
            max = values[i];
        }
    }

    m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first = min;
    m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second= max;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, size_t timeStepIndex, double& pos, double& neg)
{
    pos = HUGE_VAL;
    neg = -HUGE_VAL;

    CVF_ASSERT(scalarResultIndex < resultCount());

    if (timeStepIndex >= m_cellScalarResults[scalarResultIndex].size())
    {
        return;
    }

    if (scalarResultIndex >= m_posNegClosestToZeroPrTs.size())
    {
        m_posNegClosestToZeroPrTs.resize(scalarResultIndex+1);
    }

    if (timeStepIndex >= m_posNegClosestToZeroPrTs[scalarResultIndex].size())
    {
        m_posNegClosestToZeroPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL));
    }

    if (m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL)
    {
        pos = m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first;
        neg = m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].second;

        return;
    }

    if (scalarResultIndex == m_combinedTransmissibilityResultIndex)
    {
        size_t tranX, tranY, tranZ;
        if (findTransmissibilityResults(tranX, tranY, tranZ))
        {
            double traPos, traNeg;
            posNegClosestToZero(tranX, timeStepIndex, traPos, traNeg);
            if ( 0   < traPos && traPos < pos ) pos = traPos;
            if ( neg < traNeg && traNeg < 0   ) neg = traNeg;
            posNegClosestToZero(tranY, timeStepIndex, traPos, traNeg);
            if ( 0   < traPos && traPos < pos ) pos = traPos;
            if ( neg < traNeg && traNeg < 0   ) neg = traNeg;
            posNegClosestToZero(tranZ, timeStepIndex, traPos, traNeg);
            if ( 0   < traPos && traPos < pos ) pos = traPos;
            if ( neg < traNeg && traNeg < 0   ) neg = traNeg;
        }

        return;
    }

    std::vector<double>& values = m_cellScalarResults[scalarResultIndex][timeStepIndex];

    size_t i;
    for (i = 0; i < values.size(); i++)
    {
        if (values[i] == HUGE_VAL)
        {
            continue;
        }

        if (values[i] < pos && values[i] > 0)
        {
            pos = values[i];
        }

        if (values[i] > neg && values[i] < 0)
        {
            neg = values[i];
        }
    }

    m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first = pos;
    m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].second= neg;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
const std::vector< std::vector<double> > & RigCaseCellResultsData::cellScalarResults( size_t scalarResultIndex ) const
{
    CVF_TIGHT_ASSERT(scalarResultIndex < resultCount());

    return m_cellScalarResults[scalarResultIndex];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RigCaseCellResultsData::meanCellScalarValues(size_t scalarResultIndex, double& meanValue)
{
    CVF_ASSERT(scalarResultIndex < resultCount());

    // Extend array and cache vars

    if (scalarResultIndex >= m_meanValues.size() )
    {
        m_meanValues.resize(scalarResultIndex+1, HUGE_VAL);
    }

    if (m_meanValues[scalarResultIndex] != HUGE_VAL)
    {
        meanValue = m_meanValues[scalarResultIndex];
        return;
    }

    double valueSum = 0.0;
    size_t count = 0;

    if (scalarResultIndex == m_combinedTransmissibilityResultIndex)
    {
        size_t tranX, tranY, tranZ;
        if (findTransmissibilityResults(tranX, tranY, tranZ))
        {
            for (size_t tIdx = 0; tIdx < timeStepCount(tranX); tIdx++)
            {
                {
                    std::vector<double>& values = m_cellScalarResults[tranX][tIdx];
                    for (size_t cIdx = 0; cIdx < values.size(); ++cIdx)
                    {
                        valueSum += values[cIdx];
                    }
                    count += values.size();
                }
                {
                    std::vector<double>& values = m_cellScalarResults[tranY][tIdx];
                    for (size_t cIdx = 0; cIdx < values.size(); ++cIdx)
                    {
                        valueSum += values[cIdx];
                    }
                    count += values.size();
                }
                {
                    std::vector<double>& values = m_cellScalarResults[tranZ][tIdx];
                    for (size_t cIdx = 0; cIdx < values.size(); ++cIdx)
                    {
                        valueSum += values[cIdx];
                    }
                    count += values.size();
                }
            }
        }
    }
    else
    {
        for (size_t tIdx = 0; tIdx < timeStepCount(scalarResultIndex); tIdx++)
        {
            std::vector<double>& values = m_cellScalarResults[scalarResultIndex][tIdx];
            for (size_t cIdx = 0; cIdx < values.size(); ++cIdx)
            {
                valueSum += values[cIdx];
            }
            count += values.size();
        }
    }

    m_meanValues[scalarResultIndex] = valueSum/count;
    meanValue = m_meanValues[scalarResultIndex];
}