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);
}