/** Multiplies tensor A, on the left by it's transpose, A^T to give A^T * A And returns the answer in a symmetric tensor*/ void TensorArray_MultiplyByLeftTranspose(TensorArray tensor, Dimension_Index dim, SymmetricTensor result) { TensorArray tensorTranspose; TensorArray fullTensorResult; TensorArray_Transpose( tensor, dim, tensorTranspose); TensorArray_MultiplyByTensorArray( tensorTranspose, tensor, dim, fullTensorResult ); /** Answer is automatically a symmetric tensor by definition */ TensorArray_GetSymmetricPart( fullTensorResult, dim, result); return; }
void DruckerPrager_Extra_GetSlipVector(void* druckerPrager_Extra, ConstitutiveMatrix* constitutiveMatrix, MaterialPointsSwarm* materialPointsSwarm, Element_LocalIndex lElement_I, MaterialPoint* materialPoint, Coord xi, double dpFrictionCoefficient) { DruckerPrager_Extra* self = (DruckerPrager_Extra*) druckerPrager_Extra; DruckerPrager_Extra_Particle* particleExt; double currentVelocityGradient[9]; Eigenvector eigenvectorList[3]; double strainRate_ns[2]; SymmetricTensor currentStrainRate; XYZ normal[2]; XYZ slip[2]; double theta; int favourablePlane, err; Dimension_Index dim = constitutiveMatrix->dim; /* stupid way to recover the integration point from the materialPoint * * TODO: FIXCONSTITUTIVE use integration point only */ IntegrationPoint* integrationPoint = (IntegrationPoint*) Swarm_ParticleAt( constitutiveMatrix->integrationSwarm, constitutiveMatrix->currentParticleIndex ); particleExt = (DruckerPrager_Extra_Particle*) ExtensionManager_Get( materialPointsSwarm->particleExtensionMgr, materialPoint, self->particleExtHandle ); /* get velocity Gradients */ err = PpcManager_Get( self->mgr, lElement_I, integrationPoint, self->velocityGradientsTag, currentVelocityGradient ); if( err ) assert(0); TensorArray_GetSymmetricPart( currentVelocityGradient, dim, currentStrainRate ); /* Slip vector does not have anything to do with the constitutive behaviour since isotropic so should try and find max shear strain rate by calculating eigenvectors of strainrate */ SymmetricTensor_CalcAllEigenvectors( currentStrainRate, dim, eigenvectorList ); /* Since isotropic, the max shear stress always lies at theta = 45 degrees on mohr circle, so to for strain rate? */ theta = M_PI / 4.0; if (dim == 2) { /* Identify potential failure directions */ StGermain_RotateCoordinateAxis( slip[0], eigenvectorList[0].vector, K_AXIS, +theta); StGermain_RotateCoordinateAxis( slip[1], eigenvectorList[0].vector, K_AXIS, -theta); StGermain_RotateCoordinateAxis( normal[0], eigenvectorList[0].vector, K_AXIS, 0.5*M_PI + theta); StGermain_RotateCoordinateAxis( normal[1], eigenvectorList[0].vector, K_AXIS, 0.5*M_PI - theta); } else { /* Identify potential failure directions */ StGermain_RotateVector( slip[0], eigenvectorList[0].vector, eigenvectorList[1].vector, + theta ); StGermain_RotateVector( slip[1], eigenvectorList[0].vector, eigenvectorList[1].vector, - theta ); StGermain_RotateVector( normal[0], eigenvectorList[0].vector, eigenvectorList[1].vector, 0.5*M_PI + theta); StGermain_RotateVector( normal[1], eigenvectorList[0].vector, eigenvectorList[1].vector, 0.5*M_PI - theta); } /* Resolve shear strain-rate for the potential failure planes */ strainRate_ns[0] = fabs(TensorArray_MultiplyByVectors( currentVelocityGradient, slip[0], normal[0], dim )); strainRate_ns[1] = fabs(TensorArray_MultiplyByVectors( currentVelocityGradient, slip[1], normal[1], dim )); /* Choose the plane which is oriented favorably for continued slip */ favourablePlane = (strainRate_ns[0] > strainRate_ns[1] ? 0 : 1); memcpy( particleExt->slip, slip[favourablePlane], dim * sizeof(double) ); particleExt->slipRate = strainRate_ns[ favourablePlane ]; }