char* _Stg_ComponentFactory_GetString( void* cf, Name componentName, Dictionary_Entry_Key key, const char* const defaultVal ) {
   return Dictionary_Entry_Value_AsString( 
         _Stg_ComponentFactory_GetDictionaryValue( cf, componentName, key, 
            Dictionary_Entry_Value_FromString( defaultVal ) ) );
}
char* Stg_ComponentFactory_PluginGetString( void* cf, void* codelet, Dictionary_Entry_Key key, const char* const defaultVal ) {
   return Dictionary_Entry_Value_AsString( 
            _Stg_ComponentFactory_PluginGetDictionaryValue( cf, codelet, key,
                                                            Dictionary_Entry_Value_FromString( defaultVal ) ) );
}
void stgGenerateFlattenedXML( Dictionary* dictionary, Dictionary* sources, char* timeStamp ) {
   XML_IO_Handler* ioHandler;
   char*           outputPath;
   char*           flatFilename;
   char*           flatFilenameStamped;
   char*           slimFilename;
   Stream*         s;
   Bool            isEnabled;
   Bool            ret;
   Bool            outputSlim;

   s = Journal_Register( Info_Type, (Name)XML_IO_Handler_Type );

   /* Avoid confusing messages from XML_IO_Handler. Turn it off temporarily. */
   isEnabled = Stream_IsEnable( s );
   Stream_EnableSelfOnly( s, False );

   ioHandler = XML_IO_Handler_New();
   if( sources == NULL )
      ioHandler->writeSources = False;
   outputPath = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_GetDefault( dictionary,
      (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString( "./" ) ) ) );
   outputSlim = Dictionary_Entry_Value_AsBool( Dictionary_GetDefault( dictionary,
      (Dictionary_Entry_Key)"outputSlimmedXML", Dictionary_Entry_Value_FromBool( True ) ) );

   if( ! Stg_DirectoryExists( outputPath ) ) {
      if( Stg_FileExists( outputPath ) )
         Journal_Firewall( 0, s, "outputPath '%s' is a file an not a directory! Exiting...\n", outputPath );

      Journal_Printf( s, "outputPath '%s' does not exist, attempting to create...\n", outputPath );
      ret = Stg_CreateDirectory( outputPath );
      Journal_Firewall( ret, s, "Unable to create non-existing outputPath to '%s'\n", outputPath );
      Journal_Printf( s, "outputPath '%s' successfully created!\n", outputPath );
   }

   /* Set file names. */
   Stg_asprintf( &flatFilename, "%s/%s", outputPath, "input.xml" );

   IO_Handler_WriteAllToFile( ioHandler, flatFilename, dictionary, sources );

   /* Format; path/input-YYYY.MM.DD-HH.MM.SS.xml. */
   if (timeStamp) {
      Stg_asprintf( &flatFilenameStamped, "%s/%s-%s.%s",
                   outputPath, "input", timeStamp, "xml" );
      IO_Handler_WriteAllToFile( ioHandler, flatFilenameStamped, dictionary, sources );
      Memory_Free( flatFilenameStamped );
   }

   
   if( outputSlim && timeStamp ) {
      ioHandler->writeSources = False;
      Stg_asprintf( &slimFilename, "%s/%s-%s.%s",
         outputPath, "input-basic", timeStamp, "xml" );
      IO_Handler_WriteAllToFile( ioHandler, slimFilename, dictionary, NULL);
   }

   Stream_EnableSelfOnly( s, isEnabled );
   Stg_Class_Delete( ioHandler );

   Memory_Free( flatFilename );
}
void WallVCSuite_TestWallVC( WallVCSuiteData* data ) {
   unsigned                    nDomains;
   unsigned                    nDims = 3;
   unsigned                    meshSize[3] = {3, 3, 3};
   int                         procToWatch;
   double                      minCrds[3] = {0.0, 0.0, 0.0};
   double                      maxCrds[3] = {1.0, 1.0, 1.0};
   char*                       vcKey[] = {"WallVC_Front", "WallVC_Back", "WallVC_Left", "WallVC_Right",
                                          "WallVC_Top", "WallVC_Bottom"};
   char*                       vcKeyName[] = {"WallVC_FrontName", "WallVC_BackName", "WallVC_LeftName", "WallVC_RightName",
                                          "WallVC_TopName", "WallVC_BottomName"};
   char*                       varName[] = {"x", "y", "z", "vx", "vy", "vz", "temp"};
   char                        input_file[PCU_PATH_MAX];
   char                        expected_file[PCU_PATH_MAX];
   Mesh*                       mesh;
   Variable_Register*          variable_Register;
   ConditionFunction*          quadCF;
   ConditionFunction*          expCF;
   ConditionFunction_Register* conFunc_Register;
   ExtensionManager_Register*  extensionMgr_Register;
   Dictionary*                 dictionary;
   Dictionary*                 sources;
   Stream*                     stream;
   XML_IO_Handler*             io_handler;
   Variable*                   var[7];
   double*                     array[7];
   VariableCondition*          vc; 
   Index                       i;

   procToWatch = data->nProcs >=2 ? 1 : 0;

   io_handler = XML_IO_Handler_New();

    stream = Journal_Register( Info_Type, (Name)"WallVCStream"  );
   Stream_RedirectFile( stream, "testWallVC.dat" );

   dictionary = Dictionary_New();
   sources = Dictionary_New();
   Dictionary_Add( dictionary, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString("./output") );

   /* Input file */
   pcu_filename_input( "wallVC.xml", input_file );
   IO_Handler_ReadAllFromFile( io_handler, input_file, dictionary, sources );
   fflush( stdout );

   extensionMgr_Register = ExtensionManager_Register_New(); 

   /* Create a mesh. */
   mesh = (Mesh*) WallVCSuite_buildMesh( nDims, meshSize, minCrds, maxCrds, extensionMgr_Register );
   nDomains = Mesh_GetDomainSize( mesh, MT_VERTEX );

   /* Create CF stuff */
   quadCF = ConditionFunction_New( WallVCSuite_quadratic, (Name)"quadratic", NULL );
   expCF = ConditionFunction_New( WallVCSuite_exponential, (Name)"exponential", NULL);
   conFunc_Register = ConditionFunction_Register_New( );
   ConditionFunction_Register_Add(conFunc_Register, quadCF);
   ConditionFunction_Register_Add(conFunc_Register, expCF);

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

   /* Create variables */
   for (i = 0; i < 6; i++) {
      array[i] = Memory_Alloc_Array( double, nDomains, "array[i]" );
      var[i] = Variable_NewScalar( varName[i], NULL, Variable_DataType_Double, (Index*)&nDomains, NULL, (void**)&array[i], 0  );
      Variable_Register_Add(variable_Register, var[i]);
   }
   array[6] = Memory_Alloc_Array( double, nDomains * 5, "array[6]" );
   var[6] = Variable_NewVector( varName[6], NULL, Variable_DataType_Double, 5, &nDomains, NULL, (void**)&array[6], 0 );
   Variable_Register_Add(variable_Register, var[6]);
   Variable_Register_BuildAll(variable_Register);

   for (i = 0; i < 6; i++) {
      Index j, k;

      vc = (VariableCondition*) WallVC_New( vcKeyName[i], NULL, vcKey[i], variable_Register, conFunc_Register, dictionary, mesh );
      Stg_Component_Build( vc, 0, False );

      for (j = 0; j < 6; j++)
         memset(array[j], 0, sizeof(double)* nDomains );
      memset(array[6], 0, sizeof(double)* nDomains * 5);
      VariableCondition_Apply(vc, NULL);

      if (data->rank == procToWatch) {
         Journal_Printf( stream,"Testing for %s\n", vcKey[i]);
         for (j = 0; j < 6; j++) {
            Journal_Printf( stream,"\nvar[%u]: %.2lf", j, array[j][0]);
            for (k = 1; k < nDomains; k++)
               Journal_Printf( stream,", %.2lf", array[j][k]);
         }

         Journal_Printf( stream,"\nvar[6]: %.2lf", array[6][0]);
         for (j = 1; j < nDomains*5; j++)
            Journal_Printf( stream,", %.2lf", array[6][j]);
         Journal_Printf( stream,"\n\n");

         for (j = 0; j < 7; j++) {
            for (k = 0; k < nDomains; k++)
               Journal_Printf( stream,"%s ", VariableCondition_IsCondition(vc, k, j) ? "True " : "False");
            Journal_Printf( stream,"\n");
         } Journal_Printf( stream,"\n");

         for (j = 0; j < 7; j++) {
            for (k = 0; k < nDomains; k++) {
               VariableCondition_ValueIndex  valIndex;
               valIndex = VariableCondition_GetValueIndex(vc, k, j);
               if (valIndex != (unsigned)-1)
                  Journal_Printf( stream,"%03u ", valIndex);
               else
                  Journal_Printf( stream,"XXX ");
            } Journal_Printf( stream,"\n");
         } Journal_Printf( stream,"\n");
      }
      Stg_Class_Delete(vc);
   }

   if (data->rank == procToWatch) {
      pcu_filename_expected( "testWallVC.expected", expected_file );
      pcu_check_fileEq( "testWallVC.dat", expected_file );
      remove( "testWallVC.dat" );
   }

   Stg_Class_Delete(variable_Register);
   for (i = 0; i < 7; i++) {
      Stg_Class_Delete(var[i]);
      if (array[i]) Memory_Free(array[i]);
   }
   Stg_Class_Delete(extensionMgr_Register);
   Stg_Class_Delete(io_handler);
   Stg_Class_Delete(conFunc_Register);
   Stg_Class_Delete(quadCF);
   Stg_Class_Delete(expCF);
   Stg_Class_Delete(dictionary);
   Stg_Class_Delete(sources);
   FreeObject( mesh );
}
void _SnacRemesher_ConstructExtensions( void* _context, void* data ) {
	Snac_Context*				context = (Snac_Context*)_context;
	SnacRemesher_Context*			contextExt = ExtensionManager_Get(
							context->extensionMgr,
							context,
							SnacRemesher_ContextHandle );
	Mesh*					mesh = context->mesh;
	SnacRemesher_Mesh*			meshExt = ExtensionManager_Get(
							context->meshExtensionMgr,
							mesh,
							SnacRemesher_MeshHandle );
	char*					conditionStr;
	Dictionary_Entry_Value*			conditionCriterion;
	Dictionary* 				meshDict;
	Stream*					error = Journal_Register( Error_Type, "Remesher" );
	char					tmpBuf[PATH_MAX];

	Journal_Printf( context->debug, "In: %s\n", __func__ );
	
	contextExt->debugIC = Journal_Register( Debug_Type, "Remesher-ICs" );
	contextExt->debugCoords = Journal_Register( Debug_Type, "Remesher-Coords" );
	contextExt->debugNodes = Journal_Register( Debug_Type, "Remesher-Nodes" );
	contextExt->debugElements = Journal_Register( Debug_Type, "Remesher-Elements" );
	contextExt->debugSync = Journal_Register( Debug_Type, "Remesher-Sync" );
	
	/* Additional tables required over the nodeElementTbl already required by core Snac */
	Mesh_ActivateNodeNeighbourTbl( mesh );
	Mesh_ActivateElementNeighbourTbl( mesh );
	
	/* Work out condition to remesh on */
	if( !Dictionary_Get( context->dictionary, CONDITION_STR ) ) {
		Journal_Printf( 
			error,
			"Warning: No \"%s\" entry in dictionary... will default to \"%s\"\n", 
			CONDITION_STR,
			OFF_STR );
	}
	
	conditionStr = Dictionary_Entry_Value_AsString( 
		Dictionary_GetDefault( context->dictionary, CONDITION_STR, Dictionary_Entry_Value_FromString( OFF_STR ) ) );
	
	contextExt->OnTimeStep = 0;
	contextExt->onMinLengthScale = 0;
	if( !strcmp( conditionStr, OFF_STR ) ) {
		contextExt->condition = SnacRemesher_Off;
		Journal_Printf( context->snacInfo, "Remesher is off\n" );
	}
	else if( !strcmp( conditionStr, ONTIMESTEP_STR ) ) {
		contextExt->condition = SnacRemesher_OnTimeStep;
		conditionCriterion = Dictionary_Get( context->dictionary, TIMESTEPCRITERION_STR );
		Journal_Printf( context->snacInfo, "Remesher is on... activated based on timeStep\n" );
		
		if( conditionCriterion ) {
			contextExt->OnTimeStep = Dictionary_Entry_Value_AsUnsignedInt( conditionCriterion );
		}
		else {
		}
		Journal_Printf( context->snacInfo, "Remeshing every %u timeSteps\n", contextExt->OnTimeStep );
	}
	else if( !strcmp( conditionStr, ONMINLENGTHSCALE_STR ) ) {
		contextExt->condition = SnacRemesher_OnMinLengthScale;
		conditionCriterion = Dictionary_Get( context->dictionary, LENGTHCRITERION_STR );
		Journal_Printf( context->snacInfo, "Remesher is on... activated by minLengthScale\n" );
		
		if( conditionCriterion ) {
			contextExt->onMinLengthScale = Dictionary_Entry_Value_AsDouble( conditionCriterion );
		}
		else {
		}
		Journal_Printf( context->snacInfo, "Remesh when minLengthScale < %g\n", contextExt->onMinLengthScale );
	}
	else if( !strcmp( conditionStr, ONBOTHTIMESTEPLENGTH_STR ) ) {
		contextExt->condition = SnacRemesher_OnBothTimeStepLength;
		conditionCriterion = Dictionary_Get( context->dictionary, TIMESTEPCRITERION_STR );
		Journal_Printf( context->snacInfo, "Remesher is on... activated by both timeStep and minLengthScale\n" );
		
		if( conditionCriterion ) {
			contextExt->OnTimeStep = Dictionary_Entry_Value_AsUnsignedInt( conditionCriterion );
			conditionCriterion = Dictionary_Get( context->dictionary, LENGTHCRITERION_STR );
			contextExt->onMinLengthScale = Dictionary_Entry_Value_AsDouble( conditionCriterion );
		}
		else {
		}
		Journal_Printf( context->snacInfo, "Remesh every %u timeSteps or wheen minLengthScale < %g\n", contextExt->OnTimeStep, contextExt->onMinLengthScale );
	}
	else {
		contextExt->condition = SnacRemesher_Off;
		Journal_Printf( context->snacInfo, "Remesher is defaulting to off\n" );
		Journal_Printf( error, "Provided remesh condition \"%s\" unrecognised\n", conditionStr );
	}
	
	
	/* Work out the mesh type */
	meshDict = Dictionary_Entry_Value_AsDictionary( Dictionary_Get( context->dictionary, MESH_STR ) );
	if( meshDict ) {
		char* 					meshTypeStr;
		
		if( !Dictionary_Get( meshDict, MESHTYPE_STR ) ) {
			Journal_Printf( 
				error,
				"Warning: No \"%s\" entry in \"%s\"... will default to \"%s\"\n", 
				MESHTYPE_STR, 
				MESH_STR, 
				CARTESIAN_STR );
		}
		
		meshTypeStr = Dictionary_Entry_Value_AsString( 
			Dictionary_GetDefault( meshDict, MESHTYPE_STR, Dictionary_Entry_Value_FromString( CARTESIAN_STR ) ) );
		
		if( !strcmp( meshTypeStr, SPHERICAL_STR ) ) {
			meshExt->meshType = SnacRemesher_Spherical;
			Journal_Printf( context->snacInfo, "Remesher knows mesh as a spherical mesh\n" );
		}
		else if( !strcmp( meshTypeStr, CARTESIAN_STR ) ) {
			meshExt->meshType = SnacRemesher_Cartesian;
			Journal_Printf( context->snacInfo, "Remesher knows mesh as a cartesian mesh\n" );
		}
		else {
			meshExt->meshType = SnacRemesher_Cartesian;
			Journal_Printf( context->snacInfo, "Remesher assuming mesh as a cartesian mesh\n" );
			Journal_Printf( error, "Provided mesh type \"%s\" unrecognised!\n", meshTypeStr );
		}
	}
	else {
		meshExt->meshType = SnacRemesher_Cartesian;
		Journal_Printf( context->snacInfo, "Remesher assuming mesh as a cartesian mesh\n" );
		Journal_Printf( error, "No \"%s\" entry in dictionary!\n", MESH_STR );
	}
	/* Decide whether to restore the bottom surface */
	contextExt->bottomRestore = 0;
	if( !strcmp( Dictionary_Entry_Value_AsString( Dictionary_GetDefault( context->dictionary, "bottomRestore", Dictionary_Entry_Value_FromString( OFF_STR ) ) ), ON_STR) )
		contextExt->bottomRestore = 1;


	/* Register these functions for use in VCs */
	ConditionFunction_Register_Add(
		context->condFunc_Register,
		ConditionFunction_New( _SnacRemesher_TestCondFunc, "SnacRemesher_TestCondFunc" ) );
	
	/* Register these functions for use in VCs */
	ConditionFunction_Register_Add(
		context->condFunc_Register,
		ConditionFunction_New( _SnacRemesher_XFunc, "SnacRemesher_XFunc" ) );
	
	/* Register these functions for use in VCs */
	ConditionFunction_Register_Add(
		context->condFunc_Register,
		ConditionFunction_New( _SnacRemesher_YFunc, "SnacRemesher_YFunc" ) );
	
	/* Obtain the keys for the our new entry points... having the keys saves doing a string compare at run time */
	contextExt->recoverNodeK = EntryPoint_Register_GetHandle( 
		context->entryPoint_Register, 
		SnacRemesher_EP_RecoverNode );
	contextExt->interpolateNodeK = EntryPoint_Register_GetHandle( 
		context->entryPoint_Register, 
		SnacRemesher_EP_InterpolateNode );
	contextExt->interpolateElementK = EntryPoint_Register_GetHandle( 
		context->entryPoint_Register, 
		SnacRemesher_EP_InterpolateElement );

	/* Prepare the dump file */
	if( context->rank == 0) {
		sprintf( tmpBuf, "%s/remeshInfo.%u", context->outputPath, context->rank );
		if( (contextExt->remesherOut = fopen( tmpBuf, "w+" )) == NULL ) {
			assert( contextExt->remesherOut /* failed to open file for writing */ );
		}
	}
	/* initialize remeshing counter */
	contextExt->remeshingCount = 0;
}
Dictionary_Entry_Value* Dictionary_Entry_Value_Copy(
		Dictionary_Entry_Value*  self,
		Bool deep )
{
	Dictionary_Entry_Value* copy = NULL;
	
	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_List:
			if ( False == deep ) {
				Stream* errorStream = Journal_Register( Error_Type, "Dictionary_Entry_Value" );
				Journal_Firewall( False, errorStream, "In func %s: Shallow copy operation of list DEV not supported.\n", __func__ );
			}
			else {
				Dictionary_Entry_Value* cur = self->as.typeList->first;
				Dictionary_Entry_Value* copiedEntry = NULL;

				copy = Dictionary_Entry_Value_NewList();
				while ( cur ) {
					copiedEntry = Dictionary_Entry_Value_Copy( cur, True );
					Dictionary_Entry_Value_AddElement( copy, copiedEntry );
					cur = cur->next;
				}	
			}
			break;
		case Dictionary_Entry_Value_Type_Struct:
			if ( False == deep ) {
				copy = Dictionary_Entry_Value_FromStruct( self->as.typeStruct );
			}
			else {
				Dictionary* copiedDict;
				copiedDict = (Dictionary*)Stg_Class_Copy( self->as.typeStruct,
					NULL, True, NULL, NULL );
				copy = Dictionary_Entry_Value_FromStruct( copiedDict );
			}
			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 );
		}
	}

	return copy;
}
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[] ) {
    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 */
}
void TimeIntegrationSuite_TestDriver( TimeIntegrationSuiteData* data, char *_name, char *_DerivName0, char *_DerivName1, int _order ) {
   Stg_ComponentFactory* cf;
   Stream*               stream;
   Dictionary*           dictionary;
   TimeIntegrator*       timeIntegrator;
   TimeIntegrand*        timeIntegrand;
   TimeIntegrand*        timeIntegrandList[2];
   DomainContext*        context;
   Variable*             variable;
   Variable*             variableList[2];
   double*               array;
   double*               array2;
   Index                 size0 = 11;
   Index                 size1 = 7;
   Index                 array_I;
   Index                 timestep = 0;
   Index                 maxTimesteps = 10;
   Bool                  simultaneous;
   unsigned              order;
   double                error = 0.0;
   Name                  derivName;
   double                tolerance = 0.001;
   Index                 integrand_I;
   Index                 integrandCount = 2;
   char                  expected_file[PCU_PATH_MAX];

   dictionary = Dictionary_New();
   Dictionary_Add( dictionary, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString("./output") );
   Dictionary_Add( dictionary, (Dictionary_Entry_Key)"DerivName0", Dictionary_Entry_Value_FromString(_DerivName0) );
   Dictionary_Add( dictionary, (Dictionary_Entry_Key)"DerivName1", Dictionary_Entry_Value_FromString(_DerivName1) );

   context = DomainContext_New( "context", 0, 0, MPI_COMM_WORLD, NULL );
   cf = stgMainConstruct( dictionary, NULL, data->comm, context );
   stgMainBuildAndInitialise( cf );
      
   ContextEP_Append( context, AbstractContext_EP_Dt, TimeIntegrationSuite_GetDt );

   /* Create Stuff */
   order = _order;
   simultaneous = False;
   variableList[0] = Variable_NewVector( "testVariable", (AbstractContext*)context, Variable_DataType_Double, 2, &size0, NULL, (void**)&array, NULL );
   variableList[1] = Variable_NewVector( "testVariable2", (AbstractContext*)context, Variable_DataType_Double, 2, &size1, NULL, (void**)&array2, NULL );
   timeIntegrator = TimeIntegrator_New( "testTimeIntegrator", order, simultaneous, NULL, NULL );
   timeIntegrator->context = context;
   timeIntegrandList[0] = TimeIntegrand_New( "testTimeIntegrand0", context, timeIntegrator, variableList[0], 0, NULL, True );
   timeIntegrandList[1] = TimeIntegrand_New( "testTimeIntegrand1", context, timeIntegrator, variableList[1], 0, NULL, True );

   Journal_Enable_AllTypedStream( True );
   stream = Journal_Register( Info_Type, (Name)"EulerStream"  );
   Stream_RedirectFile( stream, _name );

   Stream_Enable( timeIntegrator->info, False );
   derivName = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"DerivName0" );
   timeIntegrandList[0]->_calculateTimeDeriv = TimeIntegrationSuite_GetFunctionPtr( derivName  );
   Journal_Printf( stream, "DerivName0 - %s\n", derivName );
   derivName = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"DerivName1" );
   timeIntegrandList[1]->_calculateTimeDeriv = TimeIntegrationSuite_GetFunctionPtr( derivName  );
   Journal_Printf( stream, "DerivName1 - %s\n", derivName );

   /* Print Stuff to file */
   Journal_PrintValue( stream, order );
   Journal_PrintBool( stream, simultaneous );

   /* Add stuff to EPs */
   TimeIntegrator_AppendSetupEP( timeIntegrator, "start1", TimeIntegrationSuite_TestContextType, CURR_MODULE_NAME, context );
   TimeIntegrator_AppendFinishEP( timeIntegrator, "finish1", TimeIntegrationSuite_TestVariableType, CURR_MODULE_NAME, variableList[0] );
   TimeIntegrator_PrependSetupEP( timeIntegrator, "start0", TimeIntegrationSuite_TestVariableType, CURR_MODULE_NAME, variableList[0] );
   TimeIntegrator_PrependFinishEP( timeIntegrator, "finish0", TimeIntegrationSuite_TestContextType, CURR_MODULE_NAME, context );

   /* Build */
   Stg_Component_Build( variableList[0], context, False );
   Stg_Component_Build( variableList[1], context, False );
   Stg_Component_Build( timeIntegrator, context, False );
   Stg_Component_Build( timeIntegrandList[0], context, False );
   Stg_Component_Build( timeIntegrandList[1], context, False );
   array = Memory_Alloc_Array( double, 2 * size0, "name" );
   array2 = Memory_Alloc_Array( double, 2 * size1, "name" );

   /* Initialise */
   memset( array, 0, sizeof(double) * 2 * size0 );
   memset( array2, 0, sizeof(double) * 2 * size1 );
   Stg_Component_Initialise( timeIntegrator, context, False );
   Stg_Component_Initialise( variableList[0], context, False );
   Stg_Component_Initialise( variableList[1], context, False );
   Stg_Component_Initialise( timeIntegrandList[0], context, False );
   Stg_Component_Initialise( timeIntegrandList[1], context, False );

   for ( timestep = 0.0 ; timestep < maxTimesteps ; timestep ++ ) {
      Journal_Printf( stream, "Step %u - Time = %.3g\n", timestep, context->currentTime );

      Stg_Component_Execute( timeIntegrator, context, True );
      context->currentTime += AbstractContext_Dt( context );

      for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
         timeIntegrand   = timeIntegrandList[ integrand_I ];
         variable         = variableList[ integrand_I ];
         for ( array_I = 0 ; array_I < variable->arraySize ; array_I++ ) {
            if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_ConstantTimeDeriv ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) - 2.0 * array_I * context->currentTime );
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) + array_I * context->currentTime );
            }
            else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_ConstantTimeDeriv2 ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) + 0.5 * array_I * context->currentTime );
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) - 3 * array_I * context->currentTime );
            }
            else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_LinearTimeDeriv ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) - array_I * context->currentTime * context->currentTime );
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) + 0.5 * array_I * context->currentTime * context->currentTime );
            }
            else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_LinearTimeDeriv2 ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) + 0.25 * array_I * context->currentTime * context->currentTime );
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) - 1.5 * array_I * context->currentTime * context->currentTime );
            }
            else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_CubicTimeDeriv ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) - 2.0 * array_I * ( 0.25 * pow( context->currentTime, 4.0 ) - pow( context->currentTime, 3.0)/3.0));
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) + array_I * ( 0.25 * pow( context->currentTime, 4.0 ) - pow( context->currentTime, 3.0 )/3.0));
            }
            else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_CubicTimeDeriv2 ) {
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 0 ) + 0.5 * array_I * ( 0.25 * pow( context->currentTime, 4.0 ) - pow( context->currentTime, 3.0)/3.0));
               error += fabs( Variable_GetValueAtDouble( variable, array_I, 1 ) - 3.0 * array_I * ( 0.25 * pow( context->currentTime, 4.0 ) - pow( context->currentTime, 3.0 )/3.0));
            }
            else
               Journal_Firewall( 0 , Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  ), "Don't understand _calculateTimeDeriv = %p\n", timeIntegrand->_calculateTimeDeriv );
         }
      }
   }
   pcu_check_lt( error, tolerance );

   if ( error < tolerance )
      Journal_Printf( stream, "Passed\n" );
   else
      Journal_Printf( stream, "Failed - Error = %lf\n", error );
   
   Journal_Enable_AllTypedStream( False );

   if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_ConstantTimeDeriv
      || timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_ConstantTimeDeriv2 ) {
      pcu_filename_expected( "testTimeIntegrationEulerOutput.expected", expected_file );
   }
   else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_LinearTimeDeriv
      || timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_LinearTimeDeriv2 ) {
      pcu_filename_expected( "testTimeIntegrationRK2Output.expected", expected_file );
   }
   else if ( timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_CubicTimeDeriv
      || timeIntegrand->_calculateTimeDeriv == TimeIntegrationSuite_CubicTimeDeriv2 ) {
      pcu_filename_expected( "testTimeIntegrationRK4Output.expected", expected_file );
   }

   pcu_check_fileEq( _name, expected_file );

   /* Destroy stuff */
   Stream_CloseAndFreeFile( stream );
   Memory_Free( array );
   Memory_Free( array2 );
   Stg_Class_Delete( variable );
   _Stg_Component_Delete( timeIntegrator );
   _Stg_Component_Delete( timeIntegrandList[0] );
   _Stg_Component_Delete( timeIntegrandList[1] );
   remove( _name );
}
Exemple #10
0
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( &argv[6], "--hot.tub.times=fun");
   Stg_asprintf( &expectedKeys[3], "hot" );

   expectedVals[3] = Dictionary_Entry_Value_NewStruct();
   Dictionary_Entry_Value_AddMember( expectedVals[3], (Dictionary_Entry_Key)"tub", tmpStruct = Dictionary_Entry_Value_NewStruct()  );
   Dictionary_Entry_Value_AddMember( tmpStruct, (Dictionary_Entry_Key)"times", Dictionary_Entry_Value_FromString( "fun" )  );
   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 );
}
Exemple #11
0
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 );
}
Exemple #12
0
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[] ) {
	
	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;
}