/*===========================================================================*/ const kvs::Real32 QuadraticTetrahedralCell::volume() const { const kvs::Vec3 v0( 0, 0, 0 ); const kvs::Vec3 v1( 1, 0, 0 ); const kvs::Vec3 v2( 0, 0, 1 ); const kvs::Vec3 v3( 0, 1, 0 ); const kvs::Vec3 v4( 0.5, 0, 0 ); const kvs::Vec3 v5( 0, 0,0.5 ); const kvs::Vec3 v6( 0,0.5, 0 ); const kvs::Vec3 v7( 0.5, 0,0.5 ); const kvs::Vec3 v8( 0,0.5,0.5 ); const kvs::Vec3 v9( 0.5,0.5, 0 ); const kvs::Vec3 c[8] = { ( v0 + v4 + v5 + v6 ) * 0.25, ( v4 + v1 + v7 + v9 ) * 0.25, ( v5 + v7 + v2 + v8 ) * 0.25, ( v6 + v9 + v8 + v3 ) * 0.25, ( v4 + v7 + v5 + v6 ) * 0.25, ( v4 + v9 + v7 + v6 ) * 0.25, ( v8 + v6 + v5 + v7 ) * 0.25, ( v8 + v7 + v9 + v6 ) * 0.25 }; float sum_metric = 0; for( size_t i = 0 ; i < 8 ; i++ ) { BaseClass::setLocalPoint( c[i] ); const kvs::Mat3 J = BaseClass::JacobiMatrix(); const float metric_element = J.determinant(); sum_metric += kvs::Math::Abs<float>( metric_element ); } return sum_metric / ( 6.0f * 8.0f ); }
/*===========================================================================*/ const kvs::Mat3 CellBase::gradientTensor() const { KVS_ASSERT( m_veclen == 3 ); // Calculate a gradient tensor in the local coordinate. const kvs::UInt32 nnodes = m_nnodes; const float* dNdp = m_differential_functions; const float* dNdq = m_differential_functions + nnodes; const float* dNdr = m_differential_functions + nnodes + nnodes; const kvs::Real32* Su = m_values; const kvs::Real32* Sv = Su + nnodes; const kvs::Real32* Sw = Sv + nnodes; const float dudp = this->interpolateValue( Su, dNdp, nnodes ); const float dudq = this->interpolateValue( Su, dNdq, nnodes ); const float dudr = this->interpolateValue( Su, dNdr, nnodes ); const float dvdp = this->interpolateValue( Sv, dNdp, nnodes ); const float dvdq = this->interpolateValue( Sv, dNdq, nnodes ); const float dvdr = this->interpolateValue( Sv, dNdr, nnodes ); const float dwdp = this->interpolateValue( Sw, dNdp, nnodes ); const float dwdq = this->interpolateValue( Sw, dNdq, nnodes ); const float dwdr = this->interpolateValue( Sw, dNdr, nnodes ); const kvs::Mat3 t( dudp, dvdp, dwdp, dudq, dvdq, dwdq, dudr, dvdr, dwdr ); // Calculate a gradient tensor in the global coordinate. const kvs::Mat3 J = this->JacobiMatrix(); float determinant = 0.0f; const kvs::Mat3 T = 3.0f * J.inverted( &determinant ) * t; return kvs::Math::IsZero( determinant ) ? kvs::Mat3::Zero() : T; }
kvs::Mat3 PrismCell::gradient() { const kvs::Mat3 t = this->localGradient(); const kvs::Mat3 J = this->JacobiMatrix(); kvs::Real32 det = 0.0f; const kvs::Mat3 T = 3.0f * J.inverted( &det ) * t; return kvs::Math::IsZero( det ) ? kvs::Mat3::Zero() : T; }
/*===========================================================================*/ kvs::Vec3 TetrahedralCell::globalToLocal( const kvs::Vec3& global ) const { const kvs::Vec3 v3( BaseClass::coord(3) ); const kvs::Vec3 v03( BaseClass::coord(0) - v3 ); const kvs::Vec3 v13( BaseClass::coord(1) - v3 ); const kvs::Vec3 v23( BaseClass::coord(2) - v3 ); const kvs::Mat3 M( v03.x(), v13.x(), v23.x(), v03.y(), v13.y(), v23.y(), v03.z(), v13.z(), v23.z() ); return M.inverted() * ( global - v3 ); }
kvs::Vec3 PrismCell::globalToLocal( const kvs::Vec3 point ) { const kvs::Vec3 X( point ); const float TinyValue = static_cast<float>( 1.e-6 ); const size_t MaxLoop = 100; kvs::Vec3 x0( 0.3f, 0.3f, 0.5f ); for ( size_t i = 0; i < MaxLoop; i++ ) { this->setLocalPoint( x0 ); const kvs::Vec3 X0( this->localToGlobal( x0 ) ); const kvs::Vec3 dX( X - X0 ); const kvs::Mat3 J( this->JacobiMatrix() ); const kvs::Vec3 dx = J.transposed().inverted() * dX; if ( dx.length() < TinyValue ) break; // Converged. x0 += dx; } return x0; }
/*===========================================================================*/ const kvs::Vec3 CellBase::gradientVector() const { KVS_ASSERT( m_veclen == 1 ); // Calculate a gradient vector in the local coordinate. const kvs::UInt32 nnodes = m_nnodes; const float* dNdp = m_differential_functions; const float* dNdq = m_differential_functions + nnodes; const float* dNdr = m_differential_functions + nnodes + nnodes; const kvs::Real32* S = m_values; const float dSdp = this->interpolateValue( S, dNdp, nnodes ); const float dSdq = this->interpolateValue( S, dNdq, nnodes ); const float dSdr = this->interpolateValue( S, dNdr, nnodes ); const kvs::Vec3 g( dSdp, dSdq, dSdr ); // Calculate a gradient vector in the global coordinate. const kvs::Mat3 J = this->JacobiMatrix(); float determinant = 0.0f; const kvs::Vec3 G = 3.0f * J.inverted( &determinant ) * g; return kvs::Math::IsZero( determinant ) ? kvs::Vec3::Zero() : G; }
/*===========================================================================*/ const kvs::Vec3 CellBase::globalToLocal( const kvs::Vec3& global ) const { const kvs::Vec3 X( global ); // Calculate the coordinate of 'global' in the local coordinate // by using Newton-Raphson method. const float TinyValue = static_cast<float>( 1.e-6 ); const size_t MaxLoop = 100; kvs::Vec3 x0( 0.25f, 0.25f, 0.25f ); // Initial point in local coordinate. for ( size_t i = 0; i < MaxLoop; i++ ) { const kvs::Vec3 X0( this->localToGlobal( x0 ) ); const kvs::Vec3 dX( X - X0 ); const kvs::Mat3 J( this->JacobiMatrix() ); const kvs::Vec3 dx = J.transposed().inverted() * dX; if ( dx.length() < TinyValue ) break; // Converged. x0 += dx; } return x0; }