void DictionarySuite_TestMerge( DictionarySuiteData* data ) {
   Dictionary_Entry_Value*    testStruct2=NULL;
   Dictionary_Entry_Value*    testGeomStruct2=NULL;
   Dictionary_Entry_Value*    mergedStruct=NULL;
   Dictionary_Entry_Value*    expectedMergedStruct=NULL;

   testStruct2 = Dictionary_Entry_Value_NewStruct( );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"height", Dictionary_Entry_Value_FromDouble( data->testDD->testStruct->height )  );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"anisotropic", Dictionary_Entry_Value_FromBool( False )  );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"new_person", Dictionary_Entry_Value_FromString( "Luke" ) );
   testGeomStruct2 = Dictionary_Entry_Value_NewStruct( );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"geom", testGeomStruct2  );
   Dictionary_Entry_Value_AddMember( testGeomStruct2, (Dictionary_Entry_Key)"startx", Dictionary_Entry_Value_FromUnsignedInt( data->testDD->testStruct->geom.startx )  );
   Dictionary_Entry_Value_AddMember( testGeomStruct2, (Dictionary_Entry_Key)"startz", Dictionary_Entry_Value_FromUnsignedInt( 222 )  );

   /* Testing Merge_Append */
   DictionarySuite_PopulateDictWithTestValues( data->dict, data->testDD );
   /* Do a copy of the DEV during merge, since we don't want it being deleted */
   Dictionary_AddMerge( data->dict, "test_struct", Dictionary_Entry_Value_Copy( testStruct2, True ), Dictionary_MergeType_Append );
   /* OK: since this was an append, we expect _two_ entries called "test_struct",
    * one preceding the other, one with the orig data, one with new data */    
   pcu_check_true( (data->testDD->testEntriesCount+1) == data->dict->count );
   pcu_check_true( Dictionary_Entry_Value_Compare( data->testDD->testValues[8], Dictionary_Get( data->dict, (Dictionary_Entry_Key)"test_struct" ) )  );
   pcu_check_true( Dictionary_Entry_Value_Compare( testStruct2, data->dict->entryPtr[9]->value ) );
   Dictionary_Empty( data->dict );

   /* Testing Merge_Merge */
   DictionarySuite_PopulateDictWithTestValues( data->dict, data->testDD );

   /* The nicest way for this test I think is to manually build a merged struct
    *  to compare against */
   expectedMergedStruct = Dictionary_Entry_Value_Copy( data->testDD->testValues[8], True );
   Dictionary_Set( expectedMergedStruct->as.typeStruct, (Dictionary_Entry_Key)"anisotropic", Dictionary_Entry_Value_FromBool( False )  );
   Dictionary_Add( expectedMergedStruct->as.typeStruct, (Dictionary_Entry_Key)"new_person", Dictionary_Entry_Value_FromString( "Luke" )  );
   Dictionary_Set( (Dictionary_Get( expectedMergedStruct->as.typeStruct, (Dictionary_Entry_Key)"geom" ) )->as.typeStruct, "startz", Dictionary_Entry_Value_FromUnsignedInt( 222 ) );

   Dictionary_AddMerge( data->dict, "test_struct", Dictionary_Entry_Value_Copy( testStruct2, True ), Dictionary_MergeType_Merge );
   /* This time, the new struct should be merged into the existing one */
   pcu_check_true( data->testDD->testEntriesCount == data->dict->count );
   mergedStruct = Dictionary_Get( data->dict, (Dictionary_Entry_Key)"test_struct"  );
   pcu_check_true( Dictionary_Entry_Value_Compare( mergedStruct, expectedMergedStruct ) );
   Dictionary_Empty( data->dict );
   Dictionary_Entry_Value_Delete( expectedMergedStruct );

   /* Testing Merge_Replace */
   DictionarySuite_PopulateDictWithTestValues( data->dict, data->testDD );
   Dictionary_AddMerge( data->dict, "test_struct", Dictionary_Entry_Value_Copy( testStruct2, True ), Dictionary_MergeType_Replace );
   pcu_check_true( data->testDD->testEntriesCount == data->dict->count );
   pcu_check_true( Dictionary_Entry_Value_Compare( testStruct2, Dictionary_Get( data->dict, (Dictionary_Entry_Key)"test_struct" ) ) );
   Dictionary_Empty( data->dict );

   Dictionary_Entry_Value_Delete( testStruct2 );
}
void Dictionary_Entry_Value_AddElementWithSource( Dictionary_Entry_Value* self, Dictionary_Entry_Value* element,
							Dictionary_Entry_Source source )
{
	/* check type - convert to a list if not so... */
	if (Dictionary_Entry_Value_Type_List != self->type) {
		Dictionary_Entry_Value* copy;
		
		switch (self->type) {
			case Dictionary_Entry_Value_Type_String:
				copy = Dictionary_Entry_Value_FromString( self->as.typeString );
				break;
			case Dictionary_Entry_Value_Type_Double:
				copy = Dictionary_Entry_Value_FromDouble( self->as.typeDouble );
				break;
			case Dictionary_Entry_Value_Type_UnsignedInt:
				copy = Dictionary_Entry_Value_FromUnsignedInt( self->as.typeUnsignedInt );
				break;
			case Dictionary_Entry_Value_Type_Int:
				copy = Dictionary_Entry_Value_FromInt( self->as.typeInt );
				break;
			case Dictionary_Entry_Value_Type_UnsignedLong:
				copy = Dictionary_Entry_Value_FromUnsignedLong( self->as.typeUnsignedLong );
				break;
			case Dictionary_Entry_Value_Type_Bool:
				copy = Dictionary_Entry_Value_FromBool( self->as.typeBool );
				break;
			case Dictionary_Entry_Value_Type_Struct:
				copy = Dictionary_Entry_Value_NewStruct();
				copy->as.typeStruct = self->as.typeStruct;
				break;
			default: {
				Stream* errorStream = Journal_Register( Error_Type, "Dictionary_Entry_Value" );
				Journal_Firewall( False, errorStream, "In func %s: self->type '%d' is invalid.\n", __func__, self->type );
			}
		}
		
		Dictionary_Entry_Value_SetNewList( self );	
		Dictionary_Entry_Value_AddElementWithSource( self, copy, source );
	}
	
	if (!self->as.typeList->first) {
		self->as.typeList->first = element;
	} else {
		self->as.typeList->last->next = element;
	}
	self->as.typeList->last = element;
	self->as.typeList->count++;
}
void DictionarySuite_TestReadAllParamFromCommandLine( DictionarySuiteData* data  ) {
   int                        argc;
   char**                     argv;
   char**                     expectedKeys;
   Dictionary_Entry_Value**   expectedVals;
   Index                      ii;
   Dictionary_Entry_Value*    tmpStruct=NULL;
   Dictionary_Entry_Value*    tmpStruct2=NULL;
   Dictionary_Entry_Value*    tmpList=NULL;
   Index                      numExp = 7;

   argc = 16;
   argv = Memory_Alloc_Array_Unnamed( char*, argc );
   expectedVals = Memory_Alloc_Array_Unnamed( Dictionary_Entry_Value*, numExp );
   expectedKeys = Memory_Alloc_Array_Unnamed( char*, numExp );

   /* Now fill in our mock command line, and create the expected values to test
    *  against along the way */   
   Stg_asprintf( &argv[0], "./testStGermain");
   Stg_asprintf( &argv[1], "-param=hey");
   Stg_asprintf( &argv[2], "--option");
   Stg_asprintf( &argv[3], "--output-dir=");
   Stg_asprintf( &expectedKeys[0], "output-dir" );

   expectedVals[0] = Dictionary_Entry_Value_FromString( "" );
   Stg_asprintf( &argv[4], "--Ra=1.0e4");
   Stg_asprintf( &expectedKeys[1], "Ra" );

   expectedVals[1] = Dictionary_Entry_Value_FromDouble( 1.0e4 );
   Stg_asprintf( &argv[5], "--foo.bar=5");
   Stg_asprintf( &expectedKeys[2], "foo" );

   expectedVals[2] = Dictionary_Entry_Value_NewStruct();
   Dictionary_Entry_Value_AddMember( expectedVals[2], (Dictionary_Entry_Key)"bar", Dictionary_Entry_Value_FromDouble( 5 )  );
   Stg_asprintf( &expectedKeys[3], "vpac" );

   expectedVals[3] = Dictionary_Entry_Value_NewStruct();
   Dictionary_Entry_Value_AddMember( expectedVals[3], (Dictionary_Entry_Key)"csd", tmpStruct = Dictionary_Entry_Value_NewStruct()  );
     Stg_asprintf( &argv[7], "--foo.bot=7");
   Dictionary_Entry_Value_AddMember( expectedVals[2], (Dictionary_Entry_Key)"bot", Dictionary_Entry_Value_FromDouble( 7 )  );
   Stg_asprintf( &argv[8], "--sports[]=hockey");
   Stg_asprintf( &expectedKeys[4], "sports" );

   expectedVals[4] = Dictionary_Entry_Value_NewList();
   Dictionary_Entry_Value_AddElement( expectedVals[4], Dictionary_Entry_Value_FromString( "hockey" ) );
   Stg_asprintf( &argv[9], "--sports[]=chess");
   /* This should be overwritten by next entry, so ignore */
   Stg_asprintf( &argv[10], "--sports[1]=tennis");
   Dictionary_Entry_Value_AddElement( expectedVals[4], Dictionary_Entry_Value_FromString( "tennis" ) );
   Stg_asprintf( &argv[11], "--sles[].name=pressure");
   Stg_asprintf( &expectedKeys[5], "sles" );

   expectedVals[5] = Dictionary_Entry_Value_NewList();
   Dictionary_Entry_Value_AddElement( expectedVals[5], tmpStruct = Dictionary_Entry_Value_NewStruct() );
   Dictionary_Entry_Value_AddMember( tmpStruct, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "pressure" )  );
   Stg_asprintf( &argv[12], "--sles[].name=temperature");
   Dictionary_Entry_Value_AddElement( expectedVals[5], tmpStruct2 = Dictionary_Entry_Value_NewStruct() );
   Dictionary_Entry_Value_AddMember( tmpStruct2, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "temperature" )  );
   Stg_asprintf( &argv[13], "--sles[0].solver=mg");
   Dictionary_Entry_Value_AddMember( tmpStruct, (Dictionary_Entry_Key)"solver", Dictionary_Entry_Value_FromString( "mg" )  );
   Stg_asprintf( &argv[14], "--sles[1].solver=direct");
   Dictionary_Entry_Value_AddMember( tmpStruct2, (Dictionary_Entry_Key)"solver", Dictionary_Entry_Value_FromString( "direct" )  );
   Stg_asprintf( &argv[15], "--some.crazy[].shit=here");
   Stg_asprintf( &expectedKeys[6], "some" );

   expectedVals[6] = Dictionary_Entry_Value_NewStruct();
   Dictionary_Entry_Value_AddMember( expectedVals[6], (Dictionary_Entry_Key)"crazy", tmpList = Dictionary_Entry_Value_NewList()  );
   Dictionary_Entry_Value_AddElement( tmpList, tmpStruct = Dictionary_Entry_Value_NewStruct() );
   Dictionary_Entry_Value_AddMember( tmpStruct, (Dictionary_Entry_Key)"shit", Dictionary_Entry_Value_FromString( "here" )  );

   Dictionary_ReadAllParamFromCommandLine( data->dict, argc, argv );

   for (ii=0; ii < numExp; ii++) {
      pcu_check_true( Dictionary_Entry_Compare( data->dict->entryPtr[ii], expectedKeys[ii]));
      pcu_check_true( Dictionary_Entry_Value_Compare( expectedVals[ii], data->dict->entryPtr[ii]->value ));
   }

   for (ii=0; ii < argc; ii++) {
      Memory_Free( argv[ii] );
   }
   Memory_Free( argv );

   for (ii=0; ii < numExp; ii++) {
      Memory_Free( expectedKeys[ii] );
      Memory_Free( expectedVals[ii] );
   }
   Memory_Free( expectedKeys );
   Memory_Free( expectedVals );
}
void DictionarySuite_SetupTestDictData( DictionarySuite_TestDictData* testDD ) {
   Index                   ii=0;
   Index                   iter=0;
   Dictionary_Entry_Value* testStruct; 
   Dictionary_Entry_Value* testStruct2; 
   Dictionary_Entry_Value* testList; 

   testDD->testEntriesCount = 9;
   testDD->testKeys = Memory_Alloc_Array_Unnamed( char*, testDD->testEntriesCount );
   testDD->testValues = Memory_Alloc_Array_Unnamed( Dictionary_Entry_Value*,
      testDD->testEntriesCount );

   for ( ii=0; ii< testDD->testEntriesCount; ii++ ) {
      testDD->testKeys[ii] = NULL;
      testDD->testValues[ii] = NULL;
   }

   Stg_asprintf( &testDD->testString, "hello" );
   Stg_asprintf( &testDD->testPlaceHolder, "test_double" );
   testDD->testDouble=45.567;
   testDD->testUint = 5;
   testDD->testInt = -5;
   testDD->testUnsignedlong = 52342423;
   testDD->testBool = True;
   iter = 0;
   Stg_asprintf( &testDD->testKeys[iter], "test_cstring" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromString( testDD->testString );
   Stg_asprintf( &testDD->testKeys[++iter], "test_double" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromDouble( testDD->testDouble );
   Stg_asprintf( &testDD->testKeys[++iter], "test_uint" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromUnsignedInt( testDD->testUint );
   Stg_asprintf( &testDD->testKeys[++iter], "test_int" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromInt( testDD->testInt );
   Stg_asprintf( &testDD->testKeys[++iter], "test_unsignedlong" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromUnsignedLong( testDD->testUnsignedlong );
   Stg_asprintf( &testDD->testKeys[++iter], "test_bool" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromUnsignedInt( testDD->testBool );
   Stg_asprintf( &testDD->testKeys[++iter], "test_placeholder" );
   testDD->testValues[iter] = Dictionary_Entry_Value_FromString( testDD->testPlaceHolder );

   /* adding a list */
   testDD->testListCount = 5;
   testDD->testList = Memory_Alloc_Array_Unnamed( double, testDD->testListCount );
   for (ii=0; ii<testDD->testListCount; ii++ ) {
      testDD->testList[ii] = 10.0 * ii;
   }

   testList = Dictionary_Entry_Value_NewList();
   Stg_asprintf( &testDD->testKeys[++iter], "test_list" );
   testDD->testValues[iter] = testList;
   for (ii=0; ii < testDD->testListCount; ii++ ) {
      Dictionary_Entry_Value_AddElement( testList, Dictionary_Entry_Value_FromDouble(testDD->testList[ii]) );
   }

   /* Adding members to a struct */
   testDD->testStruct = Memory_Alloc_Unnamed( TestStruct );
   testDD->testStruct->height = 37;
   testDD->testStruct->anisotropic = True;
   Stg_asprintf( &testDD->testStruct->person, "Patrick" );
   testDD->testStruct->geom.startx = 45;
   testDD->testStruct->geom.starty = 60;
   testDD->testStruct->geom.startz = 70;

   testStruct = Dictionary_Entry_Value_NewStruct();
   Stg_asprintf( &testDD->testKeys[++iter], "test_struct" );
   testDD->testValues[iter] = testStruct;
   Dictionary_Entry_Value_AddMember( testStruct, (Dictionary_Entry_Key)"height", Dictionary_Entry_Value_FromDouble( testDD->testStruct->height )  );
   Dictionary_Entry_Value_AddMember( testStruct, (Dictionary_Entry_Key)"anisotropic", Dictionary_Entry_Value_FromBool( testDD->testStruct->anisotropic )  );
   Dictionary_Entry_Value_AddMember( testStruct, (Dictionary_Entry_Key)"person", Dictionary_Entry_Value_FromString( testDD->testStruct->person ) );

   /* Adding a 2nd struct within the first struct */
   testStruct2 = Dictionary_Entry_Value_NewStruct( );
   Dictionary_Entry_Value_AddMember( testStruct, (Dictionary_Entry_Key)"geom", testStruct2  );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"startx", Dictionary_Entry_Value_FromUnsignedInt( testDD->testStruct->geom.startx )  );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"starty", Dictionary_Entry_Value_FromUnsignedInt( testDD->testStruct->geom.starty )  );
   Dictionary_Entry_Value_AddMember( testStruct2, (Dictionary_Entry_Key)"startz", Dictionary_Entry_Value_FromUnsignedInt( testDD->testStruct->geom.startz ) );
}
int main( int argc, char* argv[] ) {
    MPI_Comm			CommWorld;
    int				rank;
    int				numProcessors;
    int				procToWatch;
    Dictionary*			dictionary;
    Snac_Context*			snacContext;
    Element_LocalIndex		elementIndex;
    Node_LocalIndex		nodeIndex;
    double				minLengthScale;
    double				speedOfSound;
    Mass				mass;
    Mass				inertialMass;
    Force				force;
    Force				balance;
    Stream*				stream;

    Dictionary_Entry_Value* nodeICs;
    Dictionary_Entry_Value* vcList;
    Dictionary_Entry_Value* varStruct;
    Dictionary_Entry_Value* eachVarList;
    Dictionary_Entry_Value* vxStruct;
    Dictionary_Entry_Value* vyStruct;
    Dictionary_Entry_Value* vzStruct;

    /* Initialise MPI, get world info */
    MPI_Init( &argc, &argv );
    Snac_Init( &argc, &argv );
    MPI_Comm_dup( MPI_COMM_WORLD, &CommWorld );
    MPI_Comm_size( CommWorld, &numProcessors );
    MPI_Comm_rank( CommWorld, &rank );

    stream = Journal_Register (Info_Type, "myStream");

    if( argc >= 2 ) {
        procToWatch = atoi( argv[1] );
    }
    else {
        procToWatch = 0;
    }
    if( rank == procToWatch ) printf( "Watching rank: %i\n", rank );

    /* Read input */
    dictionary = Dictionary_New();
    dictionary->add( dictionary, "rank", Dictionary_Entry_Value_FromUnsignedInt( rank ) );
    dictionary->add( dictionary, "numProcessors", Dictionary_Entry_Value_FromUnsignedInt( numProcessors ) );
    dictionary->add( dictionary, "meshSizeI", Dictionary_Entry_Value_FromUnsignedInt( 4 ) );
    dictionary->add( dictionary, "meshSizeJ", Dictionary_Entry_Value_FromUnsignedInt( 4 ) );
    dictionary->add( dictionary, "meshSizeK", Dictionary_Entry_Value_FromUnsignedInt( 4 ) );
    dictionary->add( dictionary, "minX", Dictionary_Entry_Value_FromDouble( 0.0f ) );
    dictionary->add( dictionary, "minY", Dictionary_Entry_Value_FromDouble( -300.0f ) );
    dictionary->add( dictionary, "minZ", Dictionary_Entry_Value_FromDouble( 0.0f ) );
    dictionary->add( dictionary, "maxX", Dictionary_Entry_Value_FromDouble( 300.0f ) );
    dictionary->add( dictionary, "maxY", Dictionary_Entry_Value_FromDouble( 0.0f ) );
    dictionary->add( dictionary, "maxZ", Dictionary_Entry_Value_FromDouble( 300.0f ) );

    nodeICs = Dictionary_Entry_Value_NewStruct();
    vcList = Dictionary_Entry_Value_NewList();
    varStruct = Dictionary_Entry_Value_NewStruct();
    eachVarList = Dictionary_Entry_Value_NewList();
    vxStruct = Dictionary_Entry_Value_NewStruct();
    vyStruct = Dictionary_Entry_Value_NewStruct();
    vzStruct = Dictionary_Entry_Value_NewStruct();
    Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vx" ) );
    Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
    Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 3.0e-10f ) );
    Dictionary_Entry_Value_AddMember( vyStruct, "name", Dictionary_Entry_Value_FromString( "vy" ) );
    Dictionary_Entry_Value_AddMember( vyStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
    Dictionary_Entry_Value_AddMember( vyStruct, "value", Dictionary_Entry_Value_FromDouble( 3.0e-10f ) );
    Dictionary_Entry_Value_AddMember( vzStruct, "name", Dictionary_Entry_Value_FromString( "vz" ) );
    Dictionary_Entry_Value_AddMember( vzStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
    Dictionary_Entry_Value_AddMember( vzStruct, "value", Dictionary_Entry_Value_FromDouble( 6.0e-10f ) );
    Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
    Dictionary_Entry_Value_AddElement( eachVarList, vyStruct );
    Dictionary_Entry_Value_AddElement( eachVarList, vzStruct );
    Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "AllNodesVC" ) );
    Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
    Dictionary_Entry_Value_AddElement( vcList, varStruct );
    Dictionary_Entry_Value_AddMember( nodeICs, "vcList", vcList );
    Dictionary_Add( dictionary, "nodeICs", nodeICs );

    /* Build the context */
    snacContext = Snac_Context_New( 0.0f, 10.0f, sizeof(Snac_Node), sizeof(Snac_Element), CommWorld, dictionary );

    /* Construction phase -----------------------------------------------------------------------------------------------*/
    Stg_Component_Construct( snacContext, 0 /* dummy */, &snacContext, True );

    /* Building phase ---------------------------------------------------------------------------------------------------*/
    Stg_Component_Build( snacContext, 0 /* dummy */, False );

    /* Initialisaton phase ----------------------------------------------------------------------------------------------*/
    Stg_Component_Initialise( snacContext, 0 /* dummy */, False );

    /* Work out the first element's tetrahedra values, and print them. */
    printf( "Element: 0, Coords: (%g %g %g), (%g %g %g), (%g %g %g), (%g %g %g), (%g %g %g) (%g %g %g) (%g %g %g) (%g %g %g)\n",
            Snac_Element_NodeCoord( snacContext, 0, 0 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 0 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 0 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 1 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 1 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 1 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 3 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 3 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 3 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 2 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 2 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 2 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 4 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 4 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 4 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 5 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 5 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 5 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 7 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 7 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 7 )[2],
            Snac_Element_NodeCoord( snacContext, 0, 6 )[0],
            Snac_Element_NodeCoord( snacContext, 0, 6 )[1],
            Snac_Element_NodeCoord( snacContext, 0, 6 )[2] );
    printf( "Element: 0, Vel: (%g %g %g), (%g %g %g), (%g %g %g), (%g %g %g), (%g %g %g) (%g %g %g) (%g %g %g) (%g %g %g)\n",
            Snac_Element_Node_P( snacContext, 0, 0 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 0 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 0 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 1 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 1 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 1 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 3 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 3 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 3 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 2 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 2 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 2 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 4 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 4 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 4 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 5 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 5 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 5 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 7 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 7 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 7 )->velocity[2],
            Snac_Element_Node_P( snacContext, 0, 6 )->velocity[0],
            Snac_Element_Node_P( snacContext, 0, 6 )->velocity[1],
            Snac_Element_Node_P( snacContext, 0, 6 )->velocity[2] );
    /*	Snac_Material_Print( &snacContext->materialProperty[Snac_Element_At( snacContext, 0 )->material_I], stream ); */


    /* Update all the elements, and in the process work out this processor's minLengthScale */
    elementIndex = 0;
    Snac_UpdateElementMomentum( (Context*)snacContext, elementIndex, &minLengthScale );
    for( elementIndex = 1; elementIndex < snacContext->mesh->elementLocalCount; elementIndex++ ) {
        double elementMinLengthScale;

        Snac_UpdateElementMomentum( (Context*)snacContext, elementIndex, &elementMinLengthScale );

        if( elementMinLengthScale < minLengthScale ) {
            minLengthScale = elementMinLengthScale;
        }
    }

    /* Find the global minLengthScale, and then calculate the new dt and speed of sound, assuming frac=0.5,
     * strain_inert=1.0e-5f & vbc_max=3.0e-10f */
    {
        double localMinLengthScale = minLengthScale;

        MPI_Allreduce( &localMinLengthScale, &minLengthScale, 1, MPI_DOUBLE, MPI_MIN, CommWorld );

        snacContext->dt = minLengthScale * 0.5f * 1.0e-5f / 3.0e-10f;
        speedOfSound = minLengthScale * 0.5f / snacContext->dt;
    }
    printf( "Global minLengthScale: %g\n", minLengthScale );
    printf( "Dt: %g\n", snacContext->dt );
    printf( "Speed of sound: %g\n", speedOfSound );


    /* For each element, calculate strain-rate and then stress */
    for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex++ ) {
        Snac_StrainRate( (Context*)snacContext, elementIndex );
        SnacTest_Stress( (Context*)snacContext, elementIndex );
    }


    /* For each node, calculate the mass, force, veloity and coordinates */
    for( nodeIndex = 0; nodeIndex < snacContext->mesh->nodeLocalCount; nodeIndex++ ) {
        Snac_Force( (Context*)snacContext, nodeIndex, speedOfSound, &mass, &inertialMass, &force, &balance );
        Snac_UpdateNodeMomentum( (Context*)snacContext, nodeIndex, inertialMass, force );
    }


    /* For each element... just print out the info... too complicated to work out which ones have the same value */
    for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex++ ) {
        double 			elementMinLengthScale;
        Tetrahedra_Index	tetra_I;

        Snac_UpdateElementMomentum( (Context*)snacContext, elementIndex, &elementMinLengthScale );
        for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) {
            printf( "Element: %u, tetrahedra: %u, strain: (%g %g %g) (%g %g %g)\n", elementIndex, tetra_I,
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[0][0],
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[1][1],
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[2][2],
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[0][1],
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[0][2],
                    Snac_Element_At( snacContext, elementIndex )->tetra[tetra_I].strain[1][2] );
        }
    }


    /* Stg_Class_Delete stuff */
    Stg_Class_Delete( snacContext );
    Stg_Class_Delete( dictionary );

    /* Close off MPI */
    MPI_Finalize();

    return 0; /* success */
}
int main( int argc, char* argv[] ) {
	MPI_Comm			CommWorld;
	int				rank;
	int				numProcessors;
	int				procToWatch;
	Dictionary*			dictionary;
	Snac_Context*			snacContext;
	Element_LocalIndex		elementIndex;
	Node_LocalIndex		nodeIndex;
	double				minLengthScale;
	double				speedOfSound;
	Mass				mass;
	Mass				inertialMass;
	Force				force;
	Snac_Node*          node;
	Force				balance;
	Stream*				stream;
	Index elementNode_lI;
	Coord *coord;
	Index timeStep;

	Dictionary_Entry_Value* pluginsList;
	Dictionary_Entry_Value* velocityBCs;
	Dictionary_Entry_Value* vcList;
	Dictionary_Entry_Value* varStruct;
	Dictionary_Entry_Value* eachVarList;
	Dictionary_Entry_Value* vxStruct;

	/* Initialise MPI, get world info */
	MPI_Init( &argc, &argv );
	Snac_Init( &argc, &argv );
	MPI_Comm_dup( MPI_COMM_WORLD, &CommWorld );
	MPI_Comm_size( CommWorld, &numProcessors );
	MPI_Comm_rank( CommWorld, &rank );

	stream = Journal_Register (InfoStream_Type, "myStream");

	if( argc >= 2 ) {
		procToWatch = atoi( argv[1] );
	}
	else {
		procToWatch = 0;
	}
	if( rank == procToWatch ) printf( "Watching rank: %i\n", rank );

	/* Read input */
	dictionary = Dictionary_New();
	dictionary->add( dictionary, "rank", Dictionary_Entry_Value_FromUnsignedInt( rank ) );
	dictionary->add( dictionary, "numProcessors", Dictionary_Entry_Value_FromUnsignedInt( numProcessors ) );
	dictionary->add( dictionary, "meshSizeI", Dictionary_Entry_Value_FromUnsignedInt( 3 ) );
	dictionary->add( dictionary, "meshSizeJ", Dictionary_Entry_Value_FromUnsignedInt( 3 ) );
	dictionary->add( dictionary, "meshSizeK", Dictionary_Entry_Value_FromUnsignedInt( 3 ) );
	dictionary->add( dictionary, "minX", Dictionary_Entry_Value_FromDouble( 0.0f ) );
	dictionary->add( dictionary, "minY", Dictionary_Entry_Value_FromDouble( -1.0f ) );
	dictionary->add( dictionary, "minZ", Dictionary_Entry_Value_FromDouble( 0.0f ) );
	dictionary->add( dictionary, "maxX", Dictionary_Entry_Value_FromDouble( 1.0f ) );
	dictionary->add( dictionary, "maxY", Dictionary_Entry_Value_FromDouble( 0.0f ) );
	dictionary->add( dictionary, "maxZ", Dictionary_Entry_Value_FromDouble( 1.0f ) );
	dictionary->add( dictionary, "gravity", Dictionary_Entry_Value_FromDouble( 0 ) );
	dictionary->add( dictionary, "dtType", Dictionary_Entry_Value_FromString( "constant" ) );
	dictionary->add( dictionary, "timeStep", Dictionary_Entry_Value_FromDouble( 1.0 ) );
	dictionary->add( dictionary, "topo_kappa", Dictionary_Entry_Value_FromDouble( 0 ) );
	dictionary->add( dictionary, "alpha", Dictionary_Entry_Value_FromDouble( 0 ) );
	dictionary->add( dictionary, "forceCalcType", Dictionary_Entry_Value_FromString( "complete" ) );

	pluginsList = Dictionary_Entry_Value_NewList();
	Dictionary_Add( dictionary, "plugins", pluginsList );
	
	velocityBCs = Dictionary_Entry_Value_NewStruct();
	vcList = Dictionary_Entry_Value_NewList();
	/* left wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vx" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.0 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "left" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* right wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vx" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.01 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "right" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* back wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vz" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.0 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "back" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* front wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vz" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.0 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "front" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* bottom wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vy" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.0 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "bottom" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* top wall */
	varStruct = Dictionary_Entry_Value_NewStruct();
	eachVarList = Dictionary_Entry_Value_NewList();
	vxStruct = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( vxStruct, "name", Dictionary_Entry_Value_FromString( "vy" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "type", Dictionary_Entry_Value_FromString( "double" ) );
	Dictionary_Entry_Value_AddMember( vxStruct, "value", Dictionary_Entry_Value_FromDouble( 0.0 ) );
	Dictionary_Entry_Value_AddElement( eachVarList, vxStruct );
	Dictionary_Entry_Value_AddMember( varStruct, "type", Dictionary_Entry_Value_FromString( "WallVC" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "wall", Dictionary_Entry_Value_FromString( "top" ) );
	Dictionary_Entry_Value_AddMember( varStruct, "variables", eachVarList );
	Dictionary_Entry_Value_AddElement( vcList, varStruct );
	/* add to dictionary */
	Dictionary_Entry_Value_AddMember( velocityBCs, "vcList", vcList );
	Dictionary_Add( dictionary, "velocityBCs", velocityBCs );

	/* Build the context */
	snacContext = Snac_Context_New( 0.0f, 10.0f, sizeof(Snac_Node), sizeof(Snac_Element), CommWorld, dictionary );

	/* Construction phase -----------------------------------------------------------------------------------------------*/
	Stg_Component_Construct( snacContext, 0 /* dummy */, &snacContext, True );
	
	/* Building phase ---------------------------------------------------------------------------------------------------*/
	Stg_Component_Build( snacContext, 0 /* dummy */, False );
	
	/* Initialisaton phase ----------------------------------------------------------------------------------------------*/
	Stg_Component_Initialise( snacContext, 0 /* dummy */, False );

	/* Check the coordinates of the nodes. */
	for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex ++ ) {
		printf( "Element: %u, Coords: ", elementIndex );
		for( elementNode_lI = 0; elementNode_lI < 8; elementNode_lI++ ) {
			printf( "(%g %g %g) ",
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[0],
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[1],
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[2] );
		}
		printf( "\n" );
	}

	/* Check the velocity field. */
	for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex ++ ) {
		printf( "Element: %u, Vel: ",elementIndex );
		for( elementNode_lI = 0; elementNode_lI < 8; elementNode_lI++ ) {
			printf( "(%g %g %g) ",
					Snac_Element_Node_P( snacContext, elementIndex, elementNode_lI )->velocity[0],
					Snac_Element_Node_P( snacContext, elementIndex, elementNode_lI )->velocity[1],
					Snac_Element_Node_P( snacContext, elementIndex, elementNode_lI )->velocity[2] );
		}
		printf( "\n" );
	}

	/* Check the coordinates of the nodes. */
	for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex ++ ) {
		printf( "Element: %u, Coords: ", elementIndex );
		for( elementNode_lI = 0; elementNode_lI < 8; elementNode_lI++ ) {
			printf( "(%g %g %g) ",
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[0],
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[1],
					Snac_Element_NodeCoord( snacContext, elementIndex, elementNode_lI )[2] );
		}
		printf( "\n" );
	}

	/* Loop until the static solution is reached. */
	timeStep = 0;
	while( timeStep < 10 ) {
		for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex++ ) {
			double elementMinLengthScale;

			Snac_UpdateElementMomentum( snacContext, elementIndex, &elementMinLengthScale );

			if( elementMinLengthScale < minLengthScale ) {
				minLengthScale = elementMinLengthScale;
			}
		}

		/* Find the global minLengthScale, and then calculate the new dt and speed of sound, assuming frac=0.5,
		 * strain_inert=1.0e-5f & vbc_max=3.0e-10f */
		{
			double localMinLengthScale = minLengthScale;

			MPI_Allreduce( &localMinLengthScale, &minLengthScale, 1, MPI_DOUBLE, MPI_MIN, CommWorld );

			//snacContext->dt = minLengthScale * 0.5f * 1.0e-5f / 3.0e-10f;
			speedOfSound = minLengthScale * 0.5f / snacContext->dt;
		}

		/* For each element, calculate strain-rate and then stress */
		for( elementIndex = 0; elementIndex < snacContext->mesh->elementLocalCount; elementIndex++ ) {
			Snac_StrainRate( (Context*)snacContext, elementIndex );
			SnacTest_Stress( (Context*)snacContext, elementIndex );
		}

		for( nodeIndex = 0; nodeIndex < snacContext->mesh->nodeLocalCount; nodeIndex++ ) {
			node = Snac_Node_At( snacContext, nodeIndex );
			Snac_Force( snacContext, nodeIndex, speedOfSound, &mass, &inertialMass, &force, &balance );
			Snac_UpdateNodeMomentum_PreProcess( snacContext, nodeIndex, inertialMass, force );
			Snac_UpdateNodeMomentum( snacContext, nodeIndex, inertialMass, force );
		}
		timeStep++;
	}
	/* Check coordinates. */
	for( nodeIndex = 0; nodeIndex < snacContext->mesh->nodeLocalCount; nodeIndex++ ) {
		coord = Snac_NodeCoord_P( snacContext, nodeIndex );

		printf( "Node %u : coord = %g %g %g\n", nodeIndex, (*coord)[0],(*coord)[1],(*coord)[2]);
	}

	/* Stg_Class_Delete stuff */
	Stg_Class_Delete( snacContext );
	Stg_Class_Delete( dictionary );

	/* Close off MPI */
	MPI_Finalize();

	return 0; /* success */
}
int main( int argc, char* argv[] ) {
	
	Stream*				stream = NULL;
	Dictionary*			dictionary;
	Dictionary_Entry_Value*		tmpVal0;
	Dictionary_Entry_Value*		tmpVal1; 
	
	MPI_Init( &argc, &argv );
	BaseFoundation_Init( &argc, &argv );
	BaseIO_Init( &argc, &argv );
	stream = Journal_Register (Info_Type, "myStream");

	dictionary = Dictionary_New();

	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "name", Dictionary_Entry_Value_FromString( "bill" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 1.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "bottom" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "top" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_Add( dictionary, "one", tmpVal0 );
	
	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "new_name", Dictionary_Entry_Value_FromString( "frank" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 2.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "left" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "right" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_AddMerge( dictionary, "one", tmpVal0, Dictionary_MergeType_Append );
	
	Print( dictionary, stream );
	Stg_Class_Delete( dictionary );
	
	dictionary = Dictionary_New();
	
	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "name", Dictionary_Entry_Value_FromString( "bill" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 1.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "bottom" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "top" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_Add( dictionary, "one", tmpVal0 );
	
	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "new_name", Dictionary_Entry_Value_FromString( "frank" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 2.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "left" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "right" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_AddMerge( dictionary, "one", tmpVal0, Dictionary_MergeType_Merge );
	
	Print( dictionary, stream );
	Stg_Class_Delete( dictionary );
	
	dictionary = Dictionary_New();
	
	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "name", Dictionary_Entry_Value_FromString( "bill" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 1.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "bottom" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "top" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_Add( dictionary, "one", tmpVal0 );
	
	tmpVal0 = Dictionary_Entry_Value_NewStruct();
	tmpVal1 = Dictionary_Entry_Value_NewStruct();
	Dictionary_Entry_Value_AddMember( tmpVal1, "new_name", Dictionary_Entry_Value_FromString( "frank" ) );
	Dictionary_Entry_Value_AddMember( tmpVal1, "value", Dictionary_Entry_Value_FromDouble( 2.0f ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "inside", tmpVal1 );
	tmpVal1 = Dictionary_Entry_Value_NewList();
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "left" ) );
	Dictionary_Entry_Value_AddElement( tmpVal1, Dictionary_Entry_Value_FromString( "right" ) );
	Dictionary_Entry_Value_AddMember( tmpVal0, "list_one", tmpVal1 );
	Dictionary_AddMerge( dictionary, "one", tmpVal0, Dictionary_MergeType_Replace );
	
	Print( dictionary, stream );
	Stg_Class_Delete( dictionary );
	
	BaseIO_Finalise();
	BaseFoundation_Finalise();
	MPI_Finalize();
	
	return EXIT_SUCCESS;
}