void _DruckerPrager_Extra_Initialise( void* rheology, void* data ) {
    DruckerPrager_Extra*                  self                  = (DruckerPrager_Extra*) rheology;
    Particle_Index                  lParticle_I;
    Particle_Index                  particleLocalCount;
    XYZ                             slip                  = { 0.0,0.0,0.0 };
    double*                         ptr;
    _VonMises_Initialise( self, data );

    /* We should only set initial conditions if in regular non-restart mode. If in restart mode, then
    the particle-based variables will be set correcty when we re-load the Swarm. */
    if ( self->context->loadSwarmsFromCheckpoint == False ) {
        Stg_Component_Initialise( self->tensileFailure, data, False );
        Stg_Component_Initialise( self->slip, data, False );
        Stg_Component_Initialise( self->slipRate, data, False );
        Stg_Component_Initialise( self->fullySoftened, data, False );
        /* We don't need to Initialise hasYieldedVariable because it's a parent variable and _YieldRheology_Initialise
         * has already been called */
        particleLocalCount = self->hasYieldedVariable->variable->arraySize;

        for ( lParticle_I = 0 ; lParticle_I < particleLocalCount ; lParticle_I++ ) {

            Variable_SetValueChar( self->hasYieldedVariable->variable, lParticle_I, False );
            Variable_SetValueChar( self->tensileFailure->variable,lParticle_I, False );
            Variable_SetValueDouble( self->plasticStrainRate->variable,     lParticle_I, 0.0 );
            Variable_SetValueDouble( self->backgroundStrainRate->variable,     lParticle_I, 0.0 );
            ptr = Variable_GetPtrDouble( self->slip->variable, lParticle_I );
            memcpy( ptr, slip, sizeof(Coord) );
            Variable_SetValueDouble( self->slipRate->variable, data, 0.0 );
            Variable_SetValueInt( self->fullySoftened->variable, data, 0 );

        }
    }
}
void Variable_SetValueFromDictionary( void* _variable, Index index, Dictionary* dictionary ) {
	Variable*          variable = (Variable*)_variable;

	Variable_Update( variable );
	
	/* Assign variable from dictionary according to data type */
	switch (variable->dataTypes[0]) {
		case Variable_DataType_Char:
			Variable_SetValueChar(  variable, index, Dictionary_GetUnsignedInt( dictionary, variable->name ));
			break;
		case Variable_DataType_Short:
			Variable_SetValueShort( variable, index, Dictionary_GetUnsignedInt( dictionary, variable->name ));
			break;
		case Variable_DataType_Int:
			Variable_SetValueInt( variable, index, Dictionary_GetInt( dictionary, (Dictionary_Entry_Key)variable->name ) );
			break;
		case Variable_DataType_Float:
			Variable_SetValueFloat(  variable, index, Dictionary_GetDouble( dictionary, variable->name ));
			break;
		case Variable_DataType_Double:
			Variable_SetValueDouble( variable, index, Dictionary_GetDouble( dictionary, variable->name ));
			break;
		default: {
			Journal_Printf( 
				Journal_MyStream( Error_Type, variable ), 
				"In func %s: Unable to set value of %s from dictionary.", 
				__func__, 
				variable->name );
		}
	}
}
void VariableSuite_TestSetValueDouble( VariableSuiteData* data ) {
    Index                   ii;
    double tmp;
    Variable*      var = Variable_Register_GetByName( data->vr, "temperature" );

    /* Fill the temperature Variable with another known pattern of kinda random (bit filling) numbers */
    for( ii = 0; ii < data->aSize[0]; ii++ ) {

        Variable_SetValueDouble( var, ii, 1.0f - ( 1.0f / (data->aSize[0]+2) * (ii+1) ) );
    }

    /* Check that Variable_SetValueDouble on the temperature Variable set the right numbers */
    for( ii = 0; ii < data->aSize[0]; ii++ ) {
        tmp = 1.0f - 1.0f / (data->aSize[0]+2) * (ii+1);

        pcu_check_true( fabs(data->temperature[ii] - tmp ) < 1e-12);
    }
}
int main( int argc, char *argv[] ) {
	MPI_Comm		CommWorld;
	int		rank;
	int		procCount;
	int		procToWatch;
	
	/* Initialise MPI, get world info */
	MPI_Init( &argc, &argv );
	MPI_Comm_dup( MPI_COMM_WORLD, &CommWorld );
	MPI_Comm_size( MPI_COMM_WORLD, &procCount );
	MPI_Comm_rank( MPI_COMM_WORLD, &rank );
	
	Base_Init( &argc, &argv );
	
	DiscretisationGeometry_Init( &argc, &argv );
	DiscretisationShape_Init( &argc, &argv );
	DiscretisationMesh_Init( &argc, &argv );
	DiscretisationUtils_Init( &argc, &argv );
	MPI_Barrier( CommWorld ); /* Ensures copyright info always come first in output */
	
	if( argc >= 2 ) {
		procToWatch = atoi( argv[1] );
	}
	else {
		procToWatch = 0;
	}
	if( rank == procToWatch ) {
		DofLayout*		dof;
		Variable_Register*	variableRegister;
		Variable*		var[6];
		char*			varName[] = {"x", "y", "z", "vx", "vy", "vz"};
		Index			ii, var_I;
		Index			arraySize = 27;
		double*			varArrays[6];

		/* Create variable register */
		variableRegister = Variable_Register_New();

		/* Create variables */
		for (var_I = 0; var_I < 6; var_I++) {
			varArrays[var_I] = Memory_Alloc_Array_Unnamed( double, arraySize );
			var[var_I] = Variable_NewScalar( varName[var_I], Variable_DataType_Double, &arraySize, 
				(void**)&(varArrays[var_I]), variableRegister );
			Build( var[var_I], 0, False );	
			Initialise( var[var_I], 0, False );	
		}
			
		for (ii = 0; ii < arraySize; ii++) {
			for (var_I = 0; var_I < 6; var_I++) {
				Variable_SetValueDouble( var[var_I], ii, (ii*10 + var_I) );
			}
		}	

		/* Simple test */
		dof = DofLayout_New( "dofLayout", variableRegister, arraySize );
		for (ii = 0; ii < arraySize; ii++) {
			for (var_I = 0; var_I < 6; var_I++) {
				DofLayout_AddDof_ByVarName(dof, varName[var_I], ii);
			}
		}	
		Build(dof, 0, False);

		DofLayout_SaveAllVariablesToFiles( dof, "output/testDofSave", rank );

		DofLayout_SetAllToZero( dof );

		DofLayout_LoadAllVariablesFromFiles( dof, "output/testDofSave", rank );

		for (ii = 0; ii < arraySize; ii++) {
			printf("\tIndex %d - %2g,%2g,%2g,%2g,%2g,%2g\n", ii,
				DofLayout_GetValueDouble( dof, ii, 0 ),
				DofLayout_GetValueDouble( dof, ii, 1 ),
				DofLayout_GetValueDouble( dof, ii, 2 ),
				DofLayout_GetValueDouble( dof, ii, 3 ),
				DofLayout_GetValueDouble( dof, ii, 4 ),
				DofLayout_GetValueDouble( dof, ii, 5 ) );
		}	


		/* Cleanup */
		Stg_Class_Delete(dof);

		Stg_Class_Delete(variableRegister);
		for (var_I = 0; var_I < 6; var_I++) {
			if (var[var_I]) Stg_Class_Delete(var[var_I]);
			Memory_Free( varArrays[var_I] );
		}
	}
void VariableCondition_ApplyToIndexVariable(
		void*				variableCondition, 
		Index				localIndex, 
		VariableCondition_VariableIndex	varIndex,
		void*				context )
{
	VariableCondition*	self = (VariableCondition*)variableCondition;
	Variable_Index		globalVarIndex;
	Variable*		var;
	ConditionFunction*	cf;
	Index			index;
	
/*
 * NOTE: This algorithm here is RIDICULOUSLY slow. I've added a mapping
 *       to the class, that should help.

	for (index = 0; index < self->indexCount; index++)
		if (self->indexTbl[index] == localIndex)
			break;
*/

	if(!UIntMap_Map( self->mapping, localIndex, &index ))
	    return;
	
	globalVarIndex = self->vcTbl[index][varIndex].varIndex;
	var = self->variable_Register->_variable[globalVarIndex];
		
	switch (self->valueTbl[self->vcTbl[index][varIndex].valIndex].type)
	{
		case VC_ValueType_Double:
			Variable_SetValueDouble(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeDouble );
			break;
		
		case VC_ValueType_CFIndex:
			cf = self->conFunc_Register->_cf[self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeCFIndex];
			ConditionFunction_Apply( 
				cf, 
				localIndex, 
				globalVarIndex, 
				context, 
				Variable_GetStructPtr( var, self->indexTbl[index]) );
			break;
		
		case VC_ValueType_DoubleArray:
			Variable_SetValue(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeArray.array );
			break;
		
		case VC_ValueType_Int:
			Variable_SetValueInt(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeInt );
			break;
		
		case VC_ValueType_Short:
			Variable_SetValueShort(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeShort );
			break;
		
		case VC_ValueType_Char:
			Variable_SetValueChar(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typeChar );
			break;
		
		case VC_ValueType_Ptr:
			Variable_SetValuePointer(
				var, 
				self->indexTbl[index], 
				self->valueTbl[self->vcTbl[index][varIndex].valIndex].as.typePtr );
			break;
		
		default:
			assert(0);
			break;
	}
}
void VariableCondition_ApplyToIndex( void* variableCondition, Index localIndex, void* context ) {
	VariableCondition*		self = (VariableCondition*)variableCondition;
	Variable*			var;
	Variable_Index			varIndex;
	VariableCondition_ValueIndex	val_I;
	ConditionFunction*		cf;
	Index				index, i;
	Stream*				errorStr = Journal_Register( Error_Type, self->type );

	/* Ensure that the index provided (localIndex) has a condition attached to it */
	insist( UIntMap_Map( self->mapping, localIndex, &index ), == True );
	
	/* For each variable that has a condition at this index */
	for (i = 0; i < self->vcVarCountTbl[index]; i++)
	{
		varIndex = self->vcTbl[index][i].varIndex;
		assert( varIndex != (unsigned)-1 );
		
		var = self->variable_Register->_variable[varIndex];
		
		val_I = self->vcTbl[index][i].valIndex;
		assert( val_I != (unsigned)-1 );
		
		switch (self->valueTbl[val_I].type)
		{
			case VC_ValueType_Double:
				Journal_Firewall( var->dataTypeCounts[0] == 1, errorStr,
					"Error - in %s: while applying values for variable condition "
					"\"%s\", to index %d - asked to apply a scalar %s to Variable \"%s\" "
					"which has %d components. Specify a scalar Variable instead.\n",
					__func__, self->name, self->indexTbl[index], "double",
					var->name, var->dataTypeCounts[0] );
				Variable_SetValueDouble(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typeDouble );
				break;
			
			case VC_ValueType_DoubleArray:
				Variable_SetValue(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typeArray.array );
				break;
			
			case VC_ValueType_CFIndex:
				Journal_Firewall( self->valueTbl[val_I].as.typeCFIndex != (unsigned)-1, errorStr,
					"Error - in %s: trying to apply to index %d of variable \"%s\", which "
					"is supposed to be a condition function, but the cond. func. wasn't "
					"found in the c.f. register.\n", __func__, localIndex, var->name );
				cf = self->conFunc_Register->_cf[self->valueTbl[val_I].as.typeCFIndex];
				ConditionFunction_Apply(
					cf, 
					localIndex, 
					varIndex, 
					context, 
					Variable_GetStructPtr( var, self->indexTbl[index] ) );
				break;
			
			case VC_ValueType_Int:
				Journal_Firewall( var->dataTypeCounts[0] == 1, errorStr,
					"Error - in %s: while applying values for variable condition "
					"\"%s\", to index %d - asked to apply a scalar %s to Variable \"%s\" "
					"which has %d components. Specify a scalar Variable instead.\n",
					__func__, self->name, self->indexTbl[index], "int",
					var->name, var->dataTypeCounts[0] );
				Variable_SetValueInt(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typeInt );
				break;
			
			case VC_ValueType_Short:
				Journal_Firewall( var->dataTypeCounts[0] == 1, errorStr,
					"Error - in %s: while applying values for variable condition "
					"\"%s\", to index %d - asked to apply a scalar %s to Variable \"%s\" "
					"which has %d components. Specify a scalar Variable instead.\n",
					__func__, self->name, self->indexTbl[index], "short",
					var->name, var->dataTypeCounts[0] );
				Variable_SetValueShort(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typeShort );
				break;
			
			case VC_ValueType_Char:
				Journal_Firewall( var->dataTypeCounts[0] == 1, errorStr,
					"Error - in %s: while applying values for variable condition "
					"\"%s\", to index %d - asked to apply a scalar %s to Variable \"%s\" "
					"which has %d components. Specify a scalar Variable instead.\n",
					__func__, self->name, self->indexTbl[index], "char",
					var->name, var->dataTypeCounts[0] );
				Variable_SetValueChar(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typeChar );
				break;
			
			case VC_ValueType_Ptr:
				Variable_SetValuePointer(
					var, 
					self->indexTbl[index], 
					self->valueTbl[val_I].as.typePtr );
				break;
			
			default:
				assert(0);
				break;
		}
	}
}
void VariableSuite_TestVariable_Double( VariableSuiteData* data ) {
    typedef double Triple[3];

    double* array;
    Triple* structArray;
    Index length = 10;

    double testValues[] = { 123456789.0, 0.987654321 };
    Index testValueCount = 2;
    Index test_I;
    double testValue;

    Variable* var;
    Variable* vec;
    Variable* vecVar[3];

    int i, j;

    array = Memory_Alloc_Array( double, length, "test" );
    structArray = Memory_Alloc_Array( Triple, length, "test" );

    var = Variable_NewScalar( "Double-Scalar", NULL, Variable_DataType_Double, &length, NULL, (void**)&array, data->vr );
    vec = Variable_NewVector( "Double-Three", NULL, Variable_DataType_Double, 3, &length, NULL, (void**)&structArray, data->vr, "a", "b", "c" );

    vecVar[0] = Variable_Register_GetByName( data->vr, "a" );
    vecVar[1] = Variable_Register_GetByName( data->vr, "b" );
    vecVar[2] = Variable_Register_GetByName( data->vr, "c" );

    Variable_Register_BuildAll( data->vr );


    for ( test_I = 0; test_I < testValueCount; ++test_I ) {

        testValue = testValues[test_I];

        for ( i = 0; i < length; ++i ) {
            Variable_SetValueDouble( var, i, testValue );

            Variable_SetValueAtDouble( vec, i, 0, testValue );
            Variable_SetValueAtDouble( vec, i, 1, testValue );
            Variable_SetValueAtDouble( vec, i, 2, testValue );
        }

        /* "~~~Scalar~~~\n" */
        for ( i = 0; i < length; ++i ) {
            pcu_check_true( Variable_GetValueDouble( var, i ) == (double)(double)testValue );
            pcu_check_true( Variable_GetValueDoubleAsChar( var, i ) == (char)(double)testValue );
            pcu_check_true( Variable_GetValueDoubleAsShort( var, i ) == (short)(double)testValue );
            pcu_check_true( Variable_GetValueDoubleAsInt( var, i ) == (int)(double)testValue );
            pcu_check_true( Variable_GetValueDoubleAsFloat( var, i ) == (float)(double)testValue );
        }

        /*~~~Vector~~~*/
        for ( i = 0; i < length; ++i ) {
            pcu_check_true( Variable_GetValueAtDouble( vec, i, 0 ) == (double)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsChar( vec, i, 0 ) == (char)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsShort( vec, i, 0 ) == (short)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsInt( vec, i, 0 ) == (int)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsFloat( vec, i, 0 ) == (float)(double)testValue );
            pcu_check_true( Variable_GetPtrAtDouble( vec, i, 0 ) == &structArray[i][0] );

            pcu_check_true( Variable_GetValueAtDouble( vec, i, 1 ) == (double)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsChar( vec, i, 1 ) == (char)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsShort( vec, i, 1 ) == (short)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsInt( vec, i, 1 ) == (int)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsFloat( vec, i, 1 ) == (float)(double)testValue );
            pcu_check_true( Variable_GetPtrAtDouble( vec, i, 1 ) == &structArray[i][1] );

            pcu_check_true( Variable_GetValueAtDouble( vec, i, 2 ) == (double)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsChar( vec, i, 2 ) == (char)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsShort( vec, i, 2 ) == (short)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsInt( vec, i, 2 ) == (int)(double)testValue );
            pcu_check_true( Variable_GetValueAtDoubleAsFloat( vec, i, 2 ) == (float)(double)testValue );
            pcu_check_true( Variable_GetPtrAtDouble( vec, i, 2 ) == &structArray[i][2] );
        }

        /*~~~Vector: Sub-Variable~~~*/
        for ( i = 0; i < length; ++i ) {
            for ( j = 0; j < 3; ++j ) {
                pcu_check_true( Variable_GetStructPtr( vecVar[j], i ) == &structArray[i][j] );
            }
        }
    }
}