Brief description of class still missing. More...
#include <HRFK.h>
Public Member Functions | |
| Complex * | crossCorrelationMatrix (int component) |
| Complex * | crossCorrelationMatrix (double angle) |
| HRFK (QList< FKStationSignals * > array) | |
| void | initOperator (Complex *covmat, double dampingFactor, QString *log=0) |
| virtual double | value (double x, double y) const |
| virtual double | value (double x, double y, int index) const |
| ~HRFK () | |
Brief description of class still missing.
Full description of class still missing
| ArrayCore::HRFK::HRFK | ( | QList< FKStationSignals * > | array | ) |
Description of constructor still missing
References ArrayCore::FK::_array, ArrayCore::FKStationSignals::isSelected(), and TRACE.
: FK(array) { TRACE; _selectedStationCount=0; _stationIndexes=new int[_array.count()]; int n=_array.count(); for(int i=0; i<n; i++ ) { FKStationSignals * s=static_cast<FKStationSignals *>(_array.at(i)); if(s->isSelected()) { _stationIndexes[_selectedStationCount]=i; _selectedStationCount++; } } // Allocation of cross corelation matrix called R _Rmatrix=new Complex[ _selectedStationCount * _selectedStationCount ]; // Proper identification of horizontal components if any switch (array.first()->nComponents()) { case 2: _northIndex=0; _eastIndex=1; break; case 3: _northIndex=1; _eastIndex=2; break; default: _northIndex=0; _eastIndex=0; break; } }
| Complex * ArrayCore::HRFK::crossCorrelationMatrix | ( | int | component | ) |
References ArrayCore::FK::_array, ArrayCore::FK::_gaussianPtr, ArrayCore::FK::_iFreqMax, ArrayCore::FK::_iFreqMin, QGpCoreTools::conjugate(), and ArrayCore::FKStationSignals::getSignalSpectrum().
Referenced by HRFKLoopTask::initGridValues(), and HRFKTimeWindows::setComponent().
{
Complex * covmat=new Complex[ _selectedStationCount * _selectedStationCount ];
// Cache for signals
Complex * sig=new Complex[ _selectedStationCount ];
/*
Filling in the upper part of the matrix and the diagonal elements with the cross products
Summation over all frequency samples
*/
Complex tmp, specRow, specCol;
QList<FKStationSignals *>::iterator itrow, itcol;
for(register int iFreq=_iFreqMin;iFreq <= _iFreqMax;iFreq++ ) {
// Fill in the cache with signals
for(register int s=0;s < _selectedStationCount;s++ ) {
FKStationSignals * stat=_array.at(_stationIndexes[s] );
sig[s]=stat->getSignalSpectrum(component, iFreq);
}
for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=row;col < _selectedStationCount;col++ ) {
tmp=sig[col];
tmp=conjugate(tmp);
tmp *= sig[row];
tmp *= _gaussianPtr[iFreq];
covmat[ col * _selectedStationCount + row ] += tmp;
}
}
}
delete [] sig;
return covmat;
}
| Complex * ArrayCore::HRFK::crossCorrelationMatrix | ( | double | angle | ) |
angle is counted from North clockwize
References ArrayCore::FK::_array, ArrayCore::FK::_gaussianPtr, ArrayCore::FK::_iFreqMax, ArrayCore::FK::_iFreqMin, QGpCoreTools::conjugate(), QGpCoreTools::Angle::cos(), ArrayCore::FKStationSignals::getSignalSpectrum(), QGpCoreTools::Angle::setDegreeAzimuth(), and QGpCoreTools::Angle::sin().
{
Angle a;
a.setDegreeAzimuth(angle);
Complex * covmat=new Complex[ _selectedStationCount * _selectedStationCount ];
// Cache for rotated signals
Complex * sig=new Complex[ _selectedStationCount ];
/*
Filling in the upper part of the matrix and the diagonal elements with the cross products
Summation over all frequency samples
*/
Complex tmp, specRow, specCol;
QList<FKStationSignals *>::iterator itrow, itcol;
for(register int iFreq=_iFreqMin;iFreq <= _iFreqMax;iFreq++ ) {
// Fill in the cache with rotated signals
for(register int s=0;s < _selectedStationCount;s++ ) {
FKStationSignals * stat=_array.at(_stationIndexes[s] );
Complex& c=sig[s];
c=stat->getSignalSpectrum(_eastIndex, iFreq);
c *= a.cos();
tmp=stat->getSignalSpectrum(_northIndex, iFreq);
tmp *= a.sin();
c += tmp;
}
for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=row;col < _selectedStationCount;col++ ) {
tmp=sig[col];
tmp=conjugate(tmp);
tmp *= sig[row];
tmp *= _gaussianPtr[iFreq];
covmat[ col * _selectedStationCount + row ] += tmp;
}
}
}
delete [] sig;
return covmat;
}
| void ArrayCore::HRFK::initOperator | ( | Complex * | covmat, |
| double | dampingFactor, | ||
| QString * | log = 0 |
||
| ) |
References ArrayCore::FK::_frequency, ArrayCore::FK::_iFreqMax, ArrayCore::FK::_iFreqMin, QGpCoreTools::conjugate(), QGpCoreTools::Complex::re, QGpCoreTools::sqrt(), QGpCoreTools::tr(), and ArrayCore::zgesvd_().
Referenced by HRFKLoopTask::initGridValues(), and HRFKTimeWindows::setComponent().
{
/*
LAPACK is assuming matrix stored in vectors column by column
For a MxN matrix:
a(1,1) ... a(m,1) a(1,2) ... a(m,2) ... a(1,n) ... a(m,n)
On output for _Rmatrix it is the contrary:
For a MxN matrix:
a(1,1) ... a(1,n) a(2,1) ... a(2,n) ... a(m,1) ... a(m,n)
*/
int nostat2=_selectedStationCount * _selectedStationCount;
//printf("Upper\n");
//printMatrix(covmat, _selectedStationCount, _selectedStationCount);
/*
Computes the auto-power for normalizing, normalizing factor also include the division by the number
of frequency samples
*/
double * scale=new double[ _selectedStationCount ];
for(register int row=0;row < _selectedStationCount;row++ ) {
double s=covmat[ row * _selectedStationCount + row ].re();
if(s==0) { // Flat spectrum for one station
return initOperatorError( "Flat spectrum, check signal", log);
}
scale[ row ]=1.0/sqrt(s);
}
/*
Filling in the lower part of the matrix with conjugates of the upper part and normalizing
*/
for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=row;col < _selectedStationCount;col++ ) {
Complex& upper=covmat[ col * _selectedStationCount + row ];
Complex& lower=covmat[ row * _selectedStationCount + col ];
upper *= scale[ row ] * scale[ col ];
lower=conjugate(upper);
}
}
delete [] scale;
//printf("Full:\n");
//printMatrix(covmat, _selectedStationCount, _selectedStationCount);
// Damping
if(dampingFactor>0) {
dampingFactor=1.0-dampingFactor;
for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=row;col < _selectedStationCount;col++ ) {
covmat[ row * _selectedStationCount + col ] *= dampingFactor;
}
}
/*
Add white noise to avoid singular matrix
*/
dampingFactor=1.0-dampingFactor;
for(register int el=0; el < _selectedStationCount;el++ ) {
covmat[ el + _selectedStationCount * el ] += dampingFactor;
}
}
//printf("With noise:\n");
//printMatrix(covmat, _selectedStationCount, _selectedStationCount);
/*
need to allocate the matrices, etc.
I'll use now code from CLAPACK!
matrices are allocated in 1 dim.-array!
*/
Complex *a; /* copy of covmat */
Complex *vt; /* nullspace vectors */
Complex *u; /* eigenvectors */
double *s; /* eigenvalues */
Complex *work; /* work space */
double *rwork; /* another workspace */
char jobu, jobvt; /* flags what to do in zgesvd_ */
int lda, ldu, ldvt; /* dimensions of SVD problem */
int lwork, info; /* dimension of workspaces */
int mm, nn;
a=new Complex[ nostat2 ];
u=new Complex[ nostat2 ];
vt=new Complex[ nostat2 ];
work=new Complex[ 50 * _selectedStationCount + 1 ];
rwork=new double[ 5 * _selectedStationCount ];
s=new double [ _selectedStationCount ];
/*
Copy covmat to a
*/
for(register int i=nostat2 - 1;i >= 0;i-- ) {
a[ i ]=covmat[ i ];
}
//printf("a\n");
//printMatrix(a, _selectedStationCount, _selectedStationCount);
/*********************************************/
/* now find the eigenvalues and eigenvectors */
/* driver ZGESVD already sorts the basis! */
/*********************************************/
// CLAPACK is probalby not thread safe... lock it
jobu='A';
jobvt='A';
lda=ldu=ldvt=mm=nn=_selectedStationCount;
lwork=50 * _selectedStationCount + 1;
static QMutex mutex;
mutex.lock();
zgesvd_(&jobu, &jobvt, &mm, &nn, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, &info);
mutex.unlock();
/* Output is U, SIGMA and VT
A=U * SIGMA * VT
VT being the conjugate-transpose matrix of V
A^-1=V * SIGMA^-1 * UT
UT being the conjugate-transpose matrix of U
*/
//printf("u\n");
//printMatrix(u, _selectedStationCount, _selectedStationCount);
//printf("s\n");
//printMatrix(s, 1, _selectedStationCount
//printf("vt\n");
//printMatrix(vt, _selectedStationCount, _selectedStationCount);*/
// Check if matrix has a true inverse (good rank)
delete [] work;
delete [] rwork;
delete [] covmat;
delete [] a;
double sRef=1e-12 * s[ 0 ];
for(register int row=0;row < _selectedStationCount;row++ ) {
if(s[ row ] < sRef) {
static const char * msg=QT_TR_NOOP( "At %1 Hz, effective rank %2 (%3 frequency samples), "
"singular cross spectral matrix. The effective "
"rank should be at least equal to the number of stations (%4). Either "
"increase the time window lenght or the frequency band width. "
"An empy fk map will be produced." );
delete [] vt;
delete [] u;
delete [] s;
return initOperatorError(tr( msg).arg(_frequency)
.arg(row)
.arg(_iFreqMax-_iFreqMin+1)
.arg(_selectedStationCount), log);
}
}
// allocate a new temporatry matrix for multiplication of S and U
Complex * invSUT=new Complex[ nostat2 ];
for(register int row=0;row < _selectedStationCount;row++ ) {
double si=1./s[ row ];
for(register int col=0;col < _selectedStationCount;col++ ) {
Complex& invSUTElement=invSUT[ col * _selectedStationCount + row ];
Complex& uElement=u[ row * _selectedStationCount + col ];
invSUTElement=uElement;
invSUTElement=conjugate(invSUTElement);
invSUTElement *= si;
}
}
delete [] u;
delete [] s;
//printf("invSUT\n");
//printMatrix(invSUT, _selectedStationCount, _selectedStationCount);
// proceed with V * invSUT
for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=0;col < _selectedStationCount;col++ ) {
Complex& RElement=_Rmatrix[ row * _selectedStationCount + col ];
RElement=0;
for(register int k=0;k < _selectedStationCount;k++ ) {
Complex& vtElement=vt[ row * _selectedStationCount + k ];
Complex tmp=vtElement;
tmp=conjugate(tmp);
tmp *= invSUT[ col * _selectedStationCount + k ];
RElement += tmp;
}
}
}
delete [] invSUT;
delete [] vt;
//printf("R\n");
//printMatrix(_Rmatrix, _selectedStationCount, _selectedStationCount);
// Check matrix inversion
/*for(register int row=0;row < _selectedStationCount;row++ ) {
for(register int col=0;col < _selectedStationCount;col++ ) {
Complex sum;
for(int k=0;k<_selectedStationCount;k++) {
Complex tmp=covmat[row * _selectedStationCount + k];
tmp*=_Rmatrix[col * _selectedStationCount + k];
sum += tmp;
}
printf("%12lg+i*%12lg ",sum.re(), sum.im());
}
printf("\n");
}*/
}
| double ArrayCore::HRFK::value | ( | double | x, |
| double | y | ||
| ) | const [virtual] |
Implemement this function to calculate the 2D function at x and y.
Reimplemented from ArrayCore::FK.
References ArrayCore::FK::_array, QGpCoreTools::Complex::abs(), QGpCoreTools::conjugate(), and ArrayCore::FK::maximumK2().
{
double k2=kx * kx + ky * ky;
if(k2 > maximumK2()) return -1;
for(register int i=0;i < _selectedStationCount;i++ ) {
static_cast<FKStationSignals *>(_array.at(_stationIndexes[i])) ->setCurrentShift(kx, ky);
}
Complex sum;
for(register int i=0;i < _selectedStationCount;i++ ) {
Complex shiftStat1=_array.at(_stationIndexes[i] ) ->getShift();
shiftStat1=conjugate(shiftStat1);
for(register int j=0;j < _selectedStationCount;j++ ) {
Complex tmp(shiftStat1);
tmp *= _array.at(_stationIndexes[j] ) ->getShift();
tmp *= _Rmatrix[ j * _selectedStationCount + i ];
sum += tmp;
}
}
return 1.0/sum.abs();
}
| double ArrayCore::HRFK::value | ( | double | x, |
| double | y, | ||
| int | index | ||
| ) | const [virtual] |
Re-mplemement this function to calculate the 2D function for x and y aligned to a grid. x and y correspond to index in the grid: index=iy * nx + ix
If nothing is cached re-implementation of this function is useless.
Reimplemented from ArrayCore::FK.
References ArrayCore::FK::_array, QGpCoreTools::Complex::abs(), QGpCoreTools::conjugate(), and ArrayCore::FK::maximumK2().
{
double k2=kx * kx + ky * ky;
if(k2 > maximumK2()) return -1;
Complex sum;
for(register int i=0;i < _selectedStationCount;i++ ) {
Complex shiftStat1=_array.at(_stationIndexes[i] ) ->getShift(index);
shiftStat1=conjugate(shiftStat1);
for(register int j=0;j < _selectedStationCount;j++ ) {
Complex tmp(shiftStat1);
tmp *= _array.at(_stationIndexes[j] ) ->getShift(index);
tmp *= _Rmatrix[ j * _selectedStationCount + i ];
sum += tmp;
}
}
return 1.0/sum.abs();
}