femtic/src/Inversion.cpp

777 lines
30 KiB
C++
Raw Normal View History

2021-11-09 00:06:52 +08:00
//-------------------------------------------------------------------------------------------------------
// The MIT License (MIT)
//
// Copyright (c) 2021 Yoshiya Usui
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//-------------------------------------------------------------------------------------------------------
#include "Inversion.h"
#include "ObservedData.h"
#include "AnalysisControl.h"
#include "OutputFiles.h"
#include "ResistivityBlock.h"
#include "ComplexSparseMatrix.h"
#include "MeshDataBrickElement.h"
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "mkl_lapacke.h"
#include "mpi.h"
// Default constructer
Inversion::Inversion():
m_numModel(0),
m_numData(0),
m_sensitivityScalarValues(NULL)
{
for( int i = 0; i < 2; ++i ){
m_derivativesOfEMField[i] = NULL;
}
}
// Constructer
Inversion::Inversion( const int nModel, const int nData ):
m_numModel(nModel),
m_numData(nData),
m_sensitivityScalarValues(NULL)
{
for( int i = 0; i < 2; ++i ){
m_derivativesOfEMField[i] = NULL;
}
}
// Destructer
Inversion::~Inversion(){
for( int i = 0; i < 2; ++i ){
if( m_derivativesOfEMField[i] != NULL ){
delete [] m_derivativesOfEMField[i];
m_derivativesOfEMField[i] = NULL;
}
}
if( m_sensitivityScalarValues != NULL ){
delete [] m_sensitivityScalarValues;
m_sensitivityScalarValues = NULL;
}
}
// Calculate derivatives of EM field
void Inversion::calculateDerivativesOfEMField( Forward3D* const ptrForward3D, const double freq, const int iPol ){
ObservedData* const ptrObservedData = ObservedData::getInstance();
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
const ResistivityBlock* const ptrResistivityBlock = ResistivityBlock::getInstance();
const int numEquationFinallySolved = ptrForward3D->getNumOfEquationFinallySolved();;
const int numInterpolatorVectors = ptrObservedData->getNumInterpolatorVectors();
const int nBlkNotFixed = ptrResistivityBlock->getNumResistivityBlockNotFixed();
//-------------------------------------------------------------------------
// Calulate right-hand sides vectors consisting of interpolator vectors ---
//-------------------------------------------------------------------------
OutputFiles::m_logFile << "# Calulate right-hand sides vectors consisting of interpolator vectors." << ptrAnalysisControl->outputElapsedTime() << std::endl;
ptrObservedData->calculateInterpolatorVectors( ptrForward3D, freq );
//--------------------------------------------------------------------------------
// Solve phase for right-hand side vectors consisting of interpolator vectors ---
//--------------------------------------------------------------------------------
// Solution vectors of 3D forward computation for right-hand sides vectors consisting of interpolator vectors
std::complex<double>* solutionForInterpolatorVectors = new std::complex<double>[static_cast<long long>(numEquationFinallySolved) * static_cast<long long>(numInterpolatorVectors)];
OutputFiles::m_logFile << "# Solve phase of matrix solver for right-hand sides consisting of interpolator vectors." << ptrAnalysisControl->outputElapsedTime() << std::endl;
ptrForward3D->solvePhaseForRhsConsistingInterpolatorVectors( numInterpolatorVectors, solutionForInterpolatorVectors );
//--------------------------------------
// Calculate derivatives of EM field ---
//--------------------------------------
if( m_derivativesOfEMField[iPol] != NULL ){
delete [] m_derivativesOfEMField[iPol];
m_derivativesOfEMField[iPol] = NULL;
}
if( numInterpolatorVectors <= 0 ){
OutputFiles::m_logFile << "Error : Number of interpolator vectors is less than or equal to zero. numInterpolatorVectors = " << numInterpolatorVectors << std::endl;
exit(1);
}
if( nBlkNotFixed <= 0 ){
OutputFiles::m_logFile << "Error : Number of resistivity blocks whose values are not fixed is less than or equal to zero. nBlkNotFixed = " << nBlkNotFixed << std::endl;
exit(1);
}
const long long numComps = static_cast<long long>(numInterpolatorVectors) * static_cast<long long>(nBlkNotFixed);
m_derivativesOfEMField[iPol] = new std::complex<double>[numComps];
for( long long i = 0; i < numComps; ++i ){
m_derivativesOfEMField[iPol][i] = std::complex<double>(0.0, 0.0);// Initialize
}
OutputFiles::m_logFile << "# Calculate derivatives of EM field." << ptrAnalysisControl->outputElapsedTime() << std::endl;
ptrForward3D->calculateDerivativesOfEMField( numInterpolatorVectors, solutionForInterpolatorVectors, m_derivativesOfEMField[iPol] );
delete [] solutionForInterpolatorVectors;
}
// Calculate sensitivity matrix
void Inversion::calculateSensitivityMatrix( const int freqIDAmongThisPE, const double freq ){
const ObservedData* const ptrObservedData = ObservedData::getInstance();
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
const ResistivityBlock* const ptrResistivityBlock = ResistivityBlock::getInstance();
const int numDataThisPE = ptrObservedData->getNumObservedDataThisPE(freqIDAmongThisPE);
const int freqIDGlobal = ptrObservedData->getIDsOfFrequenciesCalculatedByThisPE(freqIDAmongThisPE);
//const int numModel = ptrResistivityBlock->getNumResistivityBlockNotFixed();
const int numModel = getNumberOfModel();
//-------------------------------------------
// Allocate memory for sensitivity matrix ---
//-------------------------------------------
if( numDataThisPE <= 0 ){
OutputFiles::m_logFile << "Error : Number of data of this PE is less than or equal to zero. numDataThisPE = " << numDataThisPE << std::endl;
exit(1);
}
if( numModel <= 0 ){
OutputFiles::m_logFile << "Error : Number of model is less than or equal to zero. numModel = " << numModel << std::endl;
exit(1);
}
const long long numComps = static_cast<long long>(numDataThisPE) * static_cast<long long>(numModel);
double* sensitivityMatrix = new double[numComps];
for( long long i = 0; i < numComps; ++i ){
sensitivityMatrix[i] = 0.0;// Initialize
}
OutputFiles::m_logFile << "# Calculate sensitivity matrix of frequency " << freq << "[Hz]." << ptrAnalysisControl->outputElapsedTime() << std::endl;
ptrObservedData->calculateSensitivityMatrix( m_derivativesOfEMField[0], m_derivativesOfEMField[1], freq, numModel, sensitivityMatrix );
// Release memory of derivatives ofg EM field
for( int i = 0; i < 2; ++i ){
if( m_derivativesOfEMField[i] != NULL ){
delete[] m_derivativesOfEMField[i];
m_derivativesOfEMField[i] = NULL;
}
}
#ifdef _DEBUG_WRITE
std::cout << "sensitivity matrix. freq = " << freq << std::endl;
for( int idat = 0; idat < numDataThisPE; ++idat ){
for( int imdl = 0; imdl < numModel; ++imdl ){
std::cout << "idat, imdl, val " << idat << " " << imdl << " " << sensitivityMatrix[imdl+idat*numModel] << std::endl;
}
}
#endif
//-------------------------------------------------
// Write sensitivity matrix to out-of-core file ---
//-------------------------------------------------
std::ostringstream fileName;
2025-02-06 16:26:47 +08:00
if ( !ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix().empty() ){
#ifdef _LINUX
fileName << ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix() + "\/";
#else
fileName << ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix() + "\\";
#endif
}
2021-11-09 00:06:52 +08:00
fileName << "sensMatFreq" << freqIDGlobal;
//std::ofstream outputFile(fileName.str().c_str(), std::ios::out|std::ios::binary|std::ios::trunc);
//if( outputFile.fail() ){
// OutputFiles::m_logFile << "File open error !! : " << fileName.str() << std::endl;
// exit(1);
//}
OutputFiles::m_logFile << "# Sensitivity matrix of frequency " << freq << "[Hz] is saved in the out-of-core file " << fileName.str() << "." << std::endl;
FILE* fp = NULL;
fp = fopen( fileName.str().c_str(), "wb" );
if( fp == NULL ){
OutputFiles::m_logFile << "File open error !! : " << fileName.str() << std::endl;
exit(1);
}
fwrite( &numDataThisPE, sizeof(int), 1, fp );
fwrite( &numModel, sizeof(int), 1, fp );
fwrite( sensitivityMatrix, sizeof(double), static_cast<long long>(numDataThisPE) * static_cast<long long>(numModel), fp );
fclose( fp );
//---------------------------------------------
//--- Calculate scalered sensitivity values ---
//---------------------------------------------
if( ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY) ){// if output sensitivity
const int nBlkTotal = ptrResistivityBlock->getNumResistivityBlockTotal();
for( int iblk = 0; iblk < nBlkTotal; ++iblk ){
if( ptrResistivityBlock->isFixedResistivityValue( iblk ) ){
continue;
}
const int imdl = ptrResistivityBlock->getModelIDFromBlockID(iblk);
for( int idat = 0; idat < numDataThisPE; ++idat ){
const long long index = static_cast<long long>(imdl) + static_cast<long long>(idat) * static_cast<long long>(numModel);
m_sensitivityScalarValues[imdl] += std::abs( sensitivityMatrix[index] );
}
}
//MPI_Allreduce( sensitivityScalarValuesThisPE, m_sensitivityScalarValues, numModel, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
}
delete [] sensitivityMatrix;
#ifdef _DEBUG_WRITE
std::cout << "read binary file and write agein." << std::endl;
fp = fopen( fileName.str().c_str(), "rb" );
if( fp == NULL ){
OutputFiles::m_logFile << "File open error !! : " << fileName.str() << std::endl;
exit(1);
}
int ndata(0);
int nmodel(0);
fread( &ndata, sizeof(int), 1, fp );
fread( &nmodel, sizeof(int), 1, fp );
double* temp = new double[ numDataThisPE * numModel ];
fread( temp, sizeof(double), ndata * nmodel, fp );
for( int idat = 0; idat < ndata; ++idat ){
for( int imdl = 0; imdl < nmodel; ++imdl ){
std::cout << "idat, imdl, val " << idat << " " << imdl << " " << temp[imdl+idat*numModel] << std::endl;
}
}
fclose( fp );
#endif
}
// Allocate memory for sensitivity values
void Inversion::allocateMemoryForSensitivityScalarValues(){
//const int numModel = ( ResistivityBlock::getInstance() )->getNumResistivityBlockNotFixed();
const int numModel = getNumberOfModel();
if( m_sensitivityScalarValues != NULL ){
delete [] m_sensitivityScalarValues;
m_sensitivityScalarValues = NULL;
}
m_sensitivityScalarValues = new double[ numModel ];
for( int i = 0; i < numModel; ++i ){
m_sensitivityScalarValues[i] = 0.0;
}
}
// Release memory of sensitivity values
void Inversion::releaseMemoryOfSensitivityScalarValues(){
if( m_sensitivityScalarValues != NULL ){
delete [] m_sensitivityScalarValues;
m_sensitivityScalarValues = NULL;
}
}
// Output scaler sensitivity values to vtk file
void Inversion::outputSensitivityScalarValuesToVtk() const{
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
if( !ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY ) &&
!ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY_DENSITY ) ){
return;
}
const double criteria = 1.0e-20;
const int numModel = getNumberOfModel();
double* sensitivityScalarValuesForOutput = new double[ numModel ];
#ifdef _DEBUG_WRITE
// Get process ID and total process number
//int myProcessID(0);
//MPI_Comm_rank ( MPI_COMM_WORLD, &myProcessID );
const int myProcessID = ptrAnalysisControl->getMyPE();
for( int i = 0; i < numModel; ++i ){
std::cout << "PE i m_sensitivityScalarValues : " << myProcessID << " " << i << " " << m_sensitivityScalarValues[i] << std::endl;
}
#endif
MPI_Allreduce( m_sensitivityScalarValues, sensitivityScalarValuesForOutput, numModel, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
#ifdef _DEBUG_WRITE
for( int i = 0; i < numModel; ++i ){
std::cout << "PE i sensitivityScalarValuesForOutput : " << myProcessID << " " << i << " " << sensitivityScalarValuesForOutput[i] << std::endl;
}
#endif
const MeshData* const ptrMeshData =ptrAnalysisControl->getPointerOfMeshData();
const int nElem = ptrMeshData->getNumElemTotal();
const ResistivityBlock* const ptrResistivityBlock = ResistivityBlock::getInstance();
if( ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY ) ){// Output sensitivity
OutputFiles::m_vtkFile << "SCALARS Sensitivity float" << std::endl;
OutputFiles::m_vtkFile << "LOOKUP_TABLE default" << std::endl;
double maxSensitivity(-1.0);
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
if( ptrResistivityBlock->isFixedResistivityValue( iblk ) ){
OutputFiles::m_vtkFile << criteria << std::endl;
}else{
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
//double sensitivity = fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) );
double sensitivity = fabs( sensitivityScalarValuesForOutput[imdl] );
if( sensitivity < criteria ){
sensitivity = criteria;
}
OutputFiles::m_vtkFile << sensitivity << std::endl;
if( sensitivity > maxSensitivity ){
maxSensitivity = sensitivity;
}
}
}
const double divMax = 1.0 / maxSensitivity;
OutputFiles::m_vtkFile << "SCALARS NormalizedSensitivity float" << std::endl;
OutputFiles::m_vtkFile << "LOOKUP_TABLE default" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
if( ptrResistivityBlock->isFixedResistivityValue( iblk ) ){
OutputFiles::m_vtkFile << criteria << std::endl;
}else{
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
//double sensitivityNormalized = divMax * fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) );
double sensitivityNormalized = divMax * fabs( sensitivityScalarValuesForOutput[imdl] );
if( sensitivityNormalized < criteria ){
sensitivityNormalized = criteria;
}
OutputFiles::m_vtkFile << sensitivityNormalized << std::endl;
}
}
}
if( ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY_DENSITY ) ){// Output sensitivity density
OutputFiles::m_vtkFile << "SCALARS SensitivityDensity float" << std::endl;
OutputFiles::m_vtkFile << "LOOKUP_TABLE default" << std::endl;
double maxSensitivityDensity(-1.0);
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
if( ptrResistivityBlock->isFixedResistivityValue( iblk ) ){
OutputFiles::m_vtkFile << criteria << std::endl;
}else{
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
const double volume = ptrResistivityBlock->calcVolumeOfBlock( iblk );
//double sensitivityDensity = fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) / volume;
double sensitivityDensity = fabs( sensitivityScalarValuesForOutput[imdl] ) / volume;
if( sensitivityDensity < criteria ){
sensitivityDensity = criteria;
}
OutputFiles::m_vtkFile << sensitivityDensity << std::endl;
if( sensitivityDensity > maxSensitivityDensity ){
maxSensitivityDensity = sensitivityDensity;
}
}
}
const double divMax = 1.0 / maxSensitivityDensity;
OutputFiles::m_vtkFile << "SCALARS NormalizedSensitivityDensity float" << std::endl;
OutputFiles::m_vtkFile << "LOOKUP_TABLE default" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
if( ptrResistivityBlock->isFixedResistivityValue( iblk ) ){
OutputFiles::m_vtkFile << criteria << std::endl;
}else{
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
const double volume = ptrResistivityBlock->calcVolumeOfBlock( iblk );
//double sensitivityDensityNormalized = divMax * fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) / volume;
double sensitivityDensityNormalized = divMax * fabs( sensitivityScalarValuesForOutput[imdl] ) / volume;
if( sensitivityDensityNormalized < criteria ){
sensitivityDensityNormalized = criteria;
}
OutputFiles::m_vtkFile << sensitivityDensityNormalized << std::endl;
}
}
}
delete [] sensitivityScalarValuesForOutput;
}
// Output scaler sensitivity values to binary file
void Inversion::outputSensitivityScalarValuesToBinary( const int interNum ) const{
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
if( !ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY ) &&
!ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY_DENSITY ) ){
return;
}
const double criteria = 1.0e-20;
const int numModel = getNumberOfModel();
double* sensitivityScalarValuesForOutput = new double[ numModel ];
MPI_Allreduce( m_sensitivityScalarValues, sensitivityScalarValuesForOutput, numModel, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
if( ptrAnalysisControl->getMyPE() != 0 ){// Only PE 0 output sensitivity
delete [] sensitivityScalarValuesForOutput;
return;
}
const MeshData* const ptrMeshData =ptrAnalysisControl->getPointerOfMeshData();
const ResistivityBlock* const ptrResistivityBlock = ResistivityBlock::getInstance();
const int nElem = ptrMeshData->getNumElemTotal();
if( ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY ) ){// Output sensitivity
std::ostringstream oss;
oss << "Sensitivity.iter" << interNum;
std::ofstream fout;
// Output sensitivity
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Sensitivity";
strcpy( line, ossTitle.str().c_str() );
fout.write( line, 80 );
strcpy( line, "part" );
fout.write( line, 80 );
int ibuf(1);
fout.write( (char*) &ibuf, sizeof( int ) );
if( ptrAnalysisControl->getTypeOfMesh() == MeshData::TETRA ){
strcpy( line, "tetra4" );
}
else{
strcpy( line, "hexa8" );
}
fout.write( line, 80 );
double maxSensitivity(-1.0);
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
float dbuf(criteria);
if( !ptrResistivityBlock->isFixedResistivityValue( iblk ) ){// Modifiable resisitivity
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
//dbuf = static_cast<float>( fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) );
dbuf = static_cast<float>( fabs( sensitivityScalarValuesForOutput[imdl] ) );
if( dbuf < criteria ){
dbuf = criteria;
}
if( dbuf > maxSensitivity ){
maxSensitivity = dbuf;
}
}
fout.write( (char*) &dbuf, sizeof( float ) );
}
fout.close();
const double divMax = 1.0 / maxSensitivity;
// Output normalized sensitivity
const std::string outputFileName = "Normalized"+oss.str();
fout.open( outputFileName.c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
ossTitle.clear();
ossTitle << "NormalizedSensitivity";
strcpy( line, ossTitle.str().c_str() );
fout.write( line, 80 );
strcpy( line, "part" );
fout.write( line, 80 );
fout.write( (char*) &ibuf, sizeof( int ) );
if( ptrAnalysisControl->getTypeOfMesh() == MeshData::TETRA ){
strcpy( line, "tetra4" );
}
else{
strcpy( line, "hexa8" );
}
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
float dbuf(criteria);
if( !ptrResistivityBlock->isFixedResistivityValue( iblk ) ){// Modifiable resisitivity
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
//dbuf = static_cast<float>( divMax * fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) );
dbuf = static_cast<float>( divMax * fabs( sensitivityScalarValuesForOutput[imdl] ) );
if( dbuf < criteria ){
dbuf = criteria;
}
}
fout.write( (char*) &dbuf, sizeof( float ) );
}
fout.close();
}
if( ptrAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_SENSITIVITY_DENSITY ) ){// Output sensitivity density
std::ostringstream oss;
oss << "SensitivityDensity.iter" << interNum;
std::ofstream fout;
// Output sensitivity
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "SensitivityDensity";
strcpy( line, ossTitle.str().c_str() );
fout.write( line, 80 );
strcpy( line, "part" );
fout.write( line, 80 );
int ibuf(1);
fout.write( (char*) &ibuf, sizeof( int ) );
if( ptrAnalysisControl->getTypeOfMesh() == MeshData::TETRA ){
strcpy( line, "tetra4" );
}
else{
strcpy( line, "hexa8" );
}
fout.write( line, 80 );
double maxSensitivityDensity(-1.0);
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
float dbuf(criteria);
if( !ptrResistivityBlock->isFixedResistivityValue( iblk ) ){// Modifiable resisitivity
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
const double volume = ptrResistivityBlock->calcVolumeOfBlock( iblk );
//dbuf = static_cast<float>( fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) / volume );
dbuf = static_cast<float>( fabs( sensitivityScalarValuesForOutput[imdl] ) / volume );
if( dbuf < criteria ){
dbuf = criteria;
}
if( dbuf > maxSensitivityDensity ){
maxSensitivityDensity = dbuf;
}
}
fout.write( (char*) &dbuf, sizeof( float ) );
}
fout.close();
const double divMax = 1.0 / maxSensitivityDensity;
// Output normalized sensitivity
const std::string outputFileName = "Normalized"+oss.str();
fout.open( outputFileName.c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
ossTitle.clear();
ossTitle << "NormalizedSensitivityDensity";
strcpy( line, ossTitle.str().c_str() );
fout.write( line, 80 );
strcpy( line, "part" );
fout.write( line, 80 );
fout.write( (char*) &ibuf, sizeof( int ) );
if( ptrAnalysisControl->getTypeOfMesh() == MeshData::TETRA ){
strcpy( line, "tetra4" );
}
else{
strcpy( line, "hexa8" );
}
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const int iblk = ptrResistivityBlock->getBlockIDFromElemID( iElem );
float dbuf(criteria);
if( !ptrResistivityBlock->isFixedResistivityValue( iblk ) ){// Modifiable resisitivity
const int imdl = ptrResistivityBlock->getModelIDFromBlockID( iblk );
const double volume = ptrResistivityBlock->calcVolumeOfBlock( iblk );
//dbuf = static_cast<float>( divMax * fabs( sensitivityScalarValuesForOutput[imdl] * log10( ptrResistivityBlock->getResistivityValuesFromBlockID(iblk) ) ) / volume );
dbuf = static_cast<float>( divMax * fabs( sensitivityScalarValuesForOutput[imdl] ) / volume );
if( dbuf < criteria ){
dbuf = criteria;
}
}
fout.write( (char*) &dbuf, sizeof( float ) );
}
fout.close();
}
delete [] sensitivityScalarValuesForOutput;
}
// Calculate constraining matrix
void Inversion::calcConstrainingMatrix( DoubleSparseMatrix& constrainingMatrix ) const{
const ObservedData* const ptrObservedData = ObservedData::getInstance();
const int numDistortionParamsNotFixed = ptrObservedData->getNumDistortionParamsNotFixed();
const int numResistivityBlockNotFixed = ( ResistivityBlock::getInstance() )->getNumResistivityBlockNotFixed();
const int numModel = numResistivityBlockNotFixed + numDistortionParamsNotFixed;
constrainingMatrix.setNumRowsAndColumns( numModel, numModel );
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
const double factor1 = ptrAnalysisControl->getTradeOffParameterForResistivityValue();
( ResistivityBlock::getInstance() )->calcRougheningMatrixDegeneratedForLaplacianFilter( constrainingMatrix, factor1 );
const int nBlkNotFixed = ( ResistivityBlock::getInstance() )->getNumResistivityBlockNotFixed();
int iMdl = nBlkNotFixed;
if( ptrAnalysisControl->getTypeOfDistortion() == AnalysisControl::ESTIMATE_DISTORTION_MATRIX_DIFFERENCE ){
// For distortion matrix components
const double factor2 = ptrAnalysisControl->getTradeOffParameterForDistortionMatrixComplexity();
for( int iParamsNotFixed = 0; iParamsNotFixed < numDistortionParamsNotFixed; ++iParamsNotFixed ){
constrainingMatrix.setStructureAndAddValueByTripletFormat( iMdl, iMdl, factor2 );
++iMdl;
}
}
else if( ptrAnalysisControl->getTypeOfDistortion() == AnalysisControl::ESTIMATE_GAINS_AND_ROTATIONS ){
// For gains and rotations of distortion matrix
const double factor2 = ptrAnalysisControl->getTradeOffParameterForGainsOfDistortionMatrix();
const double factor3 = ptrAnalysisControl->getTradeOffParameterForRotationsOfDistortionMatrix();
for( int iParamsNotFixed = 0; iParamsNotFixed < numDistortionParamsNotFixed; ++iParamsNotFixed ){
if( ptrObservedData->getTypesOfDistortionParamsNotFixed(iParamsNotFixed) == ObservedDataStationMT::EX_GAIN ||
ptrObservedData->getTypesOfDistortionParamsNotFixed(iParamsNotFixed) == ObservedDataStationMT::EY_GAIN ){
// Gains
constrainingMatrix.setStructureAndAddValueByTripletFormat( iMdl, iMdl, factor2 );
}else{
// Rotations
constrainingMatrix.setStructureAndAddValueByTripletFormat( iMdl, iMdl, factor3 );
}
++iMdl;
}
}
else if( ptrAnalysisControl->getTypeOfDistortion() == AnalysisControl::ESTIMATE_GAINS_ONLY ){
// For gains of distortion matrix
const double factor2 = ptrAnalysisControl->getTradeOffParameterForGainsOfDistortionMatrix();
for( int iParamsNotFixed = 0; iParamsNotFixed < numDistortionParamsNotFixed; ++iParamsNotFixed ){
constrainingMatrix.setStructureAndAddValueByTripletFormat( iMdl, iMdl, factor2 );
++iMdl;
}
}
constrainingMatrix.convertToCRSFormat();
}
// Copy model transforming jacobian matrix
void Inversion::copyModelTransformingJacobian( const int numBlockNotFixed, const int numModel, double* jacobian ) const{
( ResistivityBlock::getInstance() )->copyDerivativeLog10ResistivityWithRespectToX( jacobian );
for( int iMdl = numBlockNotFixed; iMdl < numModel; ++iMdl ){
jacobian[iMdl] = 1.0;
}
}
// Multiply model transforming jacobian matrix
void Inversion::multiplyModelTransformingJacobian( const int numData, const int numModel, const double* jacobian, double* matrix ) const{
int iDat(0);
int offset(0);
int iMdl(0);
#ifdef _USE_OMP
#pragma omp parallel for default(shared) private( iDat, offset, iMdl )
#endif
for( iDat = 0; iDat < numData; ++iDat ){
offset = iDat * numModel;
for( iMdl = 0; iMdl < numModel; ++iMdl ){
matrix[ iMdl + offset ] *= jacobian[iMdl];
}
}
}
// Delete out-of-core file all
void Inversion::deleteOutOfCoreFileAll(){
const ObservedData* const ptrObservedData = ObservedData::getInstance();
2025-02-06 16:26:47 +08:00
const AnalysisControl* const ptrAnalysisControl = AnalysisControl::getInstance();
2021-11-09 00:06:52 +08:00
const int nFreq = ptrObservedData->getNumOfFrequenciesCalculatedByThisPE();
for( int iFreq = 0; iFreq < nFreq; ++iFreq ){
const int freqID = ptrObservedData->getIDsOfFrequenciesCalculatedByThisPE(iFreq);
std::ostringstream fileName;
2025-02-06 16:26:47 +08:00
if (!ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix().empty()) {
#ifdef _LINUX
fileName << ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix() + "\/";
#else
fileName << ptrAnalysisControl->getDirectoryOfOutOfCoreFilesForSensitivityMatrix() + "\\";
#endif
}
2021-11-09 00:06:52 +08:00
fileName << "sensMatFreq" << freqID;
FILE* fp = fopen( fileName.str().c_str(), "rb" );
if( fp != NULL ){// File exists
fclose( fp );
if( remove( fileName.str().c_str() ) != 0 ){
OutputFiles::m_logFile << "Error : Fail to delete " << fileName.str() << std::endl;
exit(1);
}
}
}
}
// Get number of model
int Inversion::getNumberOfModel() const{
int numModel = ( ResistivityBlock::getInstance() )->getNumResistivityBlockNotFixed();
numModel+= ( ObservedData::getInstance() )->getNumDistortionParamsNotFixed();
return numModel;
}
// Output number of model to log file
void Inversion::outputNumberOfModel() const{
const int numBlockNotFixed = ( ResistivityBlock::getInstance() )->getNumResistivityBlockNotFixed();
const int numDistortionParams = ( ObservedData::getInstance() )->getNumDistortionParamsNotFixed();
OutputFiles::m_logFile << "#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << std::endl;
OutputFiles::m_logFile << "# Total number of model parameter : " << getNumberOfModel() << "." << std::endl;
if( numBlockNotFixed > 0 ){
OutputFiles::m_logFile << "# - Number of modifiable resisitivity values : " << numBlockNotFixed << "." << std::endl;
}
if( ( AnalysisControl::getInstance() )->estimateDistortionMatrix() ){
OutputFiles::m_logFile << "# - Number of modifiable distortion parameters : " << numDistortionParams << "." << std::endl;
}
OutputFiles::m_logFile << "#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << std::endl;
}