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 ]; }
void _lucEigenvectorsCrossSection_DrawCrossSection( void* drawingObject, lucDatabase* database, Dimension_Index dim ) { lucEigenvectorsCrossSection* self = (lucEigenvectorsCrossSection*)drawingObject; FieldVariable* tensorField = self->fieldVariable; SymmetricTensor tensor; Eigenvector eigenvectorList[3]; Dimension_Index dim_I; Index aIndex, bIndex; /* Sample the 2d cross-section */ lucCrossSection_SampleField(self, False); for ( aIndex = 0 ; aIndex < self->resolutionA ; aIndex++ ) { for ( bIndex = 0 ; bIndex < self->resolutionB ; bIndex++ ) { if (self->values[aIndex][bIndex][0] != HUGE_VAL) { /* Get tensor data & position */ int t; for (t=0; t<tensorField->fieldComponentCount; t++) tensor[t] = self->values[aIndex][bIndex][t]; SymmetricTensor_CalcAllEigenvectors( tensor, dim, eigenvectorList ); float pos[3] = {self->vertices[aIndex][bIndex][0], self->vertices[aIndex][bIndex][1], self->vertices[aIndex][bIndex][2]}; if (self->plotEigenVector) { for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) { float vec[3] = {eigenvectorList[ dim_I ].vector[0], eigenvectorList[ dim_I ].vector[1], eigenvectorList[ dim_I ].vector[2]}; lucDatabase_AddVertices(database, 1, lucVectorType, pos); lucDatabase_AddRGBA(database, lucVectorType, self->opacity, &self->colours[ dim_I ]); if (self->useEigenValue) { vec[0] *= eigenvectorList[ dim_I ].eigenvalue; vec[1] *= eigenvectorList[ dim_I ].eigenvalue; if (dim > 2) vec[2] *= eigenvectorList[ dim_I ].eigenvalue; else vec[2] = 0; } lucDatabase_AddVectors(database, 1, lucVectorType, 0, 1, vec); } } if (self->plotEigenValue) { float pointSize = 0; for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) { lucDatabase_AddVertices(database, 1, lucShapeType, pos); /* The EigenValue can be negative.... Got to attribute a potential */ /* colour for negative values, one for each dim as well */ if ( eigenvectorList[ dim_I ].eigenvalue >= 0) { pointSize = eigenvectorList[ dim_I ].eigenvalue; lucDatabase_AddRGBA(database, lucShapeType, self->opacity, &self->colours[ dim_I ]); } else { pointSize = -eigenvectorList[ dim_I ].eigenvalue; lucDatabase_AddRGBA(database, lucShapeType, self->opacity, &self->colourForNegative[ dim_I ]); } lucDatabase_AddValues(database, 1, lucShapeType, lucXWidthData, NULL, &pointSize); } } } } } lucCrossSection_FreeSampleData(self); }