void WallTensionEstimatorCylindricalCoordinates<Mesh >::constructGlobalStressVector() { //Creating the local stress tensors VectorElemental elVecSigmaX (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); VectorElemental elVecSigmaY (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); VectorElemental elVecSigmaZ (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); LifeChrono chrono; //Constructing the patch area vector for reconstruction purposes 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); this->M_displayer->leaderPrint (" \n*********************************\n "); this->M_displayer->leaderPrint (" Performing the analysis recovering the Cauchy stresses..., ", this->M_dataMaterial->solidType() ); this->M_displayer->leaderPrint (" \n*********************************\n "); 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); 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 ) ); elVecSigmaX.zero(); elVecSigmaY.zero(); elVecSigmaZ.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); this->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); //Assembling the local vectors for local tensions Component X for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaX) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 0); } //Assembling the local vectors for local tensions Component Y for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaY) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 1); } //Assembling the local vectors for local tensions Component Z for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaZ) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 2); } } super::reconstructElementaryVector ( elVecSigmaX, patchAreaR, *this->M_FESpace ); super::reconstructElementaryVector ( elVecSigmaY, patchAreaR, *this->M_FESpace ); super::reconstructElementaryVector ( elVecSigmaZ, patchAreaR, *this->M_FESpace ); //Assembling the three elemental vector in the three global for ( UInt ic = 0; ic < this->M_FESpace->fieldDim(); ++ic ) { assembleVector (*this->M_sigmaX, elVecSigmaX, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); assembleVector (*this->M_sigmaY, elVecSigmaY, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); assembleVector (*this->M_sigmaZ, elVecSigmaZ, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); } } this->M_sigmaX->globalAssemble(); this->M_sigmaY->globalAssemble(); this->M_sigmaZ->globalAssemble(); }
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
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() ); }