void SolverOperator::setPreconditioner ( operatorPtr_Type _prec ) { ASSERT_PRE ( _prec.get() != this, "Self Assignment is forbidden" ); ASSERT_PRE ( _prec.get() != 0, "Can't assign a null pointer" ); M_prec = _prec; doSetPreconditioner(); }
int SolverOperator::Apply ( const vector_Type& X, vector_Type& Y ) const { ASSERT_PRE ( X.Map().SameAs ( M_oper->OperatorDomainMap() ), "X and domain map do no coincide \n" ); ASSERT_PRE ( Y.Map().SameAs ( M_oper->OperatorRangeMap() ) , "Y and range map do no coincide \n" ); return M_oper->Apply ( X, Y ); }
void SolverOperator::setOperator ( operatorPtr_Type _oper ) { ASSERT_PRE ( _oper.get() != this, "Can't self assign" ); ASSERT_PRE ( _oper.get() != 0, "Can't assign a null pointer" ); M_oper = _oper; doSetOperator(); }
const BCIdentifierBase* BCBase::operator[] ( const ID& i ) const { ASSERT_PRE( M_finalized, "BC List should be finalized before being accessed" ); ASSERT_BD( i < M_idVector.size() ); return M_idVector[ i ].get(); }
OneDFSIBC::container2D_Type OneDFSIBC::solveLinearSystem ( const container2D_Type& line1, const container2D_Type& line2, const container2D_Type& rhs ) const { #ifdef HAVE_LIFEV_DEBUG ASSERT_PRE ( line1.size() == 2 && line2.size() == 2 && rhs.size() == 2, "OneDFSIBC::solveLinearSystem works only for 2D vectors"); #endif Real determinant = line1[0] * line2[1] - line1[1] * line2[0]; #ifdef HAVE_LIFEV_DEBUG ASSERT ( determinant != 0, "Error: the 2x2 system on the boundary is not invertible." "\nCheck the boundary conditions."); #endif container2D_Type solution; solution[0] = ( line2[1] * rhs[0] - line1[1] * rhs[1] ) / determinant; solution[1] = ( - line2[0] * rhs[0] + line1[0] * rhs[1] ) / determinant; return solution; }
void WallTensionEstimatorCylindricalCoordinates<Mesh >::analyzeTensionsRecoveryCauchyStressesCylindrical ( void ) { LifeChrono chrono; chrono.start(); UInt dim = this->M_FESpace->dim(); constructGlobalStressVector(); for ( UInt iDOF = 0; iDOF < ( UInt ) this->M_FESpace->dof().numTotalDof(); iDOF++ ) { if ( this->M_displacement->blockMap().LID ( static_cast<EpetraInt_Type> (iDOF) ) != -1 ) // The Global ID is on the calling processors { (* (this->M_sigma) ).Scale (0.0); //Extracting the gradient of U on the current DOF for ( UInt iComp = 0; iComp < this->M_FESpace->fieldDim(); ++iComp ) { Int LIDid = this->M_displacement->blockMap().LID ( static_cast<EpetraInt_Type> (iDOF + iComp * dim + this->M_offset ) ); Int GIDid = this->M_displacement->blockMap().GID (static_cast<EpetraInt_Type> (LIDid) ); (* (this->M_sigma) ) (iComp, 0) = (*this->M_sigmaX) (GIDid); // (d_xX,d_yX,d_zX) (* (this->M_sigma) ) (iComp, 1) = (*this->M_sigmaY) (GIDid); // (d_xY,d_yY,d_zY) (* (this->M_sigma) ) (iComp, 2) = (*this->M_sigmaZ) (GIDid); // (d_xZ,d_yZ,d_zZ) } //Compute the eigenvalue AssemblyElementalStructure::computeEigenvalues (* (this->M_sigma), this->M_eigenvaluesR, this->M_eigenvaluesI); //The Cauchy tensor is symmetric and therefore, the eigenvalues are real //Check on the imaginary part of eigen values given by the Lapack method Real sum (0); for ( int i = 0; i < this->M_eigenvaluesI.size(); i++ ) { sum += std::abs (this->M_eigenvaluesI[i]); } ASSERT_PRE ( sum < 1e-6 , "The eigenvalues of the Cauchy stress tensors have to be real!" ); std::sort ( this->M_eigenvaluesR.begin(), this->M_eigenvaluesR.end() ); //Save the eigenvalues in the global vector for ( UInt icoor = 0; icoor < this->M_FESpace->fieldDim(); ++icoor ) { Int LIDid = this->M_displacement->blockMap().LID ( static_cast<EpetraInt_Type> (iDOF + icoor * dim + this->M_offset) ); Int GIDid = this->M_displacement->blockMap().GID (static_cast<EpetraInt_Type> (LIDid) ); (* (this->M_globalEigenvalues) ) (GIDid) = this->M_eigenvaluesR[icoor]; } } } chrono.stop(); this->M_displayer->leaderPrint ("Analysis done in: ", chrono.diff() ); }
MeshElementMarked<1, 2, GeoShape, MC>::MeshElementMarked ( ID identity ) : MeshElement<geoShape_Type, MeshElementMarked<0, 2, GeoShape, MC> > ( identity ), M_firstAdjacentElementIdentity ( NotAnId ), M_secondAdjacentElementIdentity ( NotAnId ), M_firstAdjacentElementPosition ( NotAnId ), M_secondAdjacentElementPosition ( NotAnId ) { ASSERT_PRE ( geoShape_Type::S_nDimensions == 1 , "geoElement1D in 2D geometry with incorrect GeoShape" ) ; }
int SolverOperator::ApplyInverse( const vector_Type& X, vector_Type& Y ) const { ASSERT_PRE( Y.Map().SameAs( M_oper->OperatorDomainMap() ), "Y and domain map do no coincide \n" ); ASSERT_PRE( X.Map().SameAs( M_oper->OperatorRangeMap() ) , "X and range map do no coincide \n" ); if ( M_useTranspose ) return -1; int result = doApplyInverse( X, Y ); M_numCumulIterations += M_numIterations; if( M_comm->MyPID() == 0 && M_printSubiterationCount ) { std::cout << "> " << numIterations() << " subiterations" << std::endl; } return result; }
MeshElementMarked<1, 2, GeoShape, MC>::MeshElementMarked ( const MeshElementMarked<1, 2, GeoShape, MC>& Element ) : MeshElement<geoShape_Type, MeshElementMarked<0, 2, GeoShape, MC> > ( Element ), MC::faceMarker_Type ( Element ), M_firstAdjacentElementIdentity ( Element.M_firstAdjacentElementIdentity), M_secondAdjacentElementIdentity ( Element.M_secondAdjacentElementIdentity), M_firstAdjacentElementPosition ( Element.M_firstAdjacentElementPosition ), M_secondAdjacentElementPosition ( Element.M_secondAdjacentElementPosition ) { ASSERT_PRE ( geoShape_Type::S_nDimensions == 1 , "geoElement1D in 2D Geometry with incorrect GeoShape" ) ; }
ID DOFInterface3Dto2D::vertex3Dto2D ( const ID& idpoint3D ) const { ASSERT_PRE ( M_finalized, "The list of vertices must be finalized before accessing to the interface vertices." ); for ( std::list< std::pair<ID, ID> >::const_iterator it = M_vertexList.begin(); it != M_vertexList.end(); ++it ) { if ( it->first == idpoint3D ) { return it->second; } } ERROR_MSG ( "There is no such 3D index of vertex in the M_vertexList." ); return ID(); }
MeshElementMarked<1, 3, GeoShape, MC>::MeshElementMarked ( const MeshElementMarked<1, 3, GeoShape, MC>& Element ) : MeshElement<geoShape_Type, MeshElementMarked<0, 3, GeoShape, MC> > ( Element ), MC::edgeMarker_Type ( Element ) { ASSERT_PRE ( geoShape_Type::S_nDimensions == 1 , "geoElement1D with incorrect GeoShape" ) ; }
MeshElementMarked<1, 3, GeoShape, MC>::MeshElementMarked ( ID identity ) : MeshElement<geoShape_Type, MeshElementMarked<0, 3, GeoShape, MC> > ( identity ) { ASSERT_PRE ( geoShape_Type::S_nDimensions == 1 , "geoElement1D with incorrect GeoShape" ) ; }
void HyperbolicSolver<Mesh, SolverType>:: setup () { // LAPACK wrapper of Epetra Epetra_LAPACK lapack; // Flags for LAPACK routines. Int INFO[1] = {0}; Int NB = M_FESpace.refFE().nbDof(); // Parameter that indicate the Lower storage of matrices. char param_L = 'L'; // Total number of elements. UInt meshNumberOfElements = M_FESpace.mesh()->numElements(); // Vector of interpolation of the mass function vector_Type vectorMass ( M_FESpace.map(), Repeated ); // If the mass function is given take it, otherwise use one as a value. if ( M_mass != NULL ) { // Interpolate the mass function on the finite element space. M_FESpace.interpolate ( M_mass, vectorMass ); } else { vectorMass = 1.; } // For each element it creates the mass matrix and factorize it using Cholesky. for ( UInt iElem (0); iElem < meshNumberOfElements; ++iElem ) { // Update the element. M_FESpace.fe().update ( M_FESpace.mesh()->element ( iElem), UPDATE_QUAD_NODES | UPDATE_WDET ); // Local mass matrix MatrixElemental matElem (M_FESpace.refFE().nbDof(), 1, 1); matElem.zero(); // Compute the mass matrix for the current element VectorElemental massValue ( M_FESpace.refFE().nbDof(), 1 ); extract_vec ( vectorMass, massValue, M_FESpace.refFE(), M_FESpace.dof(), iElem, 0 ); // TODO: this works only for P0 mass ( massValue[ 0 ], matElem, M_FESpace.fe(), 0, 0); /* Put in M the matrix L and L^T, where L and L^T is the Cholesky factorization of M. For more details see http://www.netlib.org/lapack/double/dpotrf.f */ lapack.POTRF ( param_L, NB, matElem.mat(), NB, INFO ); ASSERT_PRE ( !INFO[0], "Lapack factorization of M is not achieved." ); // Save the local mass matrix in the global vector of mass matrices M_elmatMass.push_back ( matElem ); } //make sure mesh facets are updated if (! M_FESpace.mesh()->hasLocalFacets() ) { M_FESpace.mesh()->updateElementFacets(); } } // setup
void NeoHookeanMaterialNonLinear<Mesh>::computeKinematicsVariables ( const VectorElemental& dk_loc ) { Real s; //! loop on quadrature points (ig) for ( UInt ig = 0; ig < this->M_FESpace->fe().nbQuadPt(); ig++ ) { //! loop on space coordinates (icoor) for ( UInt icoor = 0; icoor < nDimensions; icoor++ ) { //! loop on space coordinates (jcoor) for ( UInt jcoor = 0; jcoor < nDimensions; jcoor++ ) { s = 0.0; for ( UInt i = 0; i < this->M_FESpace->fe().nbFEDof(); i++ ) { //! \grad u^k at a quadrature point s += this->M_FESpace->fe().phiDer ( i, jcoor, ig ) * dk_loc[ i + icoor * this->M_FESpace->fe().nbFEDof() ]; } //! gradient of displacement (*M_Fk) [ icoor ][ jcoor ][ig ] = s; } } } //! loop on quadrature points (ig) for ( UInt ig = 0; ig < this->M_FESpace->fe().nbQuadPt(); ig++ ) { //! loop on space coordinates (icoor) for ( UInt icoor = 0; icoor < nDimensions; icoor++ ) { //! deformation gradient Fk (*M_Fk) [ icoor ][ icoor ][ ig ] += 1.0; } } Real a, b, c, d, e, f, g, h, i; for ( UInt ig = 0; ig < this->M_FESpace->fe().nbQuadPt(); ig++ ) { a = (*M_Fk) [ 0 ][ 0 ][ ig ]; b = (*M_Fk) [ 0 ][ 1 ][ ig ]; c = (*M_Fk) [ 0 ][ 2 ][ ig ]; d = (*M_Fk) [ 1 ][ 0 ][ ig ]; e = (*M_Fk) [ 1 ][ 1 ][ ig ]; f = (*M_Fk) [ 1 ][ 2 ][ ig ]; g = (*M_Fk) [ 2 ][ 0 ][ ig ]; h = (*M_Fk) [ 2 ][ 1 ][ ig ]; i = (*M_Fk) [ 2 ][ 2 ][ ig ]; //! determinant of deformation gradient Fk (*M_Jack) [ig] = a * ( e * i - f * h ) - b * ( d * i - f * g ) + c * ( d * h - e * g ); ASSERT_PRE ( (*M_Jack) [ig] > 0, "Negative Jacobian. Error!" ); (*M_CofFk) [ 0 ][ 0 ][ ig ] = ( e * i - f * h ); (*M_CofFk) [ 0 ][ 1 ][ ig ] = - ( d * i - g * f ); (*M_CofFk) [ 0 ][ 2 ][ ig ] = ( d * h - e * g ); (*M_CofFk) [ 1 ][ 0 ][ ig ] = - ( b * i - c * h ); (*M_CofFk) [ 1 ][ 1 ][ ig ] = ( a * i - c * g ); (*M_CofFk) [ 1 ][ 2 ][ ig ] = - ( a * h - g * b ); (*M_CofFk) [ 2 ][ 0 ][ ig ] = ( b * f - c * e ); (*M_CofFk) [ 2 ][ 1 ][ ig ] = - ( a * f - c * d ); (*M_CofFk) [ 2 ][ 2 ][ ig ] = ( a * e - d * b ); } //! loop on quadrature points for ( UInt ig = 0; ig < this->M_FESpace->fe().nbQuadPt(); ig++ ) { s = 0.0; for ( UInt i = 0; i < nDimensions; i++) { for ( UInt j = 0; j < nDimensions; j++) { //! trace of C1 = (F1k^t F1k) s += (*M_Fk) [ i ][ j ][ ig ] * (*M_Fk) [ i ][ j ][ ig ]; } } (*M_trCk) [ ig ] = s; } for ( UInt ig = 0; ig < this->M_FESpace->fe().nbQuadPt(); ig++ ) { //! trace of deviatoric C (*M_trCisok) [ ig ] = pow ( (*M_Jack) [ ig ], -2. / 3.) * (*M_trCk) [ ig ]; } }
void WallTensionEstimatorCylindricalCoordinates<Mesh >::analyzeTensionsRecoveryEigenvaluesCylindrical ( void ) { LifeChrono chrono; this->M_displayer->leaderPrint (" \n*********************************\n "); this->M_displayer->leaderPrint (" Performing the analysis recovering the tensions..., ", this->M_dataMaterial->solidType() ); this->M_displayer->leaderPrint (" \n*********************************\n "); solutionVect_Type patchArea (* (this->M_displacement), Unique, Add); patchArea *= 0.0; super::constructPatchAreaVector ( patchArea ); //Before assembling the reconstruction process is done solutionVect_Type patchAreaR (patchArea, Repeated); QuadratureRule fakeQuadratureRule; Real refElemArea (0); //area of reference element //compute the area of reference element for (UInt iq = 0; iq < this->M_FESpace->qr().nbQuadPt(); iq++) { refElemArea += this->M_FESpace->qr().weight (iq); } Real wQuad (refElemArea / this->M_FESpace->refFE().nbDof() ); //Setting the quadrature Points = DOFs of the element and weight = 1 std::vector<GeoVector> coords = this->M_FESpace->refFE().refCoor(); std::vector<Real> weights (this->M_FESpace->fe().nbFEDof(), wQuad); fakeQuadratureRule.setDimensionShape ( shapeDimension (this->M_FESpace->refFE().shape() ), this->M_FESpace->refFE().shape() ); fakeQuadratureRule.setPoints (coords, weights); //Set the new quadrature rule this->M_FESpace->setQuadRule (fakeQuadratureRule); UInt totalDof = this->M_FESpace->dof().numTotalDof(); VectorElemental dk_loc (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); //Vectors for the deformation tensor std::vector<matrix_Type> vectorDeformationF (this->M_FESpace->fe().nbFEDof(), * (this->M_deformationF) ); //Copying the displacement field into a vector with repeated map for parallel computations solutionVect_Type dRep (* (this->M_displacement), Repeated); VectorElemental elVecTens (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); chrono.start(); //Loop on each volume for ( UInt i = 0; i < this->M_FESpace->mesh()->numVolumes(); ++i ) { this->M_FESpace->fe().updateFirstDerivQuadPt ( this->M_FESpace->mesh()->volumeList ( i ) ); elVecTens.zero(); this->M_marker = this->M_FESpace->mesh()->volumeList ( i ).markerID(); UInt eleID = this->M_FESpace->fe().currentLocalId(); //Extracting the local displacement for ( UInt iNode = 0; iNode < ( UInt ) this->M_FESpace->fe().nbFEDof(); iNode++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( iNode ); for ( UInt iComp = 0; iComp < this->M_FESpace->fieldDim(); ++iComp ) { UInt ig = this->M_FESpace->dof().localToGlobalMap ( eleID, iloc ) + iComp * this->M_FESpace->dim() + this->M_offset; dk_loc[iloc + iComp * this->M_FESpace->fe().nbFEDof()] = dRep[ig]; } } //Compute the element tensor F AssemblyElementalStructure::computeLocalDeformationGradientWithoutIdentity ( dk_loc, vectorDeformationF, this->M_FESpace->fe() ); //Compute the local vector of the principal stresses for ( UInt nDOF = 0; nDOF < ( UInt ) this->M_FESpace->fe().nbFEDof(); nDOF++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( nDOF ); vector_Type localDisplacement (this->M_FESpace->fieldDim(), 0.0); for ( UInt coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { localDisplacement[coor] = iloc + coor * this->M_FESpace->fe().nbFEDof(); } this->M_sigma->Scale (0.0); this->M_firstPiola->Scale (0.0); this->M_cofactorF->Scale (0.0); M_deformationCylindricalF->Scale (0.0); moveToCylindricalCoordinates (vectorDeformationF[nDOF], iloc, *M_deformationCylindricalF); //Compute the rightCauchyC tensor AssemblyElementalStructure::computeInvariantsRightCauchyGreenTensor (this->M_invariants, *M_deformationCylindricalF, * (this->M_cofactorF) ); //Compute the first Piola-Kirchhoff tensor this->M_material->computeLocalFirstPiolaKirchhoffTensor (* (this->M_firstPiola), *M_deformationCylindricalF, * (this->M_cofactorF), this->M_invariants, this->M_marker); //Compute the Cauchy tensor AssemblyElementalStructure::computeCauchyStressTensor (* (this->M_sigma), * (this->M_firstPiola), this->M_invariants[3], *M_deformationCylindricalF); //Compute the eigenvalue AssemblyElementalStructure::computeEigenvalues (* (this->M_sigma), this->M_eigenvaluesR, this->M_eigenvaluesI); //The Cauchy tensor is symmetric and therefore, the eigenvalues are real //Check on the imaginary part of eigen values given by the Lapack method Real sum (0); for ( int i = 0; i < this->M_eigenvaluesI.size(); i++ ) { sum += std::abs (this->M_eigenvaluesI[i]); } ASSERT_PRE ( sum < 1e-6 , "The eigenvalues of the Cauchy stress tensors have to be real!" ); std::sort ( this->M_eigenvaluesR.begin(), this->M_eigenvaluesR.end() ); //Assembling the local vector for ( int coor = 0; coor < this->M_eigenvaluesR.size(); coor++ ) { elVecTens[iloc + coor * this->M_FESpace->fe().nbFEDof()] = this->M_eigenvaluesR[coor]; } } super::reconstructElementaryVector ( elVecTens, patchAreaR, *this->M_FESpace ); //Assembling the local into global vector for ( UInt ic = 0; ic < this->M_FESpace->fieldDim(); ++ic ) { assembleVector (* (this->M_globalEigenvalues), elVecTens, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); } } this->M_globalEigenvalues->globalAssemble(); chrono.stop(); this->M_displayer->leaderPrint ("Analysis done in: ", chrono.diff() ); }
void HyperbolicSolver< Mesh, SolverType >:: localEvolve ( const UInt& iElem ) { // LAPACK wrapper of Epetra Epetra_LAPACK lapack; // Flags for LAPACK routines. Int INFO[1] = { 0 }; Int NB = M_FESpace.refFE().nbDof(); // Parameter that indicate the Lower storage of matrices. char param_L = 'L'; char param_N = 'N'; // Paramater that indicate the Transpose of matrices. char param_T = 'T'; // Numbers of columns of the right hand side := 1. Int NBRHS = 1; // Clean the local flux M_localFlux.zero(); // Loop on the faces of the element iElem and compute the local contribution for ( UInt iFace (0); iFace < M_FESpace.mesh()->numLocalFaces(); ++iFace ) { // Id mapping const UInt iGlobalFace ( M_FESpace.mesh()->localFacetId ( iElem, iFace ) ); // Take the left element to the face, see regionMesh for the meaning of left element const UInt leftElement ( M_FESpace.mesh()->faceElement ( iGlobalFace, 0 ) ); // Take the right element to the face, see regionMesh for the meaning of right element const UInt rightElement ( M_FESpace.mesh()->faceElement ( iGlobalFace, 1 ) ); // Update the normal vector of the current face in each quadrature point M_FESpace.feBd().updateMeasNormalQuadPt ( M_FESpace.mesh()->boundaryFacet ( iGlobalFace ) ); // Local flux of a face times the integration weight VectorElemental localFaceFluxWeight ( M_FESpace.refFE().nbDof(), 1 ); // Solution in the left element VectorElemental leftValue ( M_FESpace.refFE().nbDof(), 1 ); // Solution in the right element VectorElemental rightValue ( M_FESpace.refFE().nbDof(), 1 ); // Extract the solution in the current element, now is the leftElement extract_vec ( *M_uOld, leftValue, M_FESpace.refFE(), M_FESpace.dof(), leftElement , 0 ); // Check if the current face is a boundary face, that is rightElement == NotAnId if ( !Flag::testOneSet ( M_FESpace.mesh()->face ( iGlobalFace ).flag(), EntityFlags::PHYSICAL_BOUNDARY | EntityFlags::SUBDOMAIN_INTERFACE ) ) { // Extract the solution in the current element, now is the leftElement extract_vec ( *M_uOld, rightValue, M_FESpace.refFE(), M_FESpace.dof(), rightElement , 0 ); } else if ( Flag::testOneSet ( M_FESpace.mesh()->face ( iGlobalFace ).flag(), EntityFlags::SUBDOMAIN_INTERFACE ) ) { // TODO: this works only for P0 elements rightValue[ 0 ] = M_ghostDataMap[ iGlobalFace ]; } else // Flag::testOneSet ( M_FESpace.mesh()->face ( iGlobalFace ).flag(), PHYSICAL_BOUNDARY ) { // Clean the value of the right element rightValue.zero(); // Check if the boundary conditions were updated. if ( !M_BCh->bcUpdateDone() ) { // Update the boundary conditions handler. We use the finite element of the boundary of the dual variable. M_BCh->bcUpdate ( *M_FESpace.mesh(), M_FESpace.feBd(), M_FESpace.dof() ); } // Take the boundary marker for the current boundary face const ID faceMarker ( M_FESpace.mesh()->boundaryFacet ( iGlobalFace ).markerID() ); // Take the corrispective boundary function const BCBase& bcBase ( M_BCh->findBCWithFlag ( faceMarker ) ); // Check if the bounday condition is of type Essential, useful for operator splitting strategies if ( bcBase.type() == Essential ) { // Loop on all the quadrature points for ( UInt ig (0); ig < M_FESpace.feBd().nbQuadPt(); ++ig) { // Current quadrature point KN<Real> quadPoint (3); // normal vector KN<Real> normal (3); for (UInt icoor (0); icoor < 3; ++icoor) { quadPoint (icoor) = M_FESpace.feBd().quadPt ( ig, icoor ); normal (icoor) = M_FESpace.feBd().normal ( icoor, ig ) ; } // Compute the boundary contribution rightValue[0] = bcBase ( M_data.dataTime()->time(), quadPoint (0), quadPoint (1), quadPoint (2), 0 ); const Real localFaceFlux = M_numericalFlux->firstDerivativePhysicalFluxDotNormal ( normal, iElem, M_data.dataTime()->time(), quadPoint (0), quadPoint (1), quadPoint (2), rightValue[ 0 ] ); // Update the local flux of the current face with the quadrature weight localFaceFluxWeight[0] += localFaceFlux * M_FESpace.feBd().weightMeas ( ig ); } } else { /* If the boundary flag is not Essential then is automatically an outflow boundary. We impose to localFaceFluxWeight a positive value. */ localFaceFluxWeight[0] = 1.; } // It is an outflow face, we use a ghost cell if ( localFaceFluxWeight[0] > 1e-4 ) { rightValue = leftValue; } // Clean the localFaceFluxWeight localFaceFluxWeight.zero(); } // Clean the localFaceFluxWeight localFaceFluxWeight.zero(); // Loop on all the quadrature points for ( UInt ig (0); ig < M_FESpace.feBd().nbQuadPt(); ++ig ) { // Current quadrature point KN<Real> quadPoint (3); // normal vector KN<Real> normal (3); for (UInt icoor (0); icoor < 3; ++icoor) { quadPoint (icoor) = M_FESpace.feBd().quadPt ( ig, icoor ); normal (icoor) = M_FESpace.feBd().normal ( icoor, ig ) ; } // If the normal is orientated inward, we change its sign and swap the left and value of the solution if ( iElem == rightElement ) { normal *= -1.; std::swap ( leftValue, rightValue ); } const Real localFaceFlux = (*M_numericalFlux) ( leftValue[ 0 ], rightValue[ 0 ], normal, iElem, M_data.dataTime()->time(), quadPoint (0), quadPoint (1), quadPoint (2) ); // Update the local flux of the current face with the quadrature weight localFaceFluxWeight[0] += localFaceFlux * M_FESpace.feBd().weightMeas ( ig ); } /* Put in localFlux the vector L^{-1} * localFlux For more details see http://www.netlib.org/lapack/lapack-3.1.1/SRC/dtrtrs.f */ lapack.TRTRS ( param_L, param_N, param_N, NB, NBRHS, M_elmatMass[ iElem ].mat(), NB, localFaceFluxWeight, NB, INFO); ASSERT_PRE ( !INFO[0], "Lapack Computation M_elvecSource = LB^{-1} rhs is not achieved." ); /* Put in localFlux the vector L^{-T} * localFlux For more details see http://www.netlib.org/lapack/lapack-3.1.1/SRC/dtrtrs.f */ lapack.TRTRS ( param_L, param_T, param_N, NB, NBRHS, M_elmatMass[ iElem ].mat(), NB, localFaceFluxWeight, NB, INFO); ASSERT_PRE ( !INFO[0], "Lapack Computation M_elvecSource = LB^{-1} rhs is not achieved." ); // Add to the local flux the local flux of the current face M_localFlux += localFaceFluxWeight; } } // localEvolve
ID DOFInterface3Dto2D::operator[] ( const UInt& i ) const { ASSERT_PRE ( M_finalized, "The face List should be finalised before being accessed" ); ASSERT_BD ( i < M_faceList.size() ); return M_faceList[ i ].first; // M_faceList must be a vector! }