femtic/src/Forward3DNonConformingHexaElement0thOrder.cpp
2022-02-22 11:37:11 +09:00

2649 lines
124 KiB
C++

//-------------------------------------------------------------------------------------------------------
// 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 "Forward3DNonConformingHexaElement0thOrder.h"
#include "MeshDataNonConformingHexaElement.h"
#include "ResistivityBlock.h"
#include "CommonParameters.h"
#include "OutputFiles.h"
#include "ObservedData.h"
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <assert.h>
const double Forward3DNonConformingHexaElement0thOrder::m_eps = 1.0e-12;
Forward3DNonConformingHexaElement0thOrder::Forward3DNonConformingHexaElement0thOrder():
Forward3D(),
m_slaveDofToMasterDofAndFactors(NULL),
m_hasMadeMapSlaveDofToMasterDofAndFactors(false),
m_IDsAfterDegenerated2AfterConstrained(NULL),
m_numOfEquationDegeneratedAndConstrained(0),
m_solutionVectorDegeneratedAndConstrained(NULL),
m_vectorMPCConstants(NULL)
{
//---------------------------------------------------------------------------
//--- Calculate integral points and weights of two point Gauss quadrature ---
//---------------------------------------------------------------------------
int ip(0);
for( int i = 0; i < m_numGauss; ++i ){
for( int j = 0; j < m_numGauss; ++j ){
for( int k = 0; k < m_numGauss; ++k ){
m_integralPointXi[ip] = CommonParameters::abscissas2Point[i];
m_integralPointEta[ip] = CommonParameters::abscissas2Point[j];
m_integralPointZeta[ip] = CommonParameters::abscissas2Point[k];
m_weights[ip] = CommonParameters::weights2Point[i] * CommonParameters::weights2Point[j] * CommonParameters::weights2Point[k];
++ip;
}
}
}
// Array of reference coord xi values for each node
m_xiAtNode[0] = -1.0;
m_xiAtNode[1] = 1.0;
m_xiAtNode[2] = 1.0;
m_xiAtNode[3] = -1.0;
m_xiAtNode[4] = -1.0;
m_xiAtNode[5] = 1.0;
m_xiAtNode[6] = 1.0;
m_xiAtNode[7] = -1.0;
// Array of reference coord eta values for each node
m_etaAtNode[0] = -1.0;
m_etaAtNode[1] = -1.0;
m_etaAtNode[2] = 1.0;
m_etaAtNode[3] = 1.0;
m_etaAtNode[4] = -1.0;
m_etaAtNode[5] = -1.0;
m_etaAtNode[6] = 1.0;
m_etaAtNode[7] = 1.0;
// Array of reference coord zeta values for each node
m_zetaAtNode[0] = -1.0;
m_zetaAtNode[1] = -1.0;
m_zetaAtNode[2] = -1.0;
m_zetaAtNode[3] = -1.0;
m_zetaAtNode[4] = 1.0;
m_zetaAtNode[5] = 1.0;
m_zetaAtNode[6] = 1.0;
m_zetaAtNode[7] = 1.0;
// Array of reference coord xi values for each edge
m_xiAtEdge[0] = -9999.999;
m_xiAtEdge[1] = -9999.999;
m_xiAtEdge[2] = -9999.999;
m_xiAtEdge[3] = -9999.999;
m_xiAtEdge[4] = -1.0;
m_xiAtEdge[5] = -1.0;
m_xiAtEdge[6] = 1.0;
m_xiAtEdge[7] = 1.0;
m_xiAtEdge[8] = -1.0;
m_xiAtEdge[9] = 1.0;
m_xiAtEdge[10] = -1.0;
m_xiAtEdge[11] = 1.0;
// Array of reference coord eta values for each edge
m_etaAtEdge[0] = -1.0;
m_etaAtEdge[1] = 1.0;
m_etaAtEdge[2] = -1.0;
m_etaAtEdge[3] = 1.0;
m_etaAtEdge[4] = -9999.999;
m_etaAtEdge[5] = -9999.999;
m_etaAtEdge[6] = -9999.999;
m_etaAtEdge[7] = -9999.999;
m_etaAtEdge[8] = -1.0;
m_etaAtEdge[9] = -1.0;
m_etaAtEdge[10] = 1.0;
m_etaAtEdge[11] = 1.0;
// Array of reference coord zeta values for each edge
m_zetaAtEdge[0] = -1.0;
m_zetaAtEdge[1] = -1.0;
m_zetaAtEdge[2] = 1.0;
m_zetaAtEdge[3] = 1.0;
m_zetaAtEdge[4] = -1.0;
m_zetaAtEdge[5] = 1.0;
m_zetaAtEdge[6] = -1.0;
m_zetaAtEdge[7] = 1.0;
m_zetaAtEdge[8] = -9999.999;
m_zetaAtEdge[9] = -9999.999;
m_zetaAtEdge[10] = -9999.999;
m_zetaAtEdge[11] = -9999.999;
m_Fwd2DQuadrilateralElement[MeshData::ZXMinus] = new Forward2DNonConformingQuadrilateralElement0thOrderEdgeBased( MeshData::ZXMinus, CommonParameters::EX_POLARIZATION );
m_Fwd2DQuadrilateralElement[MeshData::ZXPlus ] = new Forward2DNonConformingQuadrilateralElement0thOrderEdgeBased( MeshData::ZXPlus, CommonParameters::EX_POLARIZATION );
m_Fwd2DQuadrilateralElement[MeshData::YZMinus] = new Forward2DNonConformingQuadrilateralElement0thOrderEdgeBased( MeshData::YZMinus, CommonParameters::EY_POLARIZATION );
m_Fwd2DQuadrilateralElement[MeshData::YZPlus ] = new Forward2DNonConformingQuadrilateralElement0thOrderEdgeBased( MeshData::YZPlus, CommonParameters::EY_POLARIZATION );
}
//Destructer
Forward3DNonConformingHexaElement0thOrder::~Forward3DNonConformingHexaElement0thOrder(){
if( m_slaveDofToMasterDofAndFactors != NULL ){
delete [] m_slaveDofToMasterDofAndFactors;
m_slaveDofToMasterDofAndFactors = NULL;
}
if( m_IDsAfterDegenerated2AfterConstrained != NULL ){
delete [] m_IDsAfterDegenerated2AfterConstrained;
m_IDsAfterDegenerated2AfterConstrained = NULL;
}
if( m_solutionVectorDegeneratedAndConstrained != NULL ){
delete [] m_solutionVectorDegeneratedAndConstrained;
m_solutionVectorDegeneratedAndConstrained = NULL;
}
if( m_vectorMPCConstants != NULL ){
delete [] m_vectorMPCConstants;
m_vectorMPCConstants = NULL;
}
}
// Run 3D forward calculation
void Forward3DNonConformingHexaElement0thOrder::forwardCalculation( const double freq, const int iPol ){
setFrequencyCurrent(freq);
setPolarizationCurrent(iPol);
setOrderOfFiniteElement( 0 );
if( m_matrix3DAnalysis.getNumRightHandSideVectors() != 1 ){
m_matrix3DAnalysis.reallocateMemoryForRightHandSideVectors(1);
}
const AnalysisControl* pAnalysisControl = AnalysisControl::getInstance();
if( pAnalysisControl->getBoundaryConditionBottom() != AnalysisControl::BOUNDARY_BOTTOM_PERFECT_CONDUCTOR ){
OutputFiles::m_logFile << "Error : When 0th order 3D edge-based element is used, electric field of the bottom must be zero !" << std::endl;
exit(1);
}
OutputFiles::m_logFile << "# Start 3D forward calculation with the 0th order 3D edge-based element." << pAnalysisControl->outputElapsedTime() << std::endl;
//-----------------------------------------------------------------------------
//--- Set Number of equations and array converting local IDs to global ones ---
//-----------------------------------------------------------------------------
if( !m_hasSetIDsLocal2Global ){
calcArrayConvertLocalID2Global();
}
if( !m_hasIDsGlobal2AfterDegenerated[iPol] ){
calcArrayConvertIDsGlobal2AfterDegenerated();
}
if( !m_hasMadeMapSlaveDofToMasterDofAndFactors ){
makeMapSlaveDofToMasterDofAndFactors();
}
OutputFiles::m_logFile << "# Number of equation = " << m_numOfEquation
<< ", Number of equation after degeneration = " << m_numOfEquationDegenerated
<< ", Number of equation after constraint = " << m_numOfEquationDegeneratedAndConstrained << std::endl;
// Calculate array converting global edge IDs non-zero electric field values specified to the edges
calcArrayConvertIDGlobal2NonZeroValues();
//-----------------------------------------------------------------------
//--- Set matrix structure and analyze the structure by matrix solver ---
//-----------------------------------------------------------------------
if( !m_hasSetIDsLocal2Global ){
OutputFiles::m_logFile << "Error : m_hasSetIDsLocal2Global is NULL !!" << std::endl;
exit(1);
}
if( !m_hasIDsGlobal2AfterDegenerated[iPol] ){
OutputFiles::m_logFile << "Error : m_hasIDsGlobal2AfterDegenerated[iPol] is NULL !!" << std::endl;
exit(1);
}
if( !m_hasMatrixStructureSetAndAnalyzed ){
// If matrix structure has not been set yet, set matrix structure.
OutputFiles::m_logFile << "# Set matrix structure. " << pAnalysisControl->outputElapsedTime() << std::endl;
initializeSparseSolver();
m_matrix3DAnalysis.setDegreeOfEquation( m_numOfEquationDegeneratedAndConstrained );
setNonZeroStrucuture( m_matrix3DAnalysis );
//--- Convert the matrix from the triplet format to the CRS format
if( m_matrix3DAnalysis.hasConvertedToCRSFormat() == false ){
m_matrix3DAnalysis.convertToCRSFormat();
}
//--- Anaysis phase of matrix solver
OutputFiles::m_logFile << "# Anaysis phase of matrix solver for 3D forward calculation."
<< " Polarization : " << iPol << ". "
<< pAnalysisControl->outputElapsedTime() << std::endl;
m_matrix3DAnalysis.analysisPhaseMatrixSolver();
//---- Output memory required to caluculate the 2D analysis
m_matrix3DAnalysis.writeMemoryRequiredByMatrixSolver();
m_hasMatrixStructureSetAndAnalyzed = true;
}
//-------------------------------------------------------
//--- Set values of matrix and right hand side vector ---
//-------------------------------------------------------
OutputFiles::m_logFile << "# Set values of matrix and right hand side vector. " << pAnalysisControl->outputElapsedTime() << std::endl;
m_matrix3DAnalysis.zeroClearNonZeroValues();// Zero clear matrix values
m_matrix3DAnalysis.zeroClearRightHandSideVector();// Zero clear right hand side vector
// Calculate MPC constants
calcMPCConstants();
// Set non-zero values of matrix and right-hande side vector for forward calculation
setNonZeroValues( m_matrix3DAnalysis );
//-----------------------------------------------------
//--- Numrical factorization phase of matrix solver ---
//-----------------------------------------------------
OutputFiles::m_logFile << "# Numerical factorization phase of matrix solver for 3D forward calculation."
<< " Polarization : " << iPol << "."
<< pAnalysisControl->outputElapsedTime() << std::endl;
m_matrix3DAnalysis.factorizationPhaseMatrixSolver();//Numrical factorization phase of matrix solver
//------------------------------------
//--- Solve phase of matrix solver ---
//------------------------------------
//std::complex<double>* solutionConstrained = new std::complex<double>[m_numOfEquationDegeneratedAndConstrained];
if( m_solutionVectorDegeneratedAndConstrained != NULL ){
delete [] m_solutionVectorDegeneratedAndConstrained;
m_solutionVectorDegeneratedAndConstrained = NULL;
}
m_solutionVectorDegeneratedAndConstrained = new std::complex<double>[m_numOfEquationDegeneratedAndConstrained];
OutputFiles::m_logFile << "# Solve phase of matrix solver for 3D forward calculation."
<< " Polarization : " << iPol << "."
<< pAnalysisControl->outputElapsedTime() << std::endl;
m_matrix3DAnalysis.solvePhaseMatrixSolver( m_solutionVectorDegeneratedAndConstrained );//Solve phase of matrix solver
#ifdef _DEBUG_WRITE
for( int i = 0; i < m_numOfEquationDegeneratedAndConstrained; ++i ){
std::cout << "i m_solutionVectorDegeneratedAndConstrained : " << i << " " << m_solutionVectorDegeneratedAndConstrained[i] << std::endl;
}
#endif
if( m_solution != NULL ){
delete [] m_solution;
m_solution = NULL;
}
m_solution = new std::complex<double>[ m_numOfEquation ];
bool* alreadyFound = new bool[ m_numOfEquation ];
for( int i = 0; i < m_numOfEquation; ++i ){
alreadyFound[i] = false;
}
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
for( int iEdge = 0; iEdge < 12; ++iEdge ){
const int iNum = m_IDsLocal2Global[iElem][iEdge];
if( !alreadyFound[iNum] ){
const int iNumDegenerated = m_IDsGlobal2AfterDegenerated[iPol][iNum];
if( iNumDegenerated == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_ZERO_VALUE ){
m_solution[iNum] = std::complex<double>( 0.0, 0.0 );
}else if( iNumDegenerated == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
m_solution[iNum] = m_globalID2NonZeroValues[iNum];
}else{
m_solution[iNum] = m_vectorMPCConstants[iNumDegenerated];
const std::vector< std::pair<int,double> >& masterDofAndFactor = m_slaveDofToMasterDofAndFactors[iNumDegenerated];
for( std::vector< std::pair<int,double> >::const_iterator itr = masterDofAndFactor.begin(); itr != masterDofAndFactor.end(); ++itr ){
const int dof = m_IDsAfterDegenerated2AfterConstrained[itr->first];
const std::complex<double> factor = std::complex<double>(itr->second, 0.0);
m_solution[iNum] += m_solutionVectorDegeneratedAndConstrained[dof] * factor;
}
}
alreadyFound[iNum] = true;
}
}// iEdge
}// iElem
//delete[] solutionConstrained;
delete[] alreadyFound;
#ifdef _DEBUG_WRITE
for( int i = 0; i < m_numOfEquation; ++i ){
std::cout << "i m_solution : " << i << " " << m_solution[i] << std::endl;
}
#endif
// Output EM field vectors
if( pAnalysisControl->writeBinaryFormat() ){// BINARY
outputResultToBinary( (ObservedData::getInstance())->getFreqIDs( freq ), iPol );
}
else{// ASCII
outputResultToVTK();
}
}
// Calculate X component of electric field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldXDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncX( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
return val;
}
// Calculate Y component of electric field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldYDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncY( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
return val;
}
// Calculate Z component of electric field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncZ( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
return val;
}
// Calculate Z component of rotated electric field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueRotatedElectricFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncRotatedZ( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
return val;
}
// Calculate X component of electric field only from the edges on the Earth's surface
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueRotatedElectricFieldNormal( const int iElem, const double xLocal, const double yLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
std::complex<double> val(0.0, 0.0);
Forward3D::Matrix2x2 jacobMat;
const double detJacob = calc2DJacobianMatrixForEarthSurface( iElem, xLocal, yLocal, jacobMat );
Forward3D::Matrix2x2 invJacobMat;
const double invDet = 1.0 / detJacob;
invJacobMat.mat11 = jacobMat.mat22 * invDet;
invJacobMat.mat12 = - jacobMat.mat12 * invDet;
invJacobMat.mat21 = - jacobMat.mat21 * invDet;
invJacobMat.mat22 = jacobMat.mat11 * invDet;
const int iFace = 4;
for( int i = 0; i < 4; ++i ){
const int iEdge = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFace, i );
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, iEdge );
val += m_solution[ m_IDsLocal2Global[iElem][iEdge] ] * std::complex<double>( get2DShapeFuncRotatedForEarthSurface(0.0, 0.0, i, invJacobMat) * length, 0.0 );
}
return val;
}
// Calculate X component of electric field only from the edges on the Earth's surface
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldXDirectionFromEdgesOnEarthSurface( const int iElem, const int iFace, const double uCoord, const double vCoord ) const{
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate Y component of electric field only from the edges on the Earth's surface
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldYDirectionFromEdgesOnEarthSurface( const int iElem, const int iFace, const double uCoord, const double vCoord ) const{
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate tangential electric field directed to X from all edges of owner element
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldTangentialXFromAllEdges( const int iElem, const int iFace, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncX( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
const double dzdx = JacobMat.mat13 / JacobMat.mat11;
const double factor = sqrt( 1.0 + dzdx * dzdx );
return val * std::complex<double>(factor, 0.0);
}
// Calculate tangential electric field directed to Y from all edges of owner element
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldTangentialYFromAllEdges( const int iElem, const int iFace, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncY( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
const double dzdy = JacobMat.mat23 / JacobMat.mat22;
const double factor = sqrt( 1.0 + dzdy * dzdy );
return val * std::complex<double>(factor, 0.0);
}
// Calculate tangential electric field directed to X
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldTangentialX( const int iElem, const int iFace, const double uCoord, const double vCoord ) const{
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate tangential electric field directed to Y
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueElectricFieldTangentialY( const int iElem, const int iFace, const double uCoord, const double vCoord ) const{
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate X component of magnetic field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueMagneticFieldXDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncRotatedX( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
val /= std::complex<double>(0.0, omega * CommonParameters::mu);
return val;
}
// Calculate Y component of magnetic field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueMagneticFieldYDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
std::complex<double> val(0.0, 0.0);
for( int i = 0; i < 12; ++i ){
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
val += m_solution[ m_IDsLocal2Global[iElem][i] ] * std::complex<double>( getShapeFuncRotatedY( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 );
}
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
val /= std::complex<double>(0.0, omega * CommonParameters::mu);
return val;
}
// Calculate Z component of magnetic field
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcValueMagneticFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal ) const{
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
return calcValueRotatedElectricFieldZDirection( iElem, xLocal, yLocal, zLocal ) / std::complex<double>(0.0, omega * CommonParameters::mu);
}
// Calculate interpolator vector of X component of electric field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldXDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncX( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of Y component of electric field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldYDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncY( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of Z component of electric field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncZ( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of Z component of rotated electric field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfRotatedElectricFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncRotatedZ( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of X component of electric field only from the edges on the Earth's surface
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfRotatedElectricFieldNormal( const int iElem, const double xLocal, const double yLocal,
const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix2x2 jacobMat;
const double detJacob = calc2DJacobianMatrixForEarthSurface( iElem, xLocal, yLocal, jacobMat );
Forward3D::Matrix2x2 invJacobMat;
const double invDet = 1.0 / detJacob;
invJacobMat.mat11 = jacobMat.mat22 * invDet;
invJacobMat.mat12 = - jacobMat.mat12 * invDet;
invJacobMat.mat21 = - jacobMat.mat21 * invDet;
invJacobMat.mat22 = jacobMat.mat11 * invDet;
const int iPol = getPolarizationCurrent();
const int iFace = 4;
for( int i = 0; i < 4; ++i ){
const int iEdge = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFace, i );
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][iEdge] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, iEdge );
//val += m_solution[ m_IDsLocal2Global[iElem][iEdge] ] * std::complex<double>( get2DShapeFuncRotatedForEarthSurface(0.0, 0.0, i, invJacobMat) * length, 0.0 );
const std::complex<double> val = std::complex<double>( get2DShapeFuncRotatedForEarthSurface(0.0, 0.0, i, invJacobMat) * length, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of X component of electric field only from the edges on the Earth's surface
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldXDirectionFromEdgesOnEarthSurface( const int iElem, const int iFace, const double uCoord, const double vCoord, const int irhs, const std::complex<double>& factor ){
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate interpolator vector of Y component of electric field only from the edges on the Earth's surface
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldYDirectionFromEdgesOnEarthSurface( const int iElem, const int iFace, const double uCoord, const double vCoord, const int irhs, const std::complex<double>& factor ){
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate interpolator vector of tangential electric field directed to X from all edges
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldTangentialXFromAllEdges( const int iElem, const int iFace, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double dzdx = JacobMat.mat13 / JacobMat.mat11;
const double dLengdx = sqrt( 1.0 + dzdx * dzdx );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncX( xLocal, yLocal, zLocal, i, invJacobMat ) * length * dLengdx, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of tangential electric field directed to Y from all edges
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldTangentialYFromAllEdges( const int iElem, const int iFace, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double dzdy = JacobMat.mat23 / JacobMat.mat22;
const double dLengdy = sqrt( 1.0 + dzdy * dzdy );
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncY( xLocal, yLocal, zLocal, i, invJacobMat ) * length * dLengdy, 0.0 ) * factor;
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of tangential electric field directed to X
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldTangentialX( const int iElem, const int iFace, const double uCoord, const double vCoord, const int irhs, const std::complex<double>& factor ){
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate interpolator vector of tangential electric field directed to Y
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfElectricFieldTangentialY( const int iElem, const int iFace, const double uCoord, const double vCoord, const int irhs, const std::complex<double>& factor ){
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Calculate interpolator vector of X component of magnetic field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfMagneticFieldXDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncRotatedX( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor
/ std::complex<double>(0.0, omega * CommonParameters::mu);
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of Y component of magnetic field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfMagneticFieldYDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
assert( m_solution != NULL );
assert( m_IDsLocal2Global != NULL );
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( iElem, xLocal, yLocal, zLocal, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
const int iPol = getPolarizationCurrent();
for( int i = 0; i < 12; ++i ){
const int irow = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][i] ];
if( irow < 0 ){
continue;
}
const double length = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( iElem, i );
const std::complex<double> val = std::complex<double>( getShapeFuncRotatedY( xLocal, yLocal, zLocal, i, invJacobMat ) * length, 0.0 ) * factor
/ std::complex<double>(0.0, omega * CommonParameters::mu);
addValuesToRhsVectorsByConsideringMPC( irow, irhs, val );
}
}
// Calculate interpolator vector of Z component of magnetic field
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfMagneticFieldZDirection( const int iElem, const double xLocal, const double yLocal, const double zLocal, const int irhs, const std::complex<double>& factor ){
const double omega = 2.0 * CommonParameters::PI * getFrequencyCurrent();//Angular frequency
const std::complex<double> factorMod = factor / std::complex<double>(0.0, omega * CommonParameters::mu);
calcInterpolatorVectorOfRotatedElectricFieldZDirection( iElem, xLocal, yLocal, zLocal, irhs, factorMod );
}
// Calculate interpolator vector of difference of voltage
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfVoltageDifference( const int nElem, const int* elememtsIncludingDipole,
const CommonParameters::locationXY* localCoordinateValuesStartPoint, const CommonParameters::locationXY* localCoordinateValuesEndPoint, const int irhs ){
assert( m_IDsLocal2Global != NULL );
const int iPol = getPolarizationCurrent();
assert( m_IDsGlobal2AfterDegenerated[iPol] != NULL );
for( int ielem = 0; ielem < nElem; ++ielem ){
const int elemID = elememtsIncludingDipole[ielem];
const CommonParameters::locationXY startCoord = localCoordinateValuesStartPoint[ielem];
const CommonParameters::locationXY endCoord = localCoordinateValuesEndPoint[ielem];
bool rotationDirectionPlus = true;
CommonParameters::locationXY sharedPoint = {0.0, 0.0};
const bool integralXCompFirst = doesIntegralXCompFirst( startCoord, endCoord, rotationDirectionPlus, sharedPoint );
const double lengthX = m_MeshDataNonConformingHexaElement.getEdgeLengthX(elemID);
const double lengthY = m_MeshDataNonConformingHexaElement.getEdgeLengthY(elemID);
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( elemID, 0.0, 0.0, -1.0, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double dzdx = JacobMat.mat13 / JacobMat.mat11;
const double factorX = sqrt( 1.0 + dzdx * dzdx );
const double dzdy = JacobMat.mat23 / JacobMat.mat22;
const double factorY = sqrt( 1.0 + dzdy * dzdy );
const double xCoordDifferenceOfSegment = (endCoord.X - startCoord.X) * lengthX * 0.5;
const double yCoordDifferenceOfSegment = (endCoord.Y - startCoord.Y) * lengthY * 0.5;
if( integralXCompFirst ){
//voltageDifference -= std::complex<double>( xCoordDifferenceOfSegment * factorX, 0.0 ) * calcValueElectricFieldTangentialXFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0 );// Since electric field is constant on edges
//voltageDifference -= std::complex<double>( yCoordDifferenceOfSegment * factorY, 0.0 ) * calcValueElectricFieldTangentialYFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0 );// Since electric field is constant on edges
calcInterpolatorVectorOfElectricFieldTangentialXFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0, irhs, std::complex<double>( - xCoordDifferenceOfSegment * factorX, 0.0 ) );
calcInterpolatorVectorOfElectricFieldTangentialYFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0, irhs, std::complex<double>( - yCoordDifferenceOfSegment * factorY, 0.0 ) );
}else{
//voltageDifference -= std::complex<double>( yCoordDifferenceOfSegment * factorY, 0.0 ) * calcValueElectricFieldTangentialYFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0 );// Since electric field is constant on edges
//voltageDifference -= std::complex<double>( xCoordDifferenceOfSegment * factorX, 0.0 ) * calcValueElectricFieldTangentialXFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0 );// Since electric field is constant on edges
calcInterpolatorVectorOfElectricFieldTangentialYFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0, irhs, std::complex<double>( - yCoordDifferenceOfSegment * factorY, 0.0 ) );
calcInterpolatorVectorOfElectricFieldTangentialXFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0, irhs, std::complex<double>( - xCoordDifferenceOfSegment * factorX, 0.0 ) );
}
const double areaFraction = 0.25 * fabs( (endCoord.X - startCoord.X) * (endCoord.Y - startCoord.Y) );
const double area = m_MeshDataNonConformingHexaElement.calcAreaOfFace(elemID, 4);
double areaWithSign = 0.5 * area * areaFraction;
if( !rotationDirectionPlus ){
areaWithSign *= -1.0;
}
//voltageDifference += calcValueRotatedElectricFieldNormal(elemID, 0.0, 0.0) * areaWithSign;// Since magnetic field is constant in the area
calcInterpolatorVectorOfRotatedElectricFieldNormal( elemID, 0.0, 0.0, irhs, areaWithSign );
}
}
// Calculate interpolator vector of difference of voltage
void Forward3DNonConformingHexaElement0thOrder::calcInterpolatorVectorOfVoltageDifference( const int nElem, const int* elememtsIncludingDipole, const int* const facesIncludingDipole,
const CommonParameters::AreaCoords* const areaCoordValStartPoint, const CommonParameters::AreaCoords* const areaCoordValEndPoint, const int irhs ){
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Set non-zero strucuture of matrix for forward calculation
void Forward3DNonConformingHexaElement0thOrder::setNonZeroStrucuture( ComplexSparseSquareSymmetricMatrix& matrix ){
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
const int iPol = getPolarizationCurrent();
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
const int elemID = iElem;
for( int iEdge1 = 0; iEdge1 < 12; ++iEdge1 ){
const int row = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge1] ];
if( row < 0 ){
continue;
}
for( int iEdge2 = 0; iEdge2 < 12; ++iEdge2 ){
const int col = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge2] ];
if( col < 0 ){
continue;
}
std::vector< std::pair<int,double> >& rowMasters= m_slaveDofToMasterDofAndFactors[row];
std::vector< std::pair<int,double> >& colMasters= m_slaveDofToMasterDofAndFactors[col];
for( std::vector< std::pair<int,double> >::const_iterator itrRow = rowMasters.begin(); itrRow != rowMasters.end(); ++itrRow ){
const int rowMod = m_IDsAfterDegenerated2AfterConstrained[itrRow->first];
for( std::vector< std::pair<int,double> >::const_iterator itrCol = colMasters.begin(); itrCol != colMasters.end(); ++itrCol ){
const int colMod = m_IDsAfterDegenerated2AfterConstrained[itrCol->first];
if( colMod >= rowMod ){// Store only upper triangle part
matrix.setStructureByTripletFormat( rowMod, colMod );
}
}
}
}// iEdge2
}// iEdge1
}
}
// Set non-zero values of matrix and right-hande side vector for forward calculation
void Forward3DNonConformingHexaElement0thOrder::setNonZeroValues( ComplexSparseSquareSymmetricMatrix& matrix ){
#ifdef _DEBUG_WRITE
ComplexSparseSquareSymmetricMatrix matrixTemp(m_numOfEquationDegenerated);
#endif
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
const int iPol = getPolarizationCurrent();
const double freq = getFrequencyCurrent();
const double ln10 = 2.30258509299405;
const double omega = 2.0 * CommonParameters::PI * freq;//Angular frequency
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
const int elemID = iElem;
//--- Calculate omega * mu * sigma
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(elemID);
const double factor1 = 1.0;
const std::complex<double> factor2 = std::complex<double>( 0.0, omega * CommonParameters::mu * sigma );// exp(-i*omega*t) form
double length[12];
for( int i = 0; i < 12; ++i ){
length[i] = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( elemID, i );
}
for( int iEdge1 = 0; iEdge1 < 12; ++iEdge1 ){
const int row = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge1] ];
if( row < 0 ){
continue;
}
for( int iEdge2 = 0; iEdge2 < 12; ++iEdge2 ){
const int col = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge2] ];
if( col <= Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_ZERO_VALUE ){
continue;
}
double integral1 = 0.0;
double integral2 = 0.0;
for( int ip = 0; ip < m_numIntegralPoints; ++ip ){
const double xi = m_integralPointXi[ip];
const double eta = m_integralPointEta[ip];
const double zeta = m_integralPointZeta[ip];
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( elemID, xi, eta, zeta, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
integral1 += ( getShapeFuncRotatedX( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedX( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncRotatedY( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedY( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncRotatedZ( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedZ( xi, eta, zeta, iEdge2, invJacobMat ) )
* detJacob * m_weights[ip];
integral2 += ( getShapeFuncX( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncX( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncY( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncY( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncZ( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncZ( xi, eta, zeta, iEdge2, invJacobMat ) )
* detJacob * m_weights[ip];
}
integral1 *= length[iEdge1] * length[iEdge2];
integral2 *= length[iEdge1] * length[iEdge2];
const std::complex<double> val = std::complex<double>( integral1 * factor1 , 0.0 ) - std::complex<double>( integral2, 0.0 ) * factor2;// exp(-i*omega*t) form
//#ifdef _DEBUG_WRITE
// if( col == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
// matrixTemp.addRightHandSideVector( row, -val * m_globalID2NonZeroValues[ m_IDsLocal2Global[elemID][iEdge2] ] );// Add to right hand side vector
// }else if( col >= row ){// Store only upper triangle part
// matrixTemp.setStructureAndAddValueByTripletFormat( row, col, val );// Add to matrix
// }
//#endif
const std::vector< std::pair<int,double> >& rowMasters= m_slaveDofToMasterDofAndFactors[row];
for( std::vector< std::pair<int,double> >::const_iterator itrRow = rowMasters.begin(); itrRow != rowMasters.end(); ++itrRow ){
const int rowMod = m_IDsAfterDegenerated2AfterConstrained[itrRow->first];
const std::complex<double> valMod = val * std::complex<double>(itrRow->second, 0.0);
if( col == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
// Add to right hand side vector
matrix.addRightHandSideVector( rowMod, -valMod * m_globalID2NonZeroValues[ m_IDsLocal2Global[elemID][iEdge2] ] );
}else{
// Add to right hand side vector corresponding to MPC constants
matrix.addRightHandSideVector( rowMod, valMod * m_vectorMPCConstants[col] );
const std::vector< std::pair<int,double> >& colMasters= m_slaveDofToMasterDofAndFactors[col];
for( std::vector< std::pair<int,double> >::const_iterator itrCol = colMasters.begin(); itrCol != colMasters.end(); ++itrCol ){
const int colMod = m_IDsAfterDegenerated2AfterConstrained[itrCol->first];
const std::complex<double> valModMod = valMod * std::complex<double>(itrCol->second, 0.0);
if( colMod >= rowMod ){// Store only upper triangle part
const int loc = matrix.checkAndGetLocationNonZeroValue( rowMod, colMod );
matrix.addNonZeroValuesWithoutSearchingLocation( loc, valModMod );// Add to matrix
}
}
}
}
}// iEdge2
}// iEdge1
}
#ifdef _DEBUG_WRITE
std::cout << "matrix" << std::endl;
matrix.debugWriteMatrix();
matrix.debugWriteRightHandSide();
#endif
//#ifdef _DEBUG_WRITE
// matrixTemp.transformationByConstraintMatrix( m_numOfEquationDegeneratedAndConstrained, m_transposedConstraintMatrix );
// matrixTemp.convertToCRSFormat();
// std::cout << "matrixTemp" << std::endl;
// matrixTemp.debugWriteMatrix();
// matrixTemp.debugWriteRightHandSide();
//#endif
}
// Calculate vector x of the reciprocity algorithm of Rodi (1976)
void Forward3DNonConformingHexaElement0thOrder::calVectorXOfReciprocityAlgorithm( const std::complex<double>* const vecIn, const int blkID, std::complex<double>* const vecOut, std::vector<int>& nonZeroRows ){
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
if( pResistivityBlock->isFixedResistivityValue(blkID) ){
return;
}
const int iPol = getPolarizationCurrent();
const double freq = getFrequencyCurrent();
const double ln10 = 2.30258509299405;
const double omega = 2.0 * CommonParameters::PI * freq;//Angular frequency
const std::vector< std::pair<int,double> >& mdl2Elem = pResistivityBlock->getBlockID2Elements(blkID);
const int nElem = static_cast<int>( mdl2Elem.size() );
for( int iElem = 0; iElem < nElem; ++iElem ){
// [Attention] : You must use elemID instead of iElem from this line
const int elemID = mdl2Elem[iElem].first;
//----- debug >>>>>
#ifdef _DEBUG_WRITE
std::cout << "blkID iElem elemID = " << blkID << " " << iElem << " " << elemID << std::endl;
#endif
//----- debug <<<<<
//--- Calculate omega * mu * sigma
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(elemID);
const double factor1 = 0.0;
const std::complex<double> factor2 = std::complex<double>(0.0, - omega * CommonParameters::mu * sigma * ln10 * mdl2Elem[iElem].second);// exp(-i*omega*t) form
double length[12];
for( int i = 0; i < 12; ++i ){
length[i] = m_MeshDataNonConformingHexaElement.calcEdgeLengthFromElementAndEdge( elemID, i );
}
for( int iEdge1 = 0; iEdge1 < 12; ++iEdge1 ){
const int row = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge1] ];
if( row < 0 ){
continue;
}
for( int iEdge2 = 0; iEdge2 < 12; ++iEdge2 ){
const int col = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemID][iEdge2] ];
if( col <= Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_ZERO_VALUE ){
continue;
}
double integral1 = 0.0;
double integral2 = 0.0;
for( int ip = 0; ip < m_numIntegralPoints; ++ip ){
const double xi = m_integralPointXi[ip];
const double eta = m_integralPointEta[ip];
const double zeta = m_integralPointZeta[ip];
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( elemID, xi, eta, zeta, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
integral1 += ( getShapeFuncRotatedX( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedX( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncRotatedY( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedY( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncRotatedZ( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncRotatedZ( xi, eta, zeta, iEdge2, invJacobMat ) )
* detJacob * m_weights[ip];
integral2 += ( getShapeFuncX( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncX( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncY( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncY( xi, eta, zeta, iEdge2, invJacobMat )
+ getShapeFuncZ( xi, eta, zeta, iEdge1, invJacobMat )
* getShapeFuncZ( xi, eta, zeta, iEdge2, invJacobMat ) )
* detJacob * m_weights[ip];
}
integral1 *= length[iEdge1] * length[iEdge2];
integral2 *= length[iEdge1] * length[iEdge2];
const std::complex<double> val = std::complex<double>( integral1 * factor1 , 0.0 ) - std::complex<double>( integral2, 0.0 ) * factor2;// exp(-i*omega*t) form
//#ifdef _DEBUG_WRITE
// if( col == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
// matrixTemp.addRightHandSideVector( row, -val * m_globalID2NonZeroValues[ m_IDsLocal2Global[elemID][iEdge2] ] );// Add to right hand side vector
// }else if( col >= row ){// Store only upper triangle part
// matrixTemp.setStructureAndAddValueByTripletFormat( row, col, val );// Add to matrix
// }
//#endif
const std::vector< std::pair<int,double> >& rowMasters= m_slaveDofToMasterDofAndFactors[row];
for( std::vector< std::pair<int,double> >::const_iterator itrRow = rowMasters.begin(); itrRow != rowMasters.end(); ++itrRow ){
const int rowMod = m_IDsAfterDegenerated2AfterConstrained[itrRow->first];
const std::complex<double> valMod = val * std::complex<double>(itrRow->second, 0.0);
if( col == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
nonZeroRows.push_back(rowMod);
// Add to right hand side vector
vecOut[rowMod] -= valMod * m_globalID2NonZeroValues[ m_IDsLocal2Global[elemID][iEdge2] ];
}else{
nonZeroRows.push_back(rowMod);
// Add to right hand side vector corresponding to MPC constants
vecOut[rowMod] += valMod * m_vectorMPCConstants[col];
const std::vector< std::pair<int,double> >& colMasters= m_slaveDofToMasterDofAndFactors[col];
for( std::vector< std::pair<int,double> >::const_iterator itrCol = colMasters.begin(); itrCol != colMasters.end(); ++itrCol ){
const int colMod = m_IDsAfterDegenerated2AfterConstrained[itrCol->first];
const std::complex<double> valModMod = valMod * std::complex<double>(itrCol->second, 0.0);
vecOut[rowMod] -= valModMod * vecIn[colMod];
}
}
}
}// iEdge2
}// iEdge1
}
std::sort(nonZeroRows.begin(), nonZeroRows.end());
nonZeroRows.erase( std::unique( nonZeroRows.begin(), nonZeroRows.end() ), nonZeroRows.end() );
}
// Copy solution vector degenerated
void Forward3DNonConformingHexaElement0thOrder::copySolutionVectorDegenerated( const int iPol, std::complex<double>* solutionVector ) const{
for( int i = 0; i < m_numOfEquationDegeneratedAndConstrained; ++i ){
solutionVector[i] = m_solutionVectorDegeneratedAndConstrained[i];
}
}
// Call function inputMeshData of the class MeshData
void Forward3DNonConformingHexaElement0thOrder::callInputMeshData(){
m_MeshDataNonConformingHexaElement.inputMeshData();
}
// Get pointer to the class MeshData
const MeshData* Forward3DNonConformingHexaElement0thOrder::getPointerToMeshData() const{
return static_cast<const MeshData*>( &m_MeshDataNonConformingHexaElement ) ;
}
// Get pointer to the class MeshDataNonConformingHexaElement
const MeshDataNonConformingHexaElement* Forward3DNonConformingHexaElement0thOrder::getPointerToMeshDataNonConformingHexaElement() const{
return &m_MeshDataNonConformingHexaElement;
}
// Calculate difference of voltage for brick element
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcVoltageDifference( const int nElem, const int* elememtsIncludingDipole,
const CommonParameters::locationXY* localCoordinateValuesStartPoint, const CommonParameters::locationXY* localCoordinateValuesEndPoint ) const{
std::complex<double> voltageDifference = std::complex<double>(0.0, 0.0);
for( int ielem = 0; ielem < nElem; ++ielem ){
const int elemID = elememtsIncludingDipole[ielem];
const CommonParameters::locationXY startCoord = localCoordinateValuesStartPoint[ielem];
const CommonParameters::locationXY endCoord = localCoordinateValuesEndPoint[ielem];
bool rotationDirectionPlus = true;
CommonParameters::locationXY sharedPoint = {0.0, 0.0};
const bool integralXCompFirst = doesIntegralXCompFirst( startCoord, endCoord, rotationDirectionPlus, sharedPoint );
const double lengthX = m_MeshDataNonConformingHexaElement.getEdgeLengthX(elemID);
const double lengthY = m_MeshDataNonConformingHexaElement.getEdgeLengthY(elemID);
Forward3D::Matrix3x3 JacobMat;
const double detJacob = calcJacobianMatrix( elemID, 0.0, 0.0, -1.0, JacobMat );
Forward3D::Matrix3x3 invJacobMat;
calcInverseOfJacobianMatrix( JacobMat, detJacob, invJacobMat );
const double dzdx = JacobMat.mat13 / JacobMat.mat11;
const double factorX = sqrt( 1.0 + dzdx * dzdx );
const double dzdy = JacobMat.mat23 / JacobMat.mat22;
const double factorY = sqrt( 1.0 + dzdy * dzdy );
const double xCoordDifferenceOfSegment = (endCoord.X - startCoord.X) * lengthX * 0.5;
const double yCoordDifferenceOfSegment = (endCoord.Y - startCoord.Y) * lengthY * 0.5;
if( integralXCompFirst ){
voltageDifference -= std::complex<double>( xCoordDifferenceOfSegment * factorX, 0.0 ) * calcValueElectricFieldTangentialXFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0 );// Since electric field is constant on edges
voltageDifference -= std::complex<double>( yCoordDifferenceOfSegment * factorY, 0.0 ) * calcValueElectricFieldTangentialYFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0 );// Since electric field is constant on edges
}else{
voltageDifference -= std::complex<double>( yCoordDifferenceOfSegment * factorY, 0.0 ) * calcValueElectricFieldTangentialYFromAllEdges( elemID, 4, startCoord.X, startCoord.Y, -1.0 );// Since electric field is constant on edges
voltageDifference -= std::complex<double>( xCoordDifferenceOfSegment * factorX, 0.0 ) * calcValueElectricFieldTangentialXFromAllEdges( elemID, 4, endCoord.X, endCoord.Y, -1.0 );// Since electric field is constant on edges
}
#ifdef _DEBUG_WRITE
std::cout << "voltageDifference : " << voltageDifference << std::endl;
#endif
const double areaFraction = 0.25 * fabs( (endCoord.X - startCoord.X) * (endCoord.Y - startCoord.Y) );
const double area = m_MeshDataNonConformingHexaElement.calcAreaOfFace(elemID, 4);
double areaWithSign = 0.5 * area * areaFraction;
if( !rotationDirectionPlus ){
areaWithSign *= -1.0;
}
#ifdef _DEBUG_WRITE
const std::complex<double> tmp1 = calcValueRotatedElectricFieldNormal(elemID, 0.0, 0.0);
const std::complex<double> tmp2 = calcValueRotatedElectricFieldZDirection(elemID, 0.0, 0.0, -1.0);
#endif
voltageDifference += calcValueRotatedElectricFieldNormal(elemID, 0.0, 0.0) * areaWithSign;// Since magnetic field is constant in the area
#ifdef _DEBUG_WRITE
std::cout << "areaWithSign calcValueRotatedElectricFieldZDirection : " << areaWithSign << " " << tmp1 << std::endl;
std::cout << "voltageDifference total : " << voltageDifference << std::endl;
#endif
}
return voltageDifference;
}
// Calculate difference of voltage for tetra element
std::complex<double> Forward3DNonConformingHexaElement0thOrder::calcVoltageDifference( const int nElem, const int* const elememtsIncludingDipole, const int* const facesIncludingDipole,
const CommonParameters::AreaCoords* const areaCoordValStartPoint, const CommonParameters::AreaCoords* const areaCoordValEndPoint ) const{
OutputFiles::m_logFile << "Error : " << __FUNCTION__ << " is not implemented" << std::endl;
exit(1);
}
// Get total number of equations finally solved
int Forward3DNonConformingHexaElement0thOrder::getNumOfEquationFinallySolved() const{
return m_numOfEquationDegeneratedAndConstrained;
}
// Calculate array converting local IDs to global ones
void Forward3DNonConformingHexaElement0thOrder::calcArrayConvertLocalID2Global(){
typedef std::pair< int, int > NodeIDPair;
typedef std::pair< int, int > ElemAndEdgeID;
typedef std::pair< NodeIDPair, ElemAndEdgeID > InputedDataType;
std::vector< InputedDataType > workVector;
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
for( int iEdge = 0; iEdge < 12; ++iEdge ){
const int nodeID0 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( iElem, iEdge, 0 );
const int nodeID1 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( iElem, iEdge, 1 );
const NodeIDPair nodePairCur = nodeID1 > nodeID0 ? std::make_pair( nodeID0, nodeID1 ) : std::make_pair( nodeID1, nodeID0 );
const ElemAndEdgeID elemAndEdgeIDCur = std::make_pair( iElem, iEdge );
workVector.push_back( InputedDataType( std::pair< NodeIDPair, ElemAndEdgeID >(nodePairCur, elemAndEdgeIDCur) ) );
}
}
std::sort( workVector.begin(), workVector.end() );
// Allocate memory to m_IDsLocal2Global ---
if( m_IDsLocal2Global != NULL ){
const int nElem = sizeof( m_IDsLocal2Global ) / sizeof( m_IDsLocal2Global[0] );
for( int iElem = 0; iElem < nElem; ++iElem ){
delete [] m_IDsLocal2Global[iElem];
}
delete [] m_IDsLocal2Global;
m_IDsLocal2Global = NULL;
}
m_IDsLocal2Global = new int*[nElem];
for( int iElem = 0; iElem < nElem; ++iElem ){
m_IDsLocal2Global[iElem] = new int[12];
}
//-----------------------------------------
std::pair<int, int> nodePairPre;
int edgeIDGlobal(-1);
std::vector<InputedDataType>::const_iterator itrEnd = workVector.end();
for( std::vector<InputedDataType>::const_iterator itr = workVector.begin(); itr != itrEnd; ++itr ){
const int elemIDGlobal = (*itr).second.first;
const int edgeIDLocal = (*itr).second.second;
const int nodePairCur0 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( elemIDGlobal, edgeIDLocal, 0 );
const int nodePairCur1 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( elemIDGlobal, edgeIDLocal, 1 );
if( ( nodePairCur0 == nodePairPre.first && nodePairCur1 == nodePairPre.second ) ||
( nodePairCur0 == nodePairPre.second && nodePairCur1 == nodePairPre.first ) ){// Same edge with privious one
}else{// New edge
++edgeIDGlobal;
nodePairPre.first = nodePairCur0;
nodePairPre.second = nodePairCur1;
}
m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] = edgeIDGlobal;
#ifdef _DEBUG_WRITE
std::cout << "nodePairCur0 nodePairCur1 m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] : " << nodePairCur0 << " " << nodePairCur1 << " -> " << m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] << std::endl;
#endif
}
m_numOfEquation = edgeIDGlobal + 1;
m_hasSetIDsLocal2Global = true;
}
// Calculate array converting global IDs to the ones after degeneration
void Forward3DNonConformingHexaElement0thOrder::calcArrayConvertIDsGlobal2AfterDegenerated(){
if( !m_hasSetIDsLocal2Global ){
OutputFiles::m_logFile << "Error : Array converting local edge IDs to global ones has not been set yet." << std::endl;
exit(1);
}
const int iPol = getPolarizationCurrent();
if( m_IDsGlobal2AfterDegenerated[iPol] != NULL ){
delete [] m_IDsGlobal2AfterDegenerated[iPol];
m_IDsGlobal2AfterDegenerated[iPol] = NULL;
}
m_IDsGlobal2AfterDegenerated[iPol] = new int[m_numOfEquation];
for( int i = 0; i < m_numOfEquation; ++i ){
m_IDsGlobal2AfterDegenerated[iPol][i] = 0;
}
int planesWithNonzeroValues[3] = { -1, -1, -1 };
int planesWithZeroValues[3] = { -1, -1, -1 };
if( iPol == CommonParameters::EX_POLARIZATION ){// Ex Polarization
planesWithNonzeroValues[0] = MeshData::ZXMinus;
planesWithNonzeroValues[1] = MeshData::ZXPlus;
planesWithNonzeroValues[2] = MeshData::XYMinus;
planesWithZeroValues[0] = MeshData::YZMinus;
planesWithZeroValues[1] = MeshData::YZPlus;
planesWithZeroValues[2] = MeshData::XYPlus;
}else{// Ey Polarization
planesWithNonzeroValues[0] = MeshData::YZMinus;
planesWithNonzeroValues[1] = MeshData::YZPlus;
planesWithNonzeroValues[2] = MeshData::XYMinus;
planesWithZeroValues[0] = MeshData::ZXMinus;
planesWithZeroValues[1] = MeshData::ZXPlus;
planesWithZeroValues[2] = MeshData::XYPlus;
}
// Planes on which dirichlet boundary condition with non-zero values is specified
for( int iPlane = 0; iPlane < 3; ++iPlane ){
const int planeID = planesWithNonzeroValues[iPlane];
const int nElemOnPlane = m_MeshDataNonConformingHexaElement.getNumElemOnBoundaryPlanes( planeID );
//#ifdef _DEBUG_WRITE
// std::cout << "planeID " << planeID << std::endl;
//#endif
for( int iElem = 0; iElem < nElemOnPlane; ++iElem ){
const int elemIDGlobal = m_MeshDataNonConformingHexaElement.getElemBoundaryPlanes( planeID, iElem );
const int faceIDLocal = m_MeshDataNonConformingHexaElement.getFaceIDLocalFromElementBoundaryPlanes( planeID, iElem );
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( faceIDLocal, iEdge );
//#ifdef _DEBUG_WRITE
// std::cout << "elemIDGlobal edgeIDLocal m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] : " << elemIDGlobal << " " << edgeIDLocal << " " << m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] << std::endl;
//#endif
m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] ] = Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE;
}
}
}
// Planes on which dirichlet boundary condition with zero values is specified
for( int iPlane = 0; iPlane < 3; ++iPlane ){
const int planeID = planesWithZeroValues[iPlane];
const int nElemOnPlane = m_MeshDataNonConformingHexaElement.getNumElemOnBoundaryPlanes( planeID );
for( int iElem = 0; iElem < nElemOnPlane; ++iElem ){
const int elemIDGlobal = m_MeshDataNonConformingHexaElement.getElemBoundaryPlanes( planeID, iElem );
const int faceIDLocal = m_MeshDataNonConformingHexaElement.getFaceIDLocalFromElementBoundaryPlanes( planeID, iElem );
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( faceIDLocal, iEdge );
m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDGlobal][edgeIDLocal] ] = Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_ZERO_VALUE;
}
}
}
int icount(-1);
for( int i = 0; i < m_numOfEquation; ++i ){
if( m_IDsGlobal2AfterDegenerated[iPol][i] < 0 ){
continue;
}
m_IDsGlobal2AfterDegenerated[iPol][i] = ++icount;
}
m_numOfEquationDegenerated = icount + 1;
m_hasIDsGlobal2AfterDegenerated[iPol] = true;
#ifdef _DEBUG_WRITE
for( int i = 0; i < m_numOfEquation; ++i ){
std::cout << "i m_IDsGlobal2AfterDegenerated[iPol][i] : " << i << " " << m_IDsGlobal2AfterDegenerated[iPol][i] << std::endl;
}
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
for( int iEdge = 0; iEdge < 12; ++iEdge ){
std::cout << "iElem iEdge m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][iEdge] ] : " << iElem << " " << iEdge << " " << m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[iElem][iEdge] ] << std::endl;
}
}
#endif
}
// Calculate array converting global edge IDs non-zero electric field values specified to the edges
void Forward3DNonConformingHexaElement0thOrder::calcArrayConvertIDGlobal2NonZeroValues(){
if( m_hasSetIDsLocal2Global == false ){
OutputFiles::m_logFile << "Error : Array converting local edge IDs to global ones has not been set yet." << std::endl;
exit(1);
}
const int iPol = getPolarizationCurrent();
if( m_hasIDsGlobal2AfterDegenerated[iPol] == false ){
OutputFiles::m_logFile << "Error : Array converting global IDs to the ones after degeneration has not been set yet." << std::endl;
exit(1);
}
//----------------------------------------------------------------------------
//--- Calculating EM field of the boundary planes with 2D forward analysis ---
//----------------------------------------------------------------------------
const double freq = getFrequencyCurrent();
OutputFiles::m_logFile << "# Calculating EM field of the boundary planes with 2D forward analysis." << std::endl;
if( iPol == CommonParameters::EX_POLARIZATION ){// Ex polarization
OutputFiles::m_logFile << "#-----------------------------[ Boundary Plane " << MeshData::ZXMinus << " ]-----------------------------" << std::endl;
m_Fwd2DQuadrilateralElement[MeshData::ZXMinus]->calcEMFieldsOfBoundaryPlanes( freq, &m_MeshDataNonConformingHexaElement );
OutputFiles::m_logFile << "#-----------------------------[ Boundary Plane " << MeshData::ZXPlus << " ]-----------------------------" << std::endl;
m_Fwd2DQuadrilateralElement[MeshData::ZXPlus]->calcEMFieldsOfBoundaryPlanes( freq, &m_MeshDataNonConformingHexaElement );
}else{// Ey polarization
OutputFiles::m_logFile << "#-----------------------------[ Boundary Plane " << MeshData::YZMinus << " ]-----------------------------" << std::endl;
m_Fwd2DQuadrilateralElement[MeshData::YZMinus]->calcEMFieldsOfBoundaryPlanes( freq, &m_MeshDataNonConformingHexaElement );
OutputFiles::m_logFile << "#-----------------------------[ Boundary Plane " << MeshData::YZPlus << " ]-----------------------------" << std::endl;
m_Fwd2DQuadrilateralElement[MeshData::YZPlus]->calcEMFieldsOfBoundaryPlanes( freq, &m_MeshDataNonConformingHexaElement );
}
OutputFiles::m_logFile << "#------------------------------------------------------------------------------" << std::endl;
//----------------------------------------------------------------------------
// Initialize array converting global edge IDs non-zero electric field values specified to the edges
m_globalID2NonZeroValues.clear();
int sidePlanes[2] = { -1, -1 };
if( iPol == CommonParameters::EX_POLARIZATION ){// Ex Polarization
sidePlanes[0] = MeshData::ZXMinus;
sidePlanes[1] = MeshData::ZXPlus;
}else{// Ey Polarization
sidePlanes[0] = MeshData::YZMinus;
sidePlanes[1] = MeshData::YZPlus;
}
// Side planes on which dirichlet boundary condition with non-zero values is specified
for( int iPlane = 0; iPlane < 2; ++iPlane ){
const int planeID = sidePlanes[iPlane];
const int nElemOnPlane = m_MeshDataNonConformingHexaElement.getNumElemOnBoundaryPlanes( planeID );
for( int iElem = 0; iElem < nElemOnPlane; ++iElem ){
const int elemIDGlobal = m_MeshDataNonConformingHexaElement.getElemBoundaryPlanes( planeID, iElem );
const int faceIDLocal = m_MeshDataNonConformingHexaElement.getFaceIDLocalFromElementBoundaryPlanes( planeID, iElem );
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const std::complex<double> val = m_Fwd2DQuadrilateralElement[planeID]->getSolutionFromLocalID( iElem, iEdge );
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( faceIDLocal, iEdge );
m_globalID2NonZeroValues.insert( std::map<int, std::complex<double> >::value_type( m_IDsLocal2Global[elemIDGlobal][edgeIDLocal], val ) );
}
}
}
// Top planes on which dirichlet boundary condition with non-zero values ( source field ) is specified
{
const double sourceValueElectric = CommonParameters::sourceValueElectric;
const int nElemOnPlane = m_MeshDataNonConformingHexaElement.getNumElemOnBoundaryPlanes( MeshData::XYMinus );
for( int iElem = 0; iElem < nElemOnPlane; ++iElem ){
const int elemIDGlobal = m_MeshDataNonConformingHexaElement.getElemBoundaryPlanes( MeshData::XYMinus, iElem );
const int faceIDLocal = m_MeshDataNonConformingHexaElement.getFaceIDLocalFromElementBoundaryPlanes( MeshData::XYMinus, iElem );
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( faceIDLocal, iEdge );
const int nodeID0 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( elemIDGlobal, edgeIDLocal, 0 );
const int nodeID1 = m_MeshDataNonConformingHexaElement.getNodeIDGlobalFromElementAndEdge( elemIDGlobal, edgeIDLocal, 1 );
double val = ( iPol == CommonParameters::EX_POLARIZATION ) ? m_MeshDataNonConformingHexaElement.caldDiffXOfTwoNodes( nodeID0, nodeID1 ) : m_MeshDataNonConformingHexaElement.caldDiffYOfTwoNodes( nodeID0, nodeID1 );
val /= m_MeshDataNonConformingHexaElement.calcDistanceOfTwoNodes( nodeID0, nodeID1 );
m_globalID2NonZeroValues.insert( std::map<int, std::complex<double> >::value_type( m_IDsLocal2Global[elemIDGlobal][edgeIDLocal], std::complex<double>(sourceValueElectric*val, 0.0) ) );
}
}
}
#ifdef _DEBUG_WRITE
for ( std::map<int, std::complex<double> >::iterator itr = m_globalID2NonZeroValues.begin(); itr != m_globalID2NonZeroValues.end(); ++itr ){
std::cout << "key value " << itr->first << " " << itr->second << std::endl;
}
#endif
}
// Calculate 2D jacobian matrix for the Earth's surface
double Forward3DNonConformingHexaElement0thOrder::calc2DJacobianMatrixForEarthSurface( const int elemID, const double xi, const double eta,
Forward3D::Matrix2x2& jacobMat ) const{
// Array of reference coord xi values for each node
const double xiAtNode[4] = { -1.0, 1.0, 1.0, -1.0 };
// Array of reference coord eta values for each node
const double etaAtNode[4] = { -1.0, -1.0, 1.0, 1.0 };
jacobMat.mat11 = 0.0;
jacobMat.mat12 = 0.0;
jacobMat.mat21 = 0.0;
jacobMat.mat22 = 0.0;
for( int i = 0; i < 4; ++i ){
const double xiNode = xiAtNode[i];
const double etaNode = etaAtNode[i];
const double tmp1 = 0.25 * xiNode * (1.0 + etaNode * eta);
const double tmp2 = 0.25 * etaNode * (1.0 + xiNode * xi);
const int node = m_MeshDataNonConformingHexaElement.getNodesOfElements( elemID, i );
const double xCoord = m_MeshDataNonConformingHexaElement.getXCoordinatesOfNodes(node);
const double yCoord = m_MeshDataNonConformingHexaElement.getYCoordinatesOfNodes(node);
jacobMat.mat11 += tmp1 * xCoord;
jacobMat.mat12 += tmp1 * yCoord;
jacobMat.mat21 += tmp2 * xCoord;
jacobMat.mat22 += tmp2 * yCoord;
}
return jacobMat.mat11 * jacobMat.mat22 - jacobMat.mat12 * jacobMat.mat21;
}
// Make map converting master dofs after degeneration and MPC factors from slave dof after degeneration
void Forward3DNonConformingHexaElement0thOrder::makeMapSlaveDofToMasterDofAndFactors(){
const int iPol = getPolarizationCurrent();// Constraint matrix does not depend on the type of polarization
if( m_IDsAfterDegenerated2AfterConstrained != NULL ){
delete [] m_IDsAfterDegenerated2AfterConstrained;
m_IDsAfterDegenerated2AfterConstrained = NULL;
}
m_IDsAfterDegenerated2AfterConstrained = new int[m_numOfEquationDegenerated];
for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
m_IDsAfterDegenerated2AfterConstrained[i] = 0;
}
if( m_slaveDofToMasterDofAndFactors != NULL ){
delete [] m_slaveDofToMasterDofAndFactors;
m_slaveDofToMasterDofAndFactors = NULL;
}
m_slaveDofToMasterDofAndFactors = new std::vector< std::pair<int,double> >[m_numOfEquationDegenerated];
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
const int elemID = iElem;
for( int iFace = 0; iFace < 6; ++iFace ){
if( !m_MeshDataNonConformingHexaElement.faceSlaveElements(elemID, iFace) ){
// This face does not have slave edges
continue;
}
// Dofs of master edges
int dofMasterBeforeDegenerated[4] = { -1, -1, -1, -1 };
int dofMaster[4] = { -1, -1, -1, -1 };
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFace, iEdge );
const int dofBeforeDegenerated = m_IDsLocal2Global[elemID][edgeIDLocal];
dofMasterBeforeDegenerated[iEdge] = dofBeforeDegenerated;
dofMaster[iEdge] = m_IDsGlobal2AfterDegenerated[iPol][ dofBeforeDegenerated ];
#ifdef _DEBUG_WRITE
if( dofMaster[iEdge] < 0 ){
std::cout << "iElem, iEdge, dofMaster :" << iElem << " " << iEdge << " " << dofMaster[iEdge] << std::endl;
}
#endif
}
// Face index of neighbor element
const int iFaceNeib = m_MeshDataNonConformingHexaElement.getFaceIndexOfNeighborElement(iFace);
const int numNeibElements = m_MeshDataNonConformingHexaElement.getNumNeighborElement(elemID, iFace);
if( numNeibElements == 2 ){
// Dofs of slave edges
int dofSlaves[2][4] = { { -1, -1, -1, -1 }, { -1, -1, -1, -1 } };
for( int iNeib = 0; iNeib < 2; ++iNeib ){
const int elemIDNeib = m_MeshDataNonConformingHexaElement.getIDOfNeighborElement(elemID, iFace, iNeib );
for( int iEdgeNeib = 0; iEdgeNeib < 4; ++iEdgeNeib ){
const int edgeIDLocalNeib = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFaceNeib, iEdgeNeib );
dofSlaves[iNeib][iEdgeNeib] = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDNeib][edgeIDLocalNeib] ];
}
}
assert( dofSlaves[0][3] == dofSlaves[1][2] );
if( dofMaster[0] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[0][0], dofMaster[0], 1.0 );
addMasterDofAndFactorPair( dofSlaves[1][0], dofMaster[0], 1.0 );
}
if( dofMaster[1] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[0][1], dofMaster[1], 1.0 );
addMasterDofAndFactorPair( dofSlaves[1][1], dofMaster[1], 1.0 );
}
if( dofMaster[2] >= 0 ){
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][3], dofMaster[2], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
if( dofMaster[3] >= 0 ){
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][3], dofMaster[3], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
// Slave dofs on outer edges of the face
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][0] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[1][0] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[1][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
// Slave dofs on interior edges of the face
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][3] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_INTERIOR_EDGES;
}else if( numNeibElements == 4 ){
// Dofs of slave edges
int dofSlaves[4][4] = { { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } };
for( int iNeib = 0; iNeib < 4; ++iNeib ){
const int elemIDNeib = m_MeshDataNonConformingHexaElement.getIDOfNeighborElement(elemID, iFace, iNeib );
for( int iEdgeNeib = 0; iEdgeNeib < 4; ++iEdgeNeib ){
const int edgeIDLocalNeib = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFaceNeib, iEdgeNeib );
dofSlaves[iNeib][iEdgeNeib] = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDNeib][edgeIDLocalNeib] ];
}
}
assert( dofSlaves[0][1] == dofSlaves[2][0] );
assert( dofSlaves[1][1] == dofSlaves[3][0] );
assert( dofSlaves[0][3] == dofSlaves[1][2] );
assert( dofSlaves[2][3] == dofSlaves[3][2] );
if( dofMaster[0] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[0][0], dofMaster[0], 1.0 );
addMasterDofAndFactorPair( dofSlaves[1][0], dofMaster[0], 1.0 );
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][1], dofMaster[0], 0.5 );
addMasterDofAndFactorPair( dofSlaves[1][1], dofMaster[0], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
if( dofMaster[1] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[2][1], dofMaster[1], 1.0 );
addMasterDofAndFactorPair( dofSlaves[3][1], dofMaster[1], 1.0 );
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][1], dofMaster[1], 0.5 );
addMasterDofAndFactorPair( dofSlaves[1][1], dofMaster[1], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
if( dofMaster[2] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[0][2], dofMaster[2], 1.0 );
addMasterDofAndFactorPair( dofSlaves[2][2], dofMaster[2], 1.0 );
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][3], dofMaster[2], 0.5 );
addMasterDofAndFactorPair( dofSlaves[2][3], dofMaster[2], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
if( dofMaster[3] >= 0 ){
// Slave dofs on outer edges of the face
addMasterDofAndFactorPair( dofSlaves[1][3], dofMaster[3], 1.0 );
addMasterDofAndFactorPair( dofSlaves[3][3], dofMaster[3], 1.0 );
// Slave dofs on interior edges of the face
addMasterDofAndFactorPair( dofSlaves[0][3], dofMaster[3], 0.5 );
addMasterDofAndFactorPair( dofSlaves[2][3], dofMaster[3], 0.5 );
}else{
// In this case, MPC constants are calcunated in calcMPCConstants
}
// Slave dofs on outer edges of the face
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][0] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[1][0] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[2][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[3][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][2] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[2][2] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[1][3] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[3][3] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_OUTER_EDGES;
// Slave dofs on interior edges of the face
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_INTERIOR_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[1][1] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_INTERIOR_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[0][3] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_INTERIOR_EDGES;
m_IDsAfterDegenerated2AfterConstrained[ dofSlaves[2][3] ] = Forward3DNonConformingHexaElement0thOrder::SLAVE_ON_INTERIOR_EDGES;
}else{
OutputFiles::m_logFile << "Error : Number of neighbor elements is wrong : " << numNeibElements << std::endl;
exit(1);
}
}
}
//#ifdef _DEBUG_WRITE
// for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
// std::vector< std::pair<int,double> >& vec = m_slaveDofToMasterDofAndFactors[i];
// const int numMasters = vec.size();
// assert( numMasters == 1 || numMasters == 2 );
// double sumFactor(0.0);
// for( std::vector< std::pair<int,double> >::const_iterator itrVec = vec.begin(); itrVec != vec.end(); ++itrVec ){
// sumFactor += itrVec->second;
// }
// assert( std::abs(sumFactor - 0.5) < m_eps );
// }
//#endif
int icount(-1);
for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
if( m_IDsAfterDegenerated2AfterConstrained[i] < 0 ){
// Slave dof
continue;
}
// Master dof
addMasterDofAndFactorPair( i, i, 1.0 );// Even for master dof, dof and factor are inserted
m_IDsAfterDegenerated2AfterConstrained[i] = ++icount;
}
m_numOfEquationDegeneratedAndConstrained = icount + 1;
m_hasMadeMapSlaveDofToMasterDofAndFactors = true;
#ifdef _DEBUG_WRITE
for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
std::vector< std::pair<int,double> >& vec = m_slaveDofToMasterDofAndFactors[i];
for( std::vector< std::pair<int,double> >::const_iterator itrVec = vec.begin(); itrVec != vec.end(); ++itrVec ){
std::cout << "slave master factor : " << i << " " << itrVec->first << " " << itrVec->second << std::endl;
}
}
#endif
}
// Calculate MPC constants
void Forward3DNonConformingHexaElement0thOrder::calcMPCConstants(){
const int iPol = getPolarizationCurrent();// Constraint matrix does not depend on the type of polarization
if( m_vectorMPCConstants == NULL ){
m_vectorMPCConstants = new std::complex<double>[m_numOfEquationDegenerated];
}
// Zero clear because values are added in the following procedure
for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
m_vectorMPCConstants[i] = std::complex<double>(0.0, 0.0);
}
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
for( int iElem = 0; iElem < nElem; ++iElem ){
const int elemID = iElem;
for( int iFace = 0; iFace < 6; ++iFace ){
if( !m_MeshDataNonConformingHexaElement.faceSlaveElements(elemID, iFace) ){
// This face does not have slave edges
continue;
}
// Dofs of master edges
int dofMasterBeforeDegenerated[4] = { -1, -1, -1, -1 };
int dofMaster[4] = { -1, -1, -1, -1 };
for( int iEdge = 0; iEdge < 4; ++iEdge ){
const int edgeIDLocal = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFace, iEdge );
const int dofBeforeDegenerated = m_IDsLocal2Global[elemID][edgeIDLocal];
dofMasterBeforeDegenerated[iEdge] = dofBeforeDegenerated;
dofMaster[iEdge] = m_IDsGlobal2AfterDegenerated[iPol][ dofBeforeDegenerated ];
}
// Face index of neighbor element
const int iFaceNeib = m_MeshDataNonConformingHexaElement.getFaceIndexOfNeighborElement(iFace);
const int numNeibElements = m_MeshDataNonConformingHexaElement.getNumNeighborElement(elemID, iFace);
if( numNeibElements == 2 ){
// Dofs of slave edges
int dofSlaves[2][4] = { { -1, -1, -1, -1 }, { -1, -1, -1, -1 } };
for( int iNeib = 0; iNeib < 2; ++iNeib ){
const int elemIDNeib = m_MeshDataNonConformingHexaElement.getIDOfNeighborElement(elemID, iFace, iNeib );
for( int iEdgeNeib = 0; iEdgeNeib < 4; ++iEdgeNeib ){
const int edgeIDLocalNeib = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFaceNeib, iEdgeNeib );
dofSlaves[iNeib][iEdgeNeib] = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDNeib][edgeIDLocalNeib] ];
}
}
assert( dofSlaves[0][3] == dofSlaves[1][2] );
if( dofMaster[2] < 0 ){
if( dofMaster[2] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[2] ];
m_vectorMPCConstants[ dofSlaves[0][3] ] += value;
}
}
if( dofMaster[3] < 0 ){
if( dofMaster[3] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[3] ];
m_vectorMPCConstants[ dofSlaves[0][3] ] += value;
}
}
}else if( numNeibElements == 4 ){
// Dofs of slave edges
int dofSlaves[4][4] = { { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } };
for( int iNeib = 0; iNeib < 4; ++iNeib ){
const int elemIDNeib = m_MeshDataNonConformingHexaElement.getIDOfNeighborElement(elemID, iFace, iNeib );
for( int iEdgeNeib = 0; iEdgeNeib < 4; ++iEdgeNeib ){
const int edgeIDLocalNeib = m_MeshDataNonConformingHexaElement.getEdgeIDLocalFromFaceIDLocal( iFaceNeib, iEdgeNeib );
dofSlaves[iNeib][iEdgeNeib] = m_IDsGlobal2AfterDegenerated[iPol][ m_IDsLocal2Global[elemIDNeib][edgeIDLocalNeib] ];
}
}
assert( dofSlaves[0][1] == dofSlaves[2][0] );
assert( dofSlaves[1][1] == dofSlaves[3][0] );
assert( dofSlaves[0][3] == dofSlaves[1][2] );
assert( dofSlaves[2][3] == dofSlaves[3][2] );
if( dofMaster[0] < 0 ){
if( dofMaster[0] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[0] ];
m_vectorMPCConstants[ dofSlaves[0][1] ] += value;
m_vectorMPCConstants[ dofSlaves[1][1] ] += value;
}
}
if( dofMaster[1] < 0 ){
if( dofMaster[1] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[1] ];
m_vectorMPCConstants[ dofSlaves[0][1] ] += value;
m_vectorMPCConstants[ dofSlaves[1][1] ] += value;
}
}
if( dofMaster[2] < 0 ){
if( dofMaster[2] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[2] ];
m_vectorMPCConstants[ dofSlaves[0][3] ] += value;
m_vectorMPCConstants[ dofSlaves[2][3] ] += value;
}
}
if( dofMaster[3] < 0 ){
if( dofMaster[3] == Forward3DNonConformingHexaElement0thOrder::DIRICHLET_BOUNDARY_NONZERO_VALUE ){
const std::complex<double> value = std::complex<double>(0.5, 0.0) * m_globalID2NonZeroValues[ dofMasterBeforeDegenerated[3] ];
m_vectorMPCConstants[ dofSlaves[0][3] ] += value;
m_vectorMPCConstants[ dofSlaves[2][3] ] += value;
}
}
}else{
OutputFiles::m_logFile << "Error : Number of neighbor elements is wrong : " << numNeibElements << std::endl;
exit(1);
}
}
}
#ifdef _DEBUG_WRITE
for( int i = 0; i < m_numOfEquationDegenerated; ++i ){
std::cout << "m_vectorMPCConstants[" << i << "] = " << m_vectorMPCConstants[i] << std::endl;
}
#endif
}
// Add master dof and factor pair to m_slaveDofToMasterDofAndFactors
bool Forward3DNonConformingHexaElement0thOrder::doesIntegralXCompFirst( const CommonParameters::locationXY& startPoint, const CommonParameters::locationXY& endPoint,
bool& rotationDirectionPlus, CommonParameters::locationXY& sharedPoint ) const{
const double eps = 1.0e-12;
bool intersectTwoEdges = true;
if( ( fabs( startPoint.X - 1.0 ) < eps && fabs( endPoint.Y - 1.0 ) < eps ) ||
( fabs( startPoint.Y - 1.0 ) < eps && fabs( endPoint.X - 1.0 ) < eps ) ){
sharedPoint.X = 1.0;
sharedPoint.Y = 1.0;
}else if( ( fabs( startPoint.X - 1.0 ) < eps && fabs( endPoint.Y + 1.0 ) < eps ) ||
( fabs( startPoint.Y + 1.0 ) < eps && fabs( endPoint.X - 1.0 ) < eps ) ){
sharedPoint.X = 1.0;
sharedPoint.Y = -1.0;
}else if( ( fabs( startPoint.X + 1.0 ) < eps && fabs( endPoint.Y + 1.0 ) < eps ) ||
( fabs( startPoint.Y + 1.0 ) < eps && fabs( endPoint.X + 1.0 ) < eps ) ){
sharedPoint.X = -1.0;
sharedPoint.Y = -1.0;
}else if( ( fabs( startPoint.X + 1.0 ) < eps && fabs( endPoint.Y - 1.0 ) < eps ) ||
( fabs( startPoint.Y - 1.0 ) < eps && fabs( endPoint.X + 1.0 ) < eps ) ){
sharedPoint.X = -1.0;
sharedPoint.Y = 1.0;
}else{// Not intersect two edges => integral X component first
sharedPoint.X = startPoint.X;
sharedPoint.Y = endPoint.Y;
intersectTwoEdges = false;
}
const double outerProduct = ( sharedPoint.X - startPoint.X )*( endPoint.Y - startPoint.Y ) - ( sharedPoint.Y - startPoint.Y )*( endPoint.X - startPoint.X );
if( outerProduct > 0 ){
rotationDirectionPlus = true;
}else{
rotationDirectionPlus = false;
}
if( intersectTwoEdges ){
if( sharedPoint.X * sharedPoint.Y < 0.0 ){
if( rotationDirectionPlus ){
return true;
}else{
return false;
}
}else{
if( rotationDirectionPlus ){
return false;
}else{
return true;
}
}
}else{// Not intersect two edges => integral X component first
return false;
}
}
// Add master dof and factor pair to m_slaveDofToMasterDofAndFactors
void Forward3DNonConformingHexaElement0thOrder::addMasterDofAndFactorPair( const int slaveDof, const int masterDof, const double factor ){
//std::map< int, std::vector< std::pair<int,double> > >::iterator itr = m_slaveDofToMasterDofAndFactors.find(slaveDof);
//if( itr == m_slaveDofToMasterDofAndFactors.end() ){
// // Pair has not been inserted
// std::pair<int,double> pair = std::make_pair( masterDof, factor );
// std::vector< std::pair<int,double> > vec;
// vec.push_back(pair);
// m_slaveDofToMasterDofAndFactors.insert( std::make_pair( slaveDof, vec ) );
//}else{
// // Pair has already been inserted
// std::vector< std::pair<int,double> >& vec = itr->second;
// bool found(false);
// for( std::vector< std::pair<int,double> >::iterator itrVec = vec.begin(); itrVec != vec.end(); ++itrVec ){
// if(itrVec->first == masterDof){
// found = true;
// break;
// }
// }
// if( !found ){
// // Insert only if the master has not been found
// itr->second.push_back( std::make_pair( masterDof, factor ) );
// }
//}
std::vector< std::pair<int,double> >& vec = m_slaveDofToMasterDofAndFactors[slaveDof];;
bool found(false);
for( std::vector< std::pair<int,double> >::iterator itrVec = vec.begin(); itrVec != vec.end(); ++itrVec ){
if(itrVec->first == masterDof){
found = true;
break;
}
}
if( !found ){
// Insert only if the master has not been found
vec.push_back( std::make_pair( masterDof, factor ) );
}
}
// Get shape functions of the x direction with respect to the 1st reference element coordinate system
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncX( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
return 0.125 * ( 1.0 + m_etaAtEdge[num] * eta ) * ( 1.0 + m_zetaAtEdge[num] * zeta ) * invJacobMat.mat11;
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
return 0.125 * ( 1.0 + m_zetaAtEdge[num] * zeta ) * ( 1.0 + m_xiAtEdge[num] * xi ) * invJacobMat.mat12;
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
return 0.125 * ( 1.0 + m_xiAtEdge[num] * xi ) * ( 1.0 + m_etaAtEdge[num] * eta ) * invJacobMat.mat13;
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
}
// Get shape functions of the y direction with respect to the reference element coordinate system
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncY( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
return 0.125 * ( 1.0 + m_etaAtEdge[num] * eta ) * ( 1.0 + m_zetaAtEdge[num] * zeta ) * invJacobMat.mat21;
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
return 0.125 * ( 1.0 + m_zetaAtEdge[num] * zeta ) * ( 1.0 + m_xiAtEdge[num] * xi ) * invJacobMat.mat22;
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
return 0.125 * ( 1.0 + m_xiAtEdge[num] * xi ) * ( 1.0 + m_etaAtEdge[num] * eta ) * invJacobMat.mat23;
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
}
// Get shape functions of the z direction with respect to the reference element coordinate system
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncZ( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
return 0.125 * ( 1.0 + m_etaAtEdge[num] * eta ) * ( 1.0 + m_zetaAtEdge[num] * zeta ) * invJacobMat.mat31;
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
return 0.125 * ( 1.0 + m_zetaAtEdge[num] * zeta ) * ( 1.0 + m_xiAtEdge[num] * xi ) * invJacobMat.mat32;
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
return 0.125 * ( 1.0 + m_xiAtEdge[num] * xi ) * ( 1.0 + m_etaAtEdge[num] * eta ) * invJacobMat.mat33;
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
}
// Get x component of shape function rotated for 0th order edge-based elements
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncRotatedX( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
double tmp1(0.0);
double tmp2(0.0);
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
tmp1 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat31*invJacobMat.mat22 - invJacobMat.mat21*invJacobMat.mat32 );
tmp2 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat31*invJacobMat.mat23 - invJacobMat.mat21*invJacobMat.mat33 );
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
tmp1 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat32*invJacobMat.mat23 - invJacobMat.mat22*invJacobMat.mat33 );
tmp2 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat32*invJacobMat.mat21 - invJacobMat.mat22*invJacobMat.mat31 );
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
tmp1 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat33*invJacobMat.mat21 - invJacobMat.mat23*invJacobMat.mat31 );
tmp2 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat33*invJacobMat.mat22 - invJacobMat.mat23*invJacobMat.mat32 );
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
return tmp1 + tmp2;
}
// Get y component of shape function rotated for 0th order edge-based elements
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncRotatedY( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
double tmp1(0.0);
double tmp2(0.0);
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
tmp1 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat11*invJacobMat.mat32 - invJacobMat.mat31*invJacobMat.mat12 );
tmp2 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat11*invJacobMat.mat33 - invJacobMat.mat31*invJacobMat.mat13 );
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
tmp1 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat12*invJacobMat.mat33 - invJacobMat.mat32*invJacobMat.mat13 );
tmp2 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat12*invJacobMat.mat31 - invJacobMat.mat32*invJacobMat.mat11 );
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
tmp1 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat13*invJacobMat.mat31 - invJacobMat.mat33*invJacobMat.mat11 );
tmp2 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat13*invJacobMat.mat32 - invJacobMat.mat33*invJacobMat.mat12 );
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
return tmp1 + tmp2;
}
// Get z component of shape function rotated for 0th order edge-based elements
double Forward3DNonConformingHexaElement0thOrder::getShapeFuncRotatedZ( const double xi, const double eta, const double zeta, const int num, const Forward3D::Matrix3x3& invJacobMat ) const{
double tmp1(0.0);
double tmp2(0.0);
switch( num ){
case 0:// Go through
case 1:// Go through
case 2:// Go through
case 3:
tmp1 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat21*invJacobMat.mat12 - invJacobMat.mat11*invJacobMat.mat22 );
tmp2 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat21*invJacobMat.mat13 - invJacobMat.mat11*invJacobMat.mat23 );
break;
case 4:// Go through
case 5:// Go through
case 6:// Go through
case 7:
tmp1 = 0.125 * m_zetaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat22*invJacobMat.mat13 - invJacobMat.mat12*invJacobMat.mat23 );
tmp2 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_zetaAtEdge[num] * zeta )*( invJacobMat.mat22*invJacobMat.mat11 - invJacobMat.mat12*invJacobMat.mat21 );
break;
case 8:// Go through
case 9:// Go through
case 10:// Go through
case 11:
tmp1 = 0.125 * m_xiAtEdge[num] * ( 1.0 + m_etaAtEdge[num] * eta )*( invJacobMat.mat23*invJacobMat.mat11 - invJacobMat.mat13*invJacobMat.mat21 );
tmp2 = 0.125 * m_etaAtEdge[num] * ( 1.0 + m_xiAtEdge[num] * xi )*( invJacobMat.mat23*invJacobMat.mat12 - invJacobMat.mat13*invJacobMat.mat22 );
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ << " : num = " << num << std::endl;
exit(1);
break;
}
return tmp1 + tmp2;
}
// Calculate jacobian matrix of the elements
double Forward3DNonConformingHexaElement0thOrder::get2DShapeFuncRotatedForEarthSurface( const double xi, const double eta, const int num, const Forward3D::Matrix2x2& invJacobMat ) const{
// Array of reference coord xi values for each edge
const double xiAtEdge[4] = { -9999.999, -9999.999, -1.0, 1.0 };
// Array of reference coord eta values for each edge
const double etaAtEdge[4] = { -1.0, 1.0, -9999.999, -9999.999 };
switch( num ){
case 0:// go through
case 1:
return 0.25 * etaAtEdge[num] * (invJacobMat.mat21*invJacobMat.mat12 - invJacobMat.mat11*invJacobMat.mat22 );
break;
case 2:// go through
case 3:
return 0.25 * xiAtEdge[num] * (invJacobMat.mat22*invJacobMat.mat11 - invJacobMat.mat12*invJacobMat.mat21 );
break;
default:
OutputFiles::m_logFile << "Error : Wrong number in " << __FUNCTION__ <<" : num = " << num << std::endl;
exit(1);
break;
}
}
// Calculate jacobian matrix of the elements
double Forward3DNonConformingHexaElement0thOrder::calcJacobianMatrix( const int elemID, const double xi, const double eta, const double zeta, Forward3D::Matrix3x3& JacobMat ) const{
double xCoord[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double yCoord[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double zCoord[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
for( int i = 0; i < 8; ++i ){
const int nodeID = m_MeshDataNonConformingHexaElement.getNodesOfElements(elemID, i);
xCoord[i] = m_MeshDataNonConformingHexaElement.getXCoordinatesOfNodes(nodeID);
yCoord[i] = m_MeshDataNonConformingHexaElement.getYCoordinatesOfNodes(nodeID);
zCoord[i] = m_MeshDataNonConformingHexaElement.getZCoordinatesOfNodes(nodeID);
}
// Zero clear
JacobMat.mat11 = 0.0;
JacobMat.mat12 = 0.0;
JacobMat.mat13 = 0.0;
JacobMat.mat21 = 0.0;
JacobMat.mat22 = 0.0;
JacobMat.mat23 = 0.0;
JacobMat.mat31 = 0.0;
JacobMat.mat32 = 0.0;
JacobMat.mat33 = 0.0;
for( int i = 0; i < 8; ++i ){
const double xiNode = m_xiAtNode[i];
const double etaNode = m_etaAtNode[i];
const double zetaNode = m_zetaAtNode[i];
const double tmp1 = 0.125 * xiNode * (1.0 + etaNode * eta) * (1.0 + zetaNode * zeta);
const double tmp2 = 0.125 * etaNode * (1.0 + zetaNode * zeta) * (1.0 + xiNode * xi);
const double tmp3 = 0.125 * zetaNode * (1.0 + xiNode * xi) * (1.0 + etaNode * eta);
JacobMat.mat11 += tmp1 * xCoord[i];
JacobMat.mat12 += tmp1 * yCoord[i];
JacobMat.mat13 += tmp1 * zCoord[i];
JacobMat.mat21 += tmp2 * xCoord[i];
JacobMat.mat22 += tmp2 * yCoord[i];
JacobMat.mat23 += tmp2 * zCoord[i];
JacobMat.mat31 += tmp3 * xCoord[i];
JacobMat.mat32 += tmp3 * yCoord[i];
JacobMat.mat33 += tmp3 * zCoord[i];
}
const double determinant = JacobMat.mat11 * JacobMat.mat22 * JacobMat.mat33
+ JacobMat.mat12 * JacobMat.mat23 * JacobMat.mat31
+ JacobMat.mat13 * JacobMat.mat21 * JacobMat.mat32
- JacobMat.mat13 * JacobMat.mat22 * JacobMat.mat31
- JacobMat.mat12 * JacobMat.mat21 * JacobMat.mat33
- JacobMat.mat11 * JacobMat.mat23 * JacobMat.mat32;
return determinant;
}
// Calculate inverse of jacobian matrix multiplied by determinant
void Forward3DNonConformingHexaElement0thOrder::calcInverseOfJacobianMatrix( const Forward3D::Matrix3x3& jacobMat, const double determinant, Forward3D::Matrix3x3& invJacobMat ) const{
const double invDet = 1.0 / determinant;
invJacobMat.mat11 = ( jacobMat.mat22 * jacobMat.mat33 - jacobMat.mat23 * jacobMat.mat32 ) * invDet;
invJacobMat.mat12 = ( jacobMat.mat13 * jacobMat.mat32 - jacobMat.mat12 * jacobMat.mat33 ) * invDet;
invJacobMat.mat13 = ( jacobMat.mat12 * jacobMat.mat23 - jacobMat.mat13 * jacobMat.mat22 ) * invDet;
invJacobMat.mat21 = ( jacobMat.mat23 * jacobMat.mat31 - jacobMat.mat21 * jacobMat.mat33 ) * invDet;
invJacobMat.mat22 = ( jacobMat.mat11 * jacobMat.mat33 - jacobMat.mat13 * jacobMat.mat31 ) * invDet;
invJacobMat.mat23 = ( jacobMat.mat13 * jacobMat.mat21 - jacobMat.mat11 * jacobMat.mat23 ) * invDet;
invJacobMat.mat31 = ( jacobMat.mat21 * jacobMat.mat32 - jacobMat.mat22 * jacobMat.mat31 ) * invDet;
invJacobMat.mat32 = ( jacobMat.mat12 * jacobMat.mat31 - jacobMat.mat11 * jacobMat.mat32 ) * invDet;
invJacobMat.mat33 = ( jacobMat.mat11 * jacobMat.mat22 - jacobMat.mat12 * jacobMat.mat21 ) * invDet;
}
// Output results of forward calculation to VTK file
void Forward3DNonConformingHexaElement0thOrder::outputResultToVTK() const{
if( !OutputFiles::m_vtkFile.is_open() ){
return;
}
const AnalysisControl* const pAnalysisControl = AnalysisControl::getInstance();
std::string stringPolarization;
const int iPol = getPolarizationCurrent();
if( iPol == CommonParameters::EX_POLARIZATION ){// Ex Polarization
//stringPolarization = "Ex_polarization";
stringPolarization = "ExPol";
}else{// Ey Polarization
//stringPolarization = "Ey_polarization";
stringPolarization = "EyPol";
}
//--- Total element number
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
const double freq = getFrequencyCurrent();
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_ELECTRIC_FIELD_VECTORS_TO_VTK ) ){// Output electric field vector
OutputFiles::m_vtkFile << "VECTORS Re(E)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const float Ex = static_cast<float>( real( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Ey = static_cast<float>( real( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Ez = static_cast<float>( real( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << Ex << " " << Ey << " " << Ez << std::endl;
}
OutputFiles::m_vtkFile << "VECTORS Im(E)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const float Ex = static_cast<float>( imag( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Ey = static_cast<float>( imag( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Ez = static_cast<float>( imag( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << Ex << " " << Ey << " " << Ez << std::endl;
}
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_MAGNETIC_FIELD_VECTORS_TO_VTK ) ){// Output magnetic field vector
OutputFiles::m_vtkFile << "VECTORS Re(H)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const float Hx = static_cast<float>( real( calcValueMagneticFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Hy = static_cast<float>( real( calcValueMagneticFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Hz = static_cast<float>( real( calcValueMagneticFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << Hx << " " << Hy << " " << Hz << std::endl;
}
OutputFiles::m_vtkFile << "VECTORS Im(H)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const float Hx = static_cast<float>( imag( calcValueMagneticFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Hy = static_cast<float>( imag( calcValueMagneticFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float Hz = static_cast<float>( imag( calcValueMagneticFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << Hx << " " << Hy << " " << Hz << std::endl;
}
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_CURRENT_DENSITY ) ){// Output corrent density
const ResistivityBlock* pResistivityBlock = ResistivityBlock::getInstance();
OutputFiles::m_vtkFile << "VECTORS Re(j)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
const float jx = static_cast<float>( sigma * real( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float jy = static_cast<float>( sigma * real( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float jz = static_cast<float>( sigma * real( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << jx << " " << jy << " " << jz << std::endl;
}
OutputFiles::m_vtkFile << "VECTORS Im(j)_" << freq <<"(Hz)_" << stringPolarization << " float" << std::endl;
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
const float jx = static_cast<float>( sigma * imag( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float jy = static_cast<float>( sigma * imag( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
const float jz = static_cast<float>( sigma * imag( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
OutputFiles::m_vtkFile << jx << " " << jy << " " << jz << std::endl;
}
}
}
// Output results of forward calculation to binary file
void Forward3DNonConformingHexaElement0thOrder::outputResultToBinary( const int iFreq, const int iPol ) const{
const std::string stringPolarization = iPol == CommonParameters::EX_POLARIZATION ? "ExPol" : "EyPol";
const AnalysisControl* const pAnalysisControl = AnalysisControl::getInstance();
//--- Total element number
const int nElem = m_MeshDataNonConformingHexaElement.getNumElemTotal();
const double freq = getFrequencyCurrent();
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_ELECTRIC_FIELD_VECTORS_TO_VTK ) ){
// Output real part of electric field vector
std::ostringstream oss;
oss << "ReE_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Real(E) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ex = static_cast<float>( real( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ex, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ey = static_cast<float>( real( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ey, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ez = static_cast<float>( real( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ez, sizeof( float ) );
}
fout.close();
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_ELECTRIC_FIELD_VECTORS_TO_VTK ) ){
// Output imaginary part of electric field vector
std::ostringstream oss;
oss << "ImE_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Imag(E) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ex = static_cast<float>( imag( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ex, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ey = static_cast<float>( imag( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ey, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Ez = static_cast<float>( imag( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Ez, sizeof( float ) );
}
fout.close();
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_MAGNETIC_FIELD_VECTORS_TO_VTK ) ){
// Output real part of magnetic field vector
std::ostringstream oss;
oss << "ReH_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Real(H) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hx = static_cast<float>( real( calcValueMagneticFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hx, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hy = static_cast<float>( real( calcValueMagneticFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hy, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hz = static_cast<float>( real( calcValueMagneticFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hz, sizeof( float ) );
}
fout.close();
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_MAGNETIC_FIELD_VECTORS_TO_VTK ) ){
// Output imaginary part of magnetic field vector
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
std::ostringstream oss;
oss << "ImH_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Imag(H) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hx = static_cast<float>( imag( calcValueMagneticFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hx, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hy = static_cast<float>( imag( calcValueMagneticFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hy, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
float Hz = static_cast<float>( imag( calcValueMagneticFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &Hz, sizeof( float ) );
}
fout.close();
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_CURRENT_DENSITY ) ){
// Output real part of corrent density
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
std::ostringstream oss;
oss << "Rej_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Real(j) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jx = static_cast<float>( sigma * real( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jx, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jy = static_cast<float>( sigma * real( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jy, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jz = static_cast<float>( sigma * real( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jz, sizeof( float ) );
}
fout.close();
}
if( pAnalysisControl->doesOutputToVTK( AnalysisControl::OUTPUT_CURRENT_DENSITY ) ){
// Output imaginary part of corrent density
const ResistivityBlock* const pResistivityBlock = ResistivityBlock::getInstance();
std::ostringstream oss;
oss << "Imj_Freq" << iFreq << "_" << stringPolarization << ".iter" << pAnalysisControl->getIterationNumCurrent();
std::ofstream fout;
fout.open( oss.str().c_str(), std::ios::out | std::ios::binary | std::ios::trunc );
char line[80];
std::ostringstream ossTitle;
ossTitle << "Imag(j) of " << stringPolarization << " at " << freq << " [Hz]";
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 ) );
strcpy( line, "hexa8" );
fout.write( line, 80 );
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jx = static_cast<float>( sigma * imag( calcValueElectricFieldXDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jx, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jy = static_cast<float>( sigma * imag( calcValueElectricFieldYDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jy, sizeof( float ) );
}
for( int iElem = 0 ; iElem < nElem; ++iElem ){
const double sigma = pResistivityBlock->getConductivityValuesFromElemID(iElem);
float jz = static_cast<float>( sigma * imag( calcValueElectricFieldZDirection( iElem, 0.0, 0.0, 0.0 ) ) );
fout.write( (char*) &jz, sizeof( float ) );
}
fout.close();
}
}
// Add values to right-hand sides matrix consisting of interpolator vectors by taking into account MPC
void Forward3DNonConformingHexaElement0thOrder::addValuesToRhsVectorsByConsideringMPC( const int irow, const int irhs, const std::complex<double>& val ){
const std::vector< std::pair<int,double> >& rowMasters= m_slaveDofToMasterDofAndFactors[irow];
for( std::vector< std::pair<int,double> >::const_iterator itrRow = rowMasters.begin(); itrRow != rowMasters.end(); ++itrRow ){
const int iRowMod = m_IDsAfterDegenerated2AfterConstrained[itrRow->first];
const std::complex<double> valMod = val * std::complex<double>(itrRow->second, 0.0);
addValuesToRhsVectors( iRowMod, irhs, valMod );
}
}
//// Make pair of master dof and factor for a slave dof
//void Forward3DNonConformingHexaElement0thOrder::makePairOfMasterDofAndFactorForASlaveDof( const int slaveDofAfterDegenerated, std::vector< std::pair<int,double> >& masterDofAndFactorsAfterDegenerated ) const{
//
// std::map< int, std::vector< std::pair<int,double> > > masterDofBeforeDegeneratedAndFactorsAll;
//
// const int slaveDofBeforeDegenerated = getDofBeforeDegenerationFromDofAfterDegeneration(slaveDofAfterDegenerated);
//
// std::vector< std::pair<int,double> >& masterDofBeforeDegeneratedAndFactors = masterDofBeforeDegeneratedAndFactorsAll[slaveDofBeforeDegenerated];
// if( static_cast<int>( masterDofBeforeDegeneratedAndFactors.size() ) == 0 ){
// // This dof is master
// masterDofAndFactorsAfterDegenerated.push_back( std::make_pair(slaveDofAfterDegenerated, 1.0) );
// return;
// }
//
// // This dof depends on some master dofs
// std::vector< std::pair<int,double> > masterDofAndFactorsBeforeDegenerated;
// //for( std::vector< std::pair<int,double> >::const_iterator itr = masterDofBeforeDegeneratedAndFactors.begin(); itr != masterDofBeforeDegeneratedAndFactors.end(); ++itr ){
// // const int masterDofBeforeDegenerated = itr->first;
// // const double factor = itr->second;
// // masterDofAndFactorsBeforeDegenerated.push_back( std::make_pair(masterDofBeforeDegenerated, factor) );
// //}
// masterDofAndFactorsBeforeDegenerated.push_back( std::make_pair(slaveDofBeforeDegenerated, 1.0) );
//
// bool found(true);
// while (found){
// found = false;
// for( std::vector< std::pair<int,double> >::iterator itr = masterDofAndFactorsBeforeDegenerated.begin(); itr != masterDofAndFactorsBeforeDegenerated.end(); ++itr ){
// const int masterDofBeforeDegeneratedOrg = itr->first;
// std::vector< std::pair<int,double> > masterDofAndFactorsBeforeDegeneratedAux;
// makePairOfMasterDofAndFactorForASlaveDofAux( masterDofBeforeDegeneratedOrg, masterDofAndFactorsBeforeDegeneratedAux );
// if( static_cast<int>( masterDofAndFactorsBeforeDegeneratedAux.size() ) == 0 ){
// // The dof does not has masters
// continue;
// }
// // The dofhas masters
// found = true;
// const double factorOrg = itr->second;
// std::vector< std::pair<int,double> >::const_iterator itrSub = masterDofAndFactorsBeforeDegeneratedAux.begin();
// itr->first = itrSub->first;// Replace dof
// itr->second = factorOrg * itrSub->second;// Replace factor
// for( ; itrSub != masterDofAndFactorsBeforeDegeneratedAux.end(); ++itrSub ){
// const int masterDofBeforeDegenerated = itrSub->first;
// const double factor = factorOrg * itrSub->second;
// masterDofAndFactorsBeforeDegenerated.push_back( std::make_pair(masterDofBeforeDegenerated, factor) );
// }
// }
// }
//
// const int iPol = CommonParameters::EX_POLARIZATION;// Constraint matrix does not depend on the type of polarization
// for( std::vector< std::pair<int,double> >::const_iterator itr = masterDofAndFactorsBeforeDegenerated.begin(); itr != masterDofAndFactorsBeforeDegenerated.end(); ++itr ){
// const int dofBeforeDegenerated = itr->first;
// const double factor = itr->second;
// //std::map<int,int>::const_iterator itrBeforeToAfter = arrayDofBeforeDegeneratedToAfterDegenerated.find(dofBeforeDegenerated);
// //if( itrBeforeToAfter == arrayDofBeforeDegeneratedToAfterDegenerated.end() ){
// // OutputFiles::m_logFile << "Error : Key " << dofBeforeDegenerated << " is not found in arrayDofBeforeDegeneratedToAfterDegenerated." << std::endl;
// // exit(1);
// //}
// //masterDofAndFactorsAfterDegenerated.push_back( std::make_pair( itrBeforeToAfter->second, factor ) );
// const int dofAfterDegenerated = m_IDsGlobal2AfterDegenerated[iPol][dofBeforeDegenerated];
// masterDofAndFactorsAfterDegenerated.push_back( std::make_pair( dofAfterDegenerated, factor ) );
// }
//
//}
//
//void Forward3DNonConformingHexaElement0thOrder::makePairOfMasterDofAndFactorForASlaveDofAux( const int slaveDofBeforeDegenerated, std::vector< std::pair<int,double> >& masterDofAndFactorsBeforeDegenerated ) const{
//
// std::map< int, std::vector< std::pair<int,double> > > masterDofBeforeDegeneratedAndFactorsAll;
//
// std::vector< std::pair<int,double> >& masterDofBeforeDegeneratedAndFactors = masterDofBeforeDegeneratedAndFactorsAll[slaveDofBeforeDegenerated];
// if( static_cast<int>( masterDofBeforeDegeneratedAndFactors.size() ) == 0 ){
// return;
// }
//
// // This dof depends on some master dofs
// for( std::vector< std::pair<int,double> >::const_iterator itr = masterDofBeforeDegeneratedAndFactors.begin(); itr != masterDofBeforeDegeneratedAndFactors.end(); ++itr ){
// const int masterDofBeforeDegenerated = itr->first;
// const double factor = itr->second;
// masterDofAndFactorsBeforeDegenerated.push_back( std::make_pair(masterDofBeforeDegenerated, factor) );
// }
//
//}
//
//// Get dof before degeneration from the after degeneration
//int Forward3DNonConformingHexaElement0thOrder::getDofBeforeDegenerationFromDofAfterDegeneration( const int dofAfterDegeneration ) const{
//
//
//}