2015-06-17 02:43:52 -05:00
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Copyright (C) 2015- Statoil ASA
|
|
|
|
|
// Copyright (C) 2015- 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 <http://www.gnu.org/licenses/gpl.html>
|
|
|
|
|
// for more details.
|
|
|
|
|
//
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
#include "cvfBase.h"
|
|
|
|
|
#include "cafTensor3.h"
|
|
|
|
|
#include "cvfVector3.h"
|
|
|
|
|
|
|
|
|
|
#include "cvfMatrix3.h"
|
|
|
|
|
|
|
|
|
|
namespace caf {
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
/// Compute the cofactors of the 3x3 matrix
|
|
|
|
|
/// Cofactor:
|
|
|
|
|
/// The determinant obtained by deleting the row and column of a given element and
|
|
|
|
|
/// preceded by a + or <20> sign depending whether the element is in a + or <20> position as follows:
|
|
|
|
|
///
|
|
|
|
|
/// + - +
|
|
|
|
|
/// - + -
|
|
|
|
|
/// + - +
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
cvf::Mat3d cofactor3(const cvf::Mat3d& mx)
|
|
|
|
|
{
|
|
|
|
|
int detIdxi[2];
|
|
|
|
|
int detIdxj[2];
|
|
|
|
|
|
|
|
|
|
cvf::Mat3d cof;
|
|
|
|
|
|
|
|
|
|
double sign;
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
detIdxi[0] = (i == 0) ? 1 : 0;
|
|
|
|
|
detIdxi[1] = (i == 2) ? 1 : 2;
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
|
|
|
{
|
|
|
|
|
detIdxj[0] = (j == 0) ? 1 : 0;
|
|
|
|
|
detIdxj[1] = (j == 2) ? 1 : 2;
|
|
|
|
|
sign = (abs(j - i) == 1) ? -1 : 1;
|
|
|
|
|
|
|
|
|
|
cof(i, j) = sign * ( mx(detIdxi[0], detIdxj[0]) * mx(detIdxi[1], detIdxj[1])
|
|
|
|
|
- mx(detIdxi[0], detIdxj[1]) * mx(detIdxi[1], detIdxj[0]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cof;
|
|
|
|
|
}
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
/// Compute the eigenvector of the matrix corresponding to the provided eigenvalue
|
|
|
|
|
/// The provided eigenvalue must be an actual eigenvalue of the matrix
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
cvf::Vec3d eigenVector3(const cvf::Mat3d& mx, double eigenValue, bool* computedOk)
|
|
|
|
|
{
|
|
|
|
|
const double doubleThreshold = 1.0e-60;
|
|
|
|
|
if (computedOk) (*computedOk) = false;
|
2015-10-23 08:21:23 -05:00
|
|
|
|
cvf::Mat3d mxMinusEigv = mx;
|
2015-06-17 02:43:52 -05:00
|
|
|
|
|
2015-10-23 08:21:23 -05:00
|
|
|
|
for (int i = 0; i < 3; i++)
|
2015-06-17 02:43:52 -05:00
|
|
|
|
{
|
|
|
|
|
mxMinusEigv(i, i) -= eigenValue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-23 08:21:23 -05:00
|
|
|
|
cvf::Mat3d cof = cofactor3(mxMinusEigv);
|
2015-06-17 02:43:52 -05:00
|
|
|
|
|
2015-10-23 08:21:23 -05:00
|
|
|
|
// Find largest absolute cofactor
|
2015-06-17 02:43:52 -05:00
|
|
|
|
|
2015-10-23 08:21:23 -05:00
|
|
|
|
int largestCof_i = -1;
|
2015-06-17 02:43:52 -05:00
|
|
|
|
int largestCof_j = -1;
|
2015-10-23 08:21:23 -05:00
|
|
|
|
double largestCof = 0.0;
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
|
|
|
{
|
|
|
|
|
double absCof = fabs(cof(i,j));
|
|
|
|
|
|
|
|
|
|
if (absCof > largestCof)
|
|
|
|
|
{
|
|
|
|
|
largestCof = absCof;
|
|
|
|
|
largestCof_i = i;
|
|
|
|
|
largestCof_j = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fabs(largestCof) < doubleThreshold) return cvf::Vec3d::ZERO;
|
|
|
|
|
|
|
|
|
|
// Find largest matrix element not in the max cofactor row/col
|
|
|
|
|
|
|
|
|
|
int largestMxElm_i = -1;
|
2015-06-17 02:43:52 -05:00
|
|
|
|
int largestMxElm_j = -1;
|
2015-10-23 08:21:23 -05:00
|
|
|
|
double largestMxElm = 0.0;
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i != largestCof_i)
|
|
|
|
|
{
|
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
|
|
|
{
|
|
|
|
|
if (j != largestCof_j)
|
|
|
|
|
{
|
|
|
|
|
double absMxElm = fabs(mxMinusEigv(i,j));
|
|
|
|
|
|
|
|
|
|
if (absMxElm > largestMxElm)
|
|
|
|
|
{
|
|
|
|
|
largestMxElm = absMxElm;
|
|
|
|
|
largestMxElm_i = i;
|
|
|
|
|
largestMxElm_j = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if largest coefficient is zero
|
|
|
|
|
if (fabs(largestMxElm) < doubleThreshold) return cvf::Vec3d::ZERO;
|
|
|
|
|
|
|
|
|
|
// Find last component index
|
|
|
|
|
int lastComp_j = 0;
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
if ((i != largestCof_j) && (i != largestMxElm_j)) lastComp_j = i;
|
|
|
|
|
}
|
2015-06-17 02:43:52 -05:00
|
|
|
|
|
|
|
|
|
cvf::Vec3d eigenVector;
|
2015-10-23 08:21:23 -05:00
|
|
|
|
eigenVector[largestCof_j] = 1.0;
|
|
|
|
|
eigenVector[lastComp_j] = cof(largestCof_i, lastComp_j) / cof(largestCof_i, largestCof_j);
|
|
|
|
|
eigenVector[largestMxElm_j] = (-mxMinusEigv(largestMxElm_i, largestCof_j) - mxMinusEigv(largestMxElm_i, lastComp_j)*eigenVector[lastComp_j] )
|
2015-06-17 02:43:52 -05:00
|
|
|
|
/ mxMinusEigv(largestMxElm_i, largestMxElm_j);
|
|
|
|
|
|
|
|
|
|
if (computedOk) (*computedOk) = true;
|
|
|
|
|
|
2015-10-23 08:21:23 -05:00
|
|
|
|
return eigenVector;
|
2015-06-17 02:43:52 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|