Bool _check_if_constant_nullsp_present( Stokes_SLE_UzawaSolver* self, Mat K, Mat G, Mat M, Vec t1, Vec ustar,  Vec r, Vec l, KSP ksp )
{
    PetscInt N;
    PetscScalar sum;
    PetscReal nrm;
    Bool nullsp_present;

    VecGetSize(l,&N);
    sum  = 1.0/N;
    VecSet(l,sum);

    /* [S] {l} = {r} */
    MatMult( G,l, t1 );
    KSPSolve( ksp, t1, ustar );
    MatMultTranspose( G, ustar, r );     
    if ( M ) {
	VecScale( r, -1.0 );
	MatMultAdd( M,l, r, r );
	VecScale( r, -1.0 );
    }

    VecNorm(r,NORM_2,&nrm);
    if (nrm < 1.e-7) {
	Journal_PrintfL( self->info, 1, "Constant null space detected, " ); 
	nullsp_present = True;
    }
    else {
	Journal_PrintfL( self->info, 1, "Constant null space not present, " );
	nullsp_present = False;
    }
    Journal_PrintfL( self->info, 1, "|| [S]{1} || = %G\n", nrm );


    return nullsp_present;
}
Stg_Component* _Stg_ComponentFactory_ConstructByNameWithKeyFallback( 
   void*         cf, 
   Name          parentComponentName, 
   Name                 componentTrialName, 
   Dictionary_Entry_Key fallbackKey, 
   Type         type, 
   Bool         isEssential,
   void*         data ) 
{
   Stg_ComponentFactory*   self              = (Stg_ComponentFactory*)cf;
   Stg_Component*      component;
   Stream*         stream            = self->infoStream;

   Journal_PrintfL( stream, 2, "First Trying to find component by name '%s': ", componentTrialName );
   component = LiveComponentRegister_Get( self->LCRegister, componentTrialName );
   
   if (component) {
      Journal_PrintfL( stream, 2, "Found.\n" );

      if ( !component->isConstructed ) {
         Journal_Printf( stream, "%s has not been constructed yet. Constructing now.\n", componentTrialName );
         Stream_Indent( stream );
         Stg_Component_AssignFromXML( component, self, data, True );
         Stream_UnIndent( stream );
      }
   }
   else {
      Journal_PrintfL( stream, 2, "Not found.\n" );
      Journal_PrintfL( stream, 2, "Fallback - Trying to find component by key '%s'.\n", fallbackKey );

      component = self->constructByKey( self, parentComponentName, fallbackKey, type, isEssential, data );
   }
      
   return component;
}
Stg_Component* _Stg_ComponentFactory_ConstructByName( void* cf, Name componentName, Type type, Bool isEssential, void* data ) {
   Stg_ComponentFactory*   self              = (Stg_ComponentFactory*)cf;
   Stg_Component*      component;
   Stream*         stream            = self->infoStream;

   Journal_PrintfL( stream, 2, "Looking for %sessential component '%s': ", (isEssential ? "" : "non-"), componentName );

   component = LiveComponentRegister_Get( self->LCRegister, componentName );

   /* Checking */
   if (component) {
      Journal_PrintfL( stream, 2, "Found.\n" );

      if ( !component->isConstructed ) {
         /* Journal_Printf( stream, "%s has not been constructed yet. Constructing now.\n", componentName ); */
         Stream_Indent( stream );
         Stg_Component_AssignFromXML( component, self, data, True );
         Stream_UnIndent( stream );
      }

      Stg_Class_CheckType( component, type );

   }
   else {
      Name         redirect;

      /* If we can find the component's name in the root dictionary, use that value instead. */
      if( self->rootDict ) {
         redirect = Dictionary_GetString_WithDefault( self->rootDict, componentName, "" );
         if( strcmp( redirect, "" ) ) {
            componentName = redirect;
            return self->constructByName( self, componentName, type, isEssential, data );
         }
      }

      Journal_PrintfL( stream, 2, "Not found.\n" );

      if ( isEssential ) {
         Stream* errorStream = Journal_Register( Error_Type, self->type );

         Journal_Printf( errorStream, "In func %s: Cannot find essential component '%s'.\n", __func__, componentName );

         Journal_Printf( errorStream, "Could you have meant one of these?\n" );

         Stream_Indent( errorStream );
         LiveComponentRegister_PrintSimilar( self->LCRegister, componentName, errorStream, 5 );
         Journal_Firewall( 0, errorStream, "" );
      }
   }
   
   return component;
}
Bool _Stg_ComponentFactory_GetRootDictBool( void* cf, Dictionary_Entry_Key key, const Bool defaultVal ) {
   Stg_ComponentFactory*    self              = (Stg_ComponentFactory*)cf;
   
   Journal_PrintfL( self->infoStream, 2, "Getting Bool from root dictionary with key '%s' and default value '%s'\n",
         key, defaultVal ? "True" : "False" );

   assert( self->rootDict );
   return Dictionary_GetBool_WithDefault( self->rootDict, key, defaultVal );
}   
char* _Stg_ComponentFactory_GetRootDictString( void* cf, Dictionary_Entry_Key key, const char* const defaultVal ) {
   Stg_ComponentFactory*    self              = (Stg_ComponentFactory*)cf;

   Journal_PrintfL( self->infoStream, 2, "Getting string from root dictionary with key '%s' and default value '%s'\n",
         key, defaultVal );

   assert( self->rootDict );
   return Dictionary_GetString_WithDefault( self->rootDict, key, defaultVal );
}
unsigned int _Stg_ComponentFactory_GetRootDictUnsignedInt( void* cf, Dictionary_Entry_Key key, const unsigned int defaultVal ) {
   Stg_ComponentFactory*    self              = (Stg_ComponentFactory*)cf;
   
   Journal_PrintfL( self->infoStream,2, "Getting unsigned int from root dictionary with key '%s' and default value '%u'\n",
         key, defaultVal );

   assert( self->rootDict );
   return Dictionary_GetUnsignedInt_WithDefault( self->rootDict, key, defaultVal );
}   
Stg_Component* _Stg_ComponentFactory_PluginConstructByKey( 
   void*                  cf, 
   void*                  codelet, 
   Dictionary_Entry_Key   componentKey,
   Type                  type, 
   Bool                  isEssential,
   void*                  data ) 
{
   Stg_ComponentFactory*   self = (Stg_ComponentFactory*)cf;
   Stg_Component*            plugin = (Stg_Component*)codelet;
   Dictionary*               thisPluginDict = NULL;
   Dictionary*               pluginDict = (Dictionary*)Dictionary_Get( self->rootDict, "plugins" );
   Name                     componentName, redirect, pluginType;
   Dictionary_Entry_Value*   componentEntryVal;
   Index                     pluginIndex;
   Stream*                  errorStream = Journal_Register( Error_Type, self->type );

   Journal_Firewall( self != NULL, errorStream, "In func %s: Stg_Component is NULL.\n", __func__ );

   /* Get this plugins Dictionary */
   for( pluginIndex = 0; pluginIndex < Dictionary_Entry_Value_GetCount( (Dictionary_Entry_Value*)pluginDict ); pluginIndex++ ) {
      thisPluginDict = Dictionary_Entry_Value_AsDictionary( Dictionary_Entry_Value_GetElement( (Dictionary_Entry_Value*)pluginDict, pluginIndex ) );
      pluginType = StG_Strdup( Dictionary_GetString( thisPluginDict, "Type" ) );

      if( !strcmp( plugin->type, pluginType ) ){
         Memory_Free( pluginType );
         break;
      }
      Memory_Free( pluginType );
   }
   
   /* Get Dependency's Name */
   componentEntryVal = Dictionary_Get( thisPluginDict, componentKey );
   if ( componentEntryVal == NULL ) {
      Journal_Firewall( !isEssential, errorStream,
            "plugin '%s' cannot find essential component with key '%s'.\n", plugin->type, componentKey );
      Journal_PrintfL( self->infoStream, 2, "plugin '%s' cannot find non-essential component with key '%s'.\n", plugin->type, componentKey );
      return NULL;
   }
      
   componentName = Dictionary_Entry_Value_AsString( componentEntryVal );

   /* If we can find the component's name in the root dictionary, use that value instead. */
   if( self->rootDict ) {
      redirect = Dictionary_GetString_WithDefault( self->rootDict, componentName, "" );
      if( strcmp( redirect, "" ) )
         componentName = redirect;
   }

   return self->constructByName( self, componentName, type, isEssential, data );
}
Dictionary_Entry_Value* _Stg_ComponentFactory_PluginGetNumericalValue( void* cf, void *codelet, Dictionary_Entry_Key key, Dictionary_Entry_Value* defaultVal ) {
   Stg_ComponentFactory*    self           = (Stg_ComponentFactory*)cf;
   Dictionary_Entry_Value* returnVal;
   Bool                    usedDefault       = False;
   Stream*                 stream            = self->infoStream;
   Stream*         errorStream       = Journal_Register( Error_Type, self->type );

   Journal_Firewall( self != NULL, errorStream, "In func %s: Stg_Component is NULL.\n", __func__ );

   returnVal = _Stg_ComponentFactory_PluginGetDictionaryValue( self, codelet, key, defaultVal );

   /* Check to see whether the type is a string -
    * if it is then assume that this is a dictionary key linking to the root dictionary */
   if ( returnVal ) {
      Dictionary_Entry_Key rootDictKey = Dictionary_Entry_Value_AsString( returnVal );
      Dictionary*          rootDict    = self->rootDict;

      /* Check if the number really is a string or not */
      if ( Stg_StringIsNumeric( rootDictKey ) )
         return returnVal;
      
      Journal_PrintfL( stream, 2, "Key '%s' points to key '%s' in the root dictionary: ", key, rootDictKey );

      Journal_Firewall( rootDict != NULL, errorStream, "Root Dictionary NULL in component factory.\n" );

      /* Get Value from dictionary */
      returnVal = Dictionary_Get( rootDict, rootDictKey );
      if ( !returnVal && defaultVal ) {
         returnVal = Dictionary_GetDefault( rootDict, rootDictKey, defaultVal );
         usedDefault = True;
      }

      /* Print Stuff */
      if ( usedDefault ) {
         Journal_PrintfL( stream, 2, "Using default value = " );
         if ( Stream_IsPrintableLevel( stream, 2 ) ) 
            Dictionary_Entry_Value_Print( returnVal, stream );
         Journal_PrintfL( stream, 2, "\n" );
         return returnVal;
      }
      else if ( returnVal ) {
         Journal_PrintfL( stream, 2, "Found - Value = " );
         if ( Stream_IsPrintableLevel( stream, 2 ) ) 
            Dictionary_Entry_Value_Print( returnVal, stream );
         Journal_PrintfL( stream, 2, "\n" );
      }
      else 
         Journal_PrintfL( stream, 2, "Not found.\n" );
   }

   return returnVal;
}
Dictionary_Entry_Value* _Dictionary_GetDouble_WithScopeDefault(
   Dictionary*             dictionary,
   Dictionary_Entry_Key    key,
   Dictionary_Entry_Value* defaultVal )
{
   Dictionary_Entry_Value *returnVal=NULL;
   Bool                    usedDefault = False;
   Stream*                 stream = Journal_Register( Info_Type, "Dictionary" );

   returnVal = Dictionary_GetDefault( dictionary, key, defaultVal );

   if( returnVal && returnVal->type == Dictionary_Entry_Value_Type_String ) { 
      Dictionary_Entry_Key rootDictKey = Dictionary_Entry_Value_AsString( returnVal ); 
      Dictionary*          rootDict    = dictionary; 

      /* Check if the number really is a string or not */ 
      if( Stg_StringIsNumeric( rootDictKey ) ) 
         return returnVal; 

      Journal_PrintfL(
         stream,
         2,
         "Key '%s' points to key '%s' in the root dictionary: ",
         key,
         rootDictKey ); 

      /* Get Value from dictionary */ 
      returnVal = Dictionary_Get( rootDict, rootDictKey ); 
      if( !returnVal && defaultVal ) { 
         returnVal = Dictionary_GetDefault( rootDict, rootDictKey, defaultVal ); 
         usedDefault = True; 
      } 

      /* Print Stuff */ 
      if( usedDefault ) { 
         Journal_PrintfL( stream, 2, "Using default value = " ); 
         if( Stream_IsPrintableLevel( stream, 2 ) )  
            Dictionary_Entry_Value_Print( returnVal, stream ); 
            Journal_PrintfL( stream, 2, "\n" ); 
         return returnVal; 
      } 
      else if( returnVal ) { 
         Journal_PrintfL( stream, 2, "Found - Value = " ); 
         if( Stream_IsPrintableLevel( stream, 2 ) )  
            Dictionary_Entry_Value_Print( returnVal, stream ); 
         Journal_PrintfL( stream, 2, "\n" ); 
      } 
      else  
         Journal_PrintfL( stream, 2, "Not found.\n" ); 
   } 
   return returnVal;
}
Stg_Component* _Stg_ComponentFactory_ConstructByKey( 
      void*         cf, 
      Name         parentComponentName, 
      Dictionary_Entry_Key   componentKey,
      Type         type, 
      Bool          isEssential,
      void*          data ) 
{
   Stg_ComponentFactory*   self              = (Stg_ComponentFactory*)cf;
   Dictionary*      thisComponentDict = NULL;
   Dictionary*      componentDict     = NULL;
   Name         componentName, redirect;
   Dictionary_Entry_Value*   componentEntryVal;
   Stream*         errorStream       = Journal_Register( Error_Type, self->type );

   Journal_Firewall( self != NULL, errorStream, "In func %s: Stg_Component is NULL.\n", __func__ );

   /* Get this Stg_Component's Dictionary */
   componentDict = self->componentDict;
   Journal_Firewall( componentDict != NULL, errorStream, 
         "In func %s: Stg_Component Factory's dictionary is NULL.\n", __func__ );
   thisComponentDict = Dictionary_GetDictionary( componentDict, parentComponentName );

   /* Get Dependency's Name */
   componentEntryVal = Dictionary_Get( thisComponentDict, componentKey );
   if ( componentEntryVal == NULL ) {
      Journal_Firewall( !isEssential, errorStream,
            "Stg_Component '%s' cannot find essential component with key '%s'.\n", parentComponentName, componentKey );
      Journal_PrintfL( self->infoStream, 2, "Stg_Component '%s' cannot find non-essential component with key '%s'.\n", parentComponentName, componentKey );
      return NULL;
   }
      
   componentName = Dictionary_Entry_Value_AsString( componentEntryVal );

   /* If we can find the component's name in the root dictionary, use that value instead. */
   if( self->rootDict ) {
      redirect = Dictionary_GetString_WithDefault( self->rootDict, componentName, "" );
      if( strcmp( redirect, "" ) )
         componentName = redirect;
   }

   return self->constructByName( self, componentName, type, isEssential, data );
}
Dictionary_Entry_Value* _Stg_ComponentFactory_GetDictionaryValue( void* cf, Name componentName, Dictionary_Entry_Key key, Dictionary_Entry_Value* defaultVal ) {
   Stg_ComponentFactory*       self              = (Stg_ComponentFactory*) cf;
   Dictionary*             componentDict     = NULL;
   Dictionary*             thisComponentDict = NULL;
   Dictionary_Entry_Value* returnVal;
   Bool                    usedDefault       = False;
   Stream*                 errorStream       = Journal_Register( Error_Type, Stg_Component_Type );
   Stream*                 stream            = self->infoStream;

   Journal_Firewall( self != NULL, errorStream, "In func %s: Stg_ComponentFactory is NULL.\n", __func__ );

   Journal_PrintfL( stream, 2, "Getting parameter '%s': ", key );

   /* Get this Stg_Component's Dictionary */
   componentDict = self->componentDict;
   Journal_Firewall( componentDict != NULL, errorStream, 
         "In func %s: Stg_Component Factory's dictionary is NULL.\n", __func__ );
   thisComponentDict = Dictionary_GetDictionary( componentDict, componentName );
   if( thisComponentDict == NULL )
      return defaultVal;

   /* Get Value from dictionary */
   returnVal = Dictionary_Get( thisComponentDict, key );
   if ( !returnVal && defaultVal ) {
      returnVal = Dictionary_GetDefault( thisComponentDict, key, defaultVal );
      usedDefault = True;
   }

   /* Print Stuff */
   if ( usedDefault ) {
      Journal_PrintfL( stream, 2, "Using default value = " );
      if ( Stream_IsPrintableLevel( stream, 2 ) ) 
         Dictionary_Entry_Value_Print( returnVal, stream );
      Journal_PrintfL( stream, 2, "\n" );

      return returnVal;
   }
   else if ( returnVal ) {
      Journal_PrintfL( stream, 2, "Found - Value = " );
      if ( Stream_IsPrintableLevel( stream, 2 ) ) 
         Dictionary_Entry_Value_Print( returnVal, stream );
      Journal_PrintfL( stream, 2, "\n" );
   }
   else 
      Journal_PrintfL( stream, 2, "Not found.\n" );

   return returnVal;
}
void _Stokes_SLE_UzawaSolver_Solve( void* solver, void* stokesSLE ) {
	Stokes_SLE_UzawaSolver* self            = (Stokes_SLE_UzawaSolver*)solver;	
	Stokes_SLE*             sle             = (Stokes_SLE*)stokesSLE;
	
	/* Create shortcuts to stuff needed on sle */
	Mat                     K_Mat           = sle->kStiffMat->matrix;
	Mat                     G_Mat           = sle->gStiffMat->matrix;
	Mat                     D_Mat           = NULL;
	Mat                     M_Mat           = NULL;
	Vec                     uVec            = sle->uSolnVec->vector;
	Vec                     qVec            = sle->pSolnVec->vector;
	Vec                     fVec            = sle->fForceVec->vector;
	Vec                     hVec            = sle->hForceVec->vector;
	
	/* Create shortcuts to solver related stuff */
	Vec                     qTempVec        = self->pTempVec;  
	Vec                     rVec            = self->rVec;
	Vec                     sVec            = self->sVec;
	Vec                     fTempVec        = self->fTempVec;
	Vec                     vStarVec        = self->vStarVec; 
	KSP                     velSolver       = self->velSolver;	/*  Inner velocity solver */
	KSP                     pcSolver        = self->pcSolver;   /*  Preconditioner  */

	Iteration_Index         maxIterations   = self->maxUzawaIterations;
	Iteration_Index         minIterations   = self->minUzawaIterations;
	Iteration_Index         iteration_I     = 0;
	Iteration_Index         outputInterval  = 1;
	
	double                  zdotr_current	= 0.0;
	double                  zdotr_previous 	= 1.0;
	double                  sdotGTrans_v;
	double                  alpha, beta;
	double                  absResidual;  
	double                  relResidual;
	double*                 chosenResidual;	  /* We can opt to use either the absolute or relative residual in termination condition */
    	double                  uzawaRhsScale;      
	double                  divU;
	double                  weightedResidual;
	double                  weightedVelocityScale;
	double                  momentumEquationResidual;
	
	Iteration_Index         innerLoopIterations;
	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)Stokes_SLE_UzawaSolver_Type  );
	
	PetscInt		fVecSize, qTempVecSize, uVecSize, qVecSize;
	PetscScalar		fVecNorm, qTempVecNorm, uVecNorm, rVecNorm, fTempVecNorm, uVecNormInf, qVecNorm, qVecNormInf;

	double                  qGlobalProblemScale;
	double                  qReciprocalGlobalProblemScale;
	int			init_info_stream_rank;	
	PetscScalar p_sum;
	/* Bool nullsp_present; */
	Bool uzawa_summary;
	double time,t0,rnorm0;

	PetscTruth     flg;
	double        ksptime;

	VecGetSize( qTempVec, &qTempVecSize );
	qGlobalProblemScale = sqrt( (double) qTempVecSize );
	qReciprocalGlobalProblemScale = 1.0 / qGlobalProblemScale;
	init_info_stream_rank = Stream_GetPrintingRank( self->info );
	Stream_SetPrintingRank( self->info, 0 ); 

	/*	DEFINITIONS:
					See accompanying documentation
					u - the displacement / velocity solution (to which constraints are applied)
					q - the pressure-like variable which constrains the divergence displacement / velocity	(= pressure for incompressible)	
					F - standard FE force vector
					Fhat - Uzawa RHS = K^{-1} G F  - h 
					K - standard FE stiffness matrix
					Khat - Uzawa transformed stiffness matrix = G^T K^{-1} G
					G matrix - discrete gradient operator
					D matrix - discrete divergence operator = G^T for this particular algorithm
					C matrix - Mass matrix (M) for compressibility 
					
		LM & DAM			
	*/

	/* CHOICE OF RESIDUAL: 
					we may opt to converge on the absolute value (self->useAbsoluteTolerance == True ... default)
					or the relative value of the residual (self->useAbsoluteTolerance == False) 
			 		(another possibility would be always to improve the residual by a given tolerance)
					The Moresi & Solomatov (Phys Fluids, 1995) approach is to use the relative tolerance	
	*/ 

	VecNorm( fVec, NORM_2, &fVecNorm );
	VecGetSize( fVec, &fVecSize );
	if ( fVecNorm / sqrt( (double)fVecSize ) <= 1e-99 ) {
		Journal_Printf( errorStream,
			"Error in func %s: The momentum force vector \"%s\" is zero. "
			"The force vector should be non-zero either because of your chosen boundary "
			"conditions, or because of the element force vector assembly. You have %d "
			"element force vectors attached.\n",
			__func__, sle->fForceVec->name, sle->fForceVec->assembleForceVector->hooks->count );
		if ( sle->fForceVec->assembleForceVector->hooks->count > 0 ) {
			Journal_Printf( errorStream, "You used the following force vector assembly terms:\n" );
			EntryPoint_PrintConcise( sle->fForceVec->assembleForceVector, errorStream );
/* 			 TODO : need to print the elementForceVector assembly, not the global guy!! */
		}	
		Journal_Printf( errorStream,
			"Please check values for building the force vector.\n" );
		Journal_Firewall( 0, errorStream, "Exiting.\n" ); 	
	}
	
					
 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
	Journal_RPrintfL( self->debug, 2, "Conjugate Gradient Uzawa solver with:\n");
	
	Stream_IndentBranch( StgFEM_Debug );
	
	Journal_RPrintfL( self->debug, 2, "Compressibility %s\n", (sle->cStiffMat)? "on" : "off");
	Journal_RPrintfL( self->debug, 2, "Preconditioning %s\n", (pcSolver)? "on" : "off" );   
	
	
	
	if ( sle->cStiffMat ) {
		Journal_DPrintfL( self->debug, 2, "(compressibility active)\n" );
		M_Mat = sle->cStiffMat->matrix;   
	}
	else {
		Journal_DPrintfL( self->debug, 2, "(compressibility inactive)\n" );
	}
	if ( sle->dStiffMat ) {
		Journal_DPrintfL( self->debug, 2, "(asymmetric geometry: handling D Matrix [incorrectly - will be ignored])\n" );
		D_Mat = sle->dStiffMat->matrix;
	}
	else {
		Journal_DPrintfL( self->debug, 2, "(No D -> symmetric geometry: D = Gt)\n" );
	}
	
	#if DEBUG
	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
		Journal_DPrintf( self->debug, "Matrices and Vectors to solve are:\n" );
		Journal_DPrintf( self->debug, "K Matrix:\n" );
		/* No nice way of viewing Matrices, so commented out as incompatible with
		 * new 3D decomp at present --Kathleen Humble 30-04-07 
		 * Matrix_View( sle->kStiffMat->matrix, self->debug ); */
		Journal_DPrintf( self->debug, "G Matrix:\n" );
		if ( D_Mat ) {
			Journal_DPrintf( self->debug, "D Matrix:\n" );
		}	
		if ( M_Mat ) {
			Journal_DPrintf( self->debug, "M Matrix:\n" );
		}	
		Journal_DPrintf( self->debug, "Z (preconditioner) Matrix:\n" );
		Journal_DPrintf( self->debug, "f Vector:\n" );
		_SLE_VectorView( fVec, self->debug );
		Journal_DPrintf( self->debug, "h Vector:\n" );
		_SLE_VectorView( hVec, self->debug );
	}
	#endif
	
	/* STEP 1: Estimate the magnitude of the RHS for the transformed problem
			   we compute (usually to lower accuracy than elsewhere) the RHS (Fhat - h) 
	         and store the result in qTempVec.
		LM & DAM			
	*/
	
	Journal_DPrintfL( self->debug, 2, "Building Fhat - h.\n" );
	PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
	KSPSetTolerances( velSolver, self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	if (flg) {
	    ksptime = MPI_Wtime();
	}
	KSPSolve( velSolver, fVec, vStarVec );
	if (flg) {
	    ksptime = MPI_Wtime() - ksptime;
	    PetscPrintf( PETSC_COMM_WORLD,  "KSP on velSolver took %lf seconds in Building Fhat step\n", ksptime);
	}
	KSPGetIterationNumber( velSolver, &innerLoopIterations );
	
	Journal_DPrintfL( self->debug, 2, "Fhat inner solution: Number of iterations: %d\n", innerLoopIterations );
	
        if ( D_Mat ) {
          MatMult( D_Mat, vStarVec, qTempVec );
        }
        else {
          MatMultTranspose( G_Mat, vStarVec, qTempVec );
        }
	VecAXPY( qTempVec, -1.0, hVec );
	
	/*  WARNING:
			If D != G^T then the resulting \hat{K} is not likely to be symmetric, positive definite as
			required by this implementation of the Uzawa iteration.  This next piece of code
			is VERY unlikely to work properly so it's in the sin bin for the time being - LM.
			
			if ( D_Mat ) {
				MatrixMultiply( D_Mat, vStarVec, qTempVec );
			}
			else {
				MatrixTransposeMultiply( G_Mat, vStarVec, qTempVec );
			}
		LM & DAM			
	*/	

	
	/* STEP 2: The problem scaling - optionally normalize the uzawa residual by the magnitude of the RHS (use a relative tolerance)
			For the inner velocity solver,  Citcom uses a relative tolerance equal to that used for the Uzawa iteration as a whole
		LM & DAM			
	*/
	
	if (self->useAbsoluteTolerance) {
		chosenResidual = &absResidual;
		Journal_PrintfL( self->info, 2, "Absolute residual < %g for Uzawa stopping condition\n", self->tolerance);
		/* We should calculate the effective relative tolerance and insert that here !! */
		KSPSetTolerances( velSolver, 0.1 * self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	}
	else {  /* The CITCOM compatible choice */
		chosenResidual = &relResidual;
		Journal_PrintfL( self->info, 2, "Relative residual < %g for Uzawa stopping condition\n", self->tolerance);	
		KSPSetTolerances( velSolver, 0.1 * self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	}
	
	Journal_DPrintfL( self->debug, 2, "Determining scaling factor for residual:\n" );
	VecNorm( qTempVec, NORM_2, &qTempVecNorm );
	uzawaRhsScale = ((double)qTempVecNorm) * qReciprocalGlobalProblemScale;
	
	Journal_DPrintfL( self->debug, 2, "uzawaRhsScale = %f\n", uzawaRhsScale );	
	Journal_Firewall( isGoodNumber( uzawaRhsScale ), errorStream, 
			"Error in func '%s' for %s '%s' - uzawaRhsScale has illegal value '%g'.\n", __func__, self->type, self->name, uzawaRhsScale );
	
	/* STEP 3: Calculate initial residual for transformed equation  (\hat{F} - h - \hat{K} q_0)
	    Compute the solution to K u_0 = F - G q_0  (u_0 unknown)
		  Then G^T u* = \hat{F} - \hat{K} q_0 
	    u_0 is also the initial velocity solution to which the constraint is applied by the subsequent iteration
		LM & DAM			
	*/
	
	Journal_DPrintfL( self->debug, 2, "Solving for transformed Uzawa RHS.\n" );
	
	VecCopy( fVec, fTempVec );
	VecScale( fTempVec, -1.0 );
	MatMultAdd( G_Mat, qVec, fTempVec, fTempVec );
	VecScale( fTempVec, -1.0 );
	KSPSolve( velSolver, fTempVec, uVec );

	/* Handling for NON-SYMMETRIC: relegated to sin bin (see comment above) LM & DAM */
        if ( D_Mat ) {
           MatMult( D_Mat, uVec, rVec );
        }
        else {
           MatMultTranspose( G_Mat, uVec, rVec );
        }
	VecNorm( rVec, NORM_2, &rnorm0 );
	VecNorm( uVec, NORM_2, &uVecNorm );
	divU = rnorm0 / uVecNorm;
	
	Journal_PrintfL( self->info, 2, "Initial l2Norm( Div u ) / l2Norm( u ) = %f \n", divU);
	
	Journal_Firewall( isGoodNumber( divU ), errorStream, 
			"Error in func '%s' for %s '%s' - l2Norm( Div u ) has illegal value '%g'.\n",
			__func__, self->type, self->name, divU );
	
	
	Journal_DPrintfL( self->debug, 2, "Adding compressibility and prescribed divergence terms.\n" );
	
	if ( M_Mat ) {
		MatMultAdd( M_Mat, qVec, rVec, rVec );
	}	
	VecAXPY( rVec, -1.0, hVec );
			
	/* Check for existence of constant null space */
#if 0
	nullsp_present = _check_if_constant_nullsp_present( self, K_Mat,G_Mat,M_Mat, fTempVec,vStarVec,qTempVec,sVec, velSolver );
#endif
			
	/* STEP 4: Preconditioned conjugate gradient iteration loop */	
		
	Journal_DPrintfL( self->debug, 1, "Beginning main Uzawa conjugate gradient loop:\n" );	

	iteration_I = 0;

        /* outer_it, residual, time */
        uzawa_summary = self->monitor;
	time = 0.0;
	t0 = MPI_Wtime();
//	Journal_PrintfL( self->info, 1, "  |r0| = %.8e \n", rnorm0 );

	do{	
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->outeritsinitialtime = 0;
		self->outeritsendtime = 0;
		//BEGINNING OF OUTER ITERATIONS!!!!!
		/*get wall time for start of outer loop*/
		self->outeritsinitialtime = MPI_Wtime();
		
		Journal_DPrintfL( self->debug, 2, "Beginning solve '%u'.\n", iteration_I );
		Stream_IndentBranch( StgFEM_Debug );
		
		/* STEP 4.1: Preconditioner
			Solve:
				Q_\hat{K} z_1 =  r_1
				Q_\hat{K} is an approximation to \hat{K} which is simple / trivial / quick to invert
			LM & DAM			
		*/
		
		if ( pcSolver ) {
		    PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
		    if (flg) {
			ksptime = MPI_Wtime();
		    }
		    KSPSolve( pcSolver, rVec, qTempVec );
		    if (flg) {
			ksptime = MPI_Wtime() - ksptime;
			PetscPrintf( PETSC_COMM_WORLD,  "KSP on pcSolver took %lf seconds\n", ksptime);
		    }
		}
		else {
			VecCopy( rVec, qTempVec );
		}

		/* Remove the constant null space, but only if NOT compressible */
#if 0
		if( nullsp_present == True ) {
			_remove_constant_nullsp( qTempVec );
		}
#endif
				
		/* STEP 4.2: Calculate s_I, the pressure search direction
				z_{I-1} . r_{I-1}  
				\beta = (z_{I-1} . r_{I-1}) / (z_{I-2} . r_{I-2})  
					\beta = 0 for the first iteration
		      s_I = z_(I-1) + \beta * s_(I-1) 
			LM & DAM			
		*/ 
		
		VecDot( qTempVec, rVec, &zdotr_current );
	
		VecNorm( qTempVec, NORM_2, &qTempVecNorm );
		VecNorm( rVec, NORM_2, &rVecNorm );	
		Journal_DPrintfL( self->debug, 2, "l2Norm (qTempVec) %g; (rVec) %g \n", 
			qTempVecNorm * qReciprocalGlobalProblemScale,
			rVecNorm * qReciprocalGlobalProblemScale );
		
		if ( iteration_I == 0 ) {
			VecCopy( qTempVec, sVec );
		}
		else {
			beta = zdotr_current/zdotr_previous;
			VecAYPX( sVec, beta, qTempVec );
		}
		
		/* STEP 4.3: Velocity search direction corresponding to s_I is found by solving
				K u* = G s_I
			LM & DAM			
		*/
			
		MatMult( G_Mat, sVec, fTempVec );
		
		Journal_DPrintfL( self->debug, 2, "Uzawa inner iteration step\n");
		
		//START OF INNER ITERATIONS!!!!
		PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
		/*get initial wall time for inner loop*/
		self->inneritsinitialtime = MPI_Wtime();
		if (flg) {
		    ksptime = MPI_Wtime();
		}
		KSPSolve( velSolver, fTempVec, vStarVec );
		if (flg) {
		    ksptime = MPI_Wtime() - ksptime;
		    PetscPrintf( PETSC_COMM_WORLD,  "KSP on velSolver took %lf seconds in Uzawa inner iteration step\n", ksptime);
		}
		/*get end wall time for inner loop*/
		self->inneritsendtime = MPI_Wtime();
		
		/* add time to total time inner its: */
		self->totalinneritstime = self->totalinneritstime + (-self->inneritsinitialtime + self->inneritsendtime);
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->inneritsinitialtime = 0;
		self->inneritsendtime = 0;
		
		KSPGetIterationNumber( velSolver, &innerLoopIterations );
		/* add the inner loop iterations to the total inner iterations */
		self->totalnuminnerits = self->totalnuminnerits + innerLoopIterations;
		
		Journal_DPrintfL( self->debug, 2, "Completed Uzawa inner iteration in '%u' iterations \n", innerLoopIterations );
				
		/* STEP 4.4: Calculate the step size ( \alpha = z_{I-1} . r_{I-1} / (s_I . \hat{K} s_I) )
				 \hat{K} s_I = G^T u* - M s_I (u* from step 4.3) 	
			LM & DAM			
		*/ 
		
                if ( D_Mat ) {
                   MatMult( D_Mat, vStarVec, qTempVec );
                }
                else {
                   MatMultTranspose( G_Mat, vStarVec, qTempVec );
                }
		
		/* Handling for NON-SYMMETRIC: relegated to sin bin (see comment above) 
		
			if ( D_Mat ) {
				MatrixMultiply( D_Mat, vStarVec, qTempVec );
			}
			else {
				MatrixTransposeMultiply( G_Mat, vStarVec, qTempVec );
			}
			LM & DAM			
		*/

		if ( M_Mat ) {
			Journal_DPrintfL( self->debug, 2, "Correcting for Compressibility\n" );
			VecScale( qTempVec, -1.0 );
			MatMultAdd( M_Mat, sVec, qTempVec, qTempVec );
			VecScale( qTempVec, -1.0 );
		}

		VecDot( sVec, qTempVec, &sdotGTrans_v );
		
		alpha = zdotr_current/sdotGTrans_v;
		
		/* STEP 4.5: Update pressure, velocity and value of residual
				 by \alpha times corresponding search direction 
			LM & DAM			
		*/
		
		Journal_DPrintfL( self->debug, 2, "zdotr_current = %g \n", zdotr_current);
		Journal_DPrintfL( self->debug, 2, "sdotGTrans_v = %g \n", sdotGTrans_v);
		Journal_DPrintfL( self->debug, 2, "alpha = %g \n", alpha);
	
		Journal_Firewall( 
				isGoodNumber( zdotr_current ) && isGoodNumber( sdotGTrans_v ) && isGoodNumber( alpha ), 
				errorStream, 
				"Error in func '%s' for %s '%s' - zdotr_current, sdotGTrans_v or alpha has an illegal value: '%g','%g' or '%g'\n",
				__func__, self->type, self->name, zdotr_current, sdotGTrans_v, alpha );
		
		VecAXPY( qVec, alpha, sVec );
		VecAXPY( uVec, -alpha, vStarVec );
		VecAXPY( rVec, -alpha, qTempVec );
		
		/* STEP 4.6: store the value of z_{I-1} . r_{I-1} for the next iteration
		 LM & DAM
		*/
		
		zdotr_previous = zdotr_current; 
		
		VecNorm( rVec, NORM_2, &rVecNorm );
		absResidual = rVecNorm * qReciprocalGlobalProblemScale;
		relResidual = absResidual / uzawaRhsScale;
		
		Stream_UnIndentBranch( StgFEM_Debug );
		
		if( iteration_I % outputInterval == 0 ) {
			Journal_PrintfL( self->info, 2, "\tLoop = %u, absResidual = %.8e, relResidual = %.8e\n", 
				iteration_I, absResidual, relResidual );
		}
		
		Journal_Firewall( isGoodNumber( absResidual ), errorStream, 
				"Error in func '%s' for %s '%s' - absResidual has an illegal value: '%g'\n",
				__func__, self->type, self->name, absResidual );
		
		Journal_Firewall( iteration_I < maxIterations, 
				errorStream, "In func %s: Reached maximum number of iterations %u without converging; absResidual = %.5g, relResidual = %.5g \n",
				__func__, iteration_I, absResidual, relResidual );

/* 		 TODO: test for small change in 10 iterations and if so restart? */

		time = MPI_Wtime()-t0;
		if (uzawa_summary) {
                	Journal_PrintfL( self->info, 1, "  %1.4d uzawa residual norm %12.13e, cpu time %5.5e\n", iteration_I+1,*chosenResidual,time );
        	}
			
	iteration_I++;  
	//END OF OUTER ITERATION LOOP!!!
		/*get wall time for end of outer loop*/
		self->outeritsendtime = MPI_Wtime();
		/* add time to total time inner its: */
		self->totalouteritstime = self->totalouteritstime + (-self->outeritsinitialtime + self->outeritsendtime);
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->outeritsinitialtime = 0;
		self->outeritsendtime = 0;
		/* add the outer loop iterations to the total outer iterations */
		self->totalnumouterits++; 
	}  while ( (*chosenResidual > self->tolerance) || (iteration_I<minIterations) );  
//	}  while ( *chosenResidual > self->tolerance );

	Journal_DPrintfL( self->debug, 1, "Pressure solution converged. Exiting uzawa \n ");
	
	/* STEP 5:  Check all the relevant residuals and report back */
	
	if (Stream_IsEnable( self->info ) ) {
	
	/* This information should be in an info stream */
	Journal_PrintfL( self->info, 1, "Summary:\n");
	Journal_PrintfL( self->info, 1, "  Uzawa its. = %04d , Uzawa residual = %12.13e\n", iteration_I, relResidual );
	MatMultTranspose( G_Mat, uVec, rVec );
	VecNorm( rVec, NORM_2, &rVecNorm );
	VecNorm( uVec, NORM_2, &uVecNorm );
	divU = rVecNorm / uVecNorm;
	Journal_PrintfL( self->info, 1, "  |G^T u|/|u|               = %.8e\n", divU);
	
	/* Residual for the momentum equation 
		Compute r = || F - Ku - Gp || / || F ||
	*/
	
	MatMult( G_Mat, qVec, vStarVec );
	MatMultAdd( K_Mat, uVec, vStarVec, fTempVec );
	VecAYPX( fTempVec, -1.0, fVec );
	
	VecNorm( fTempVec, NORM_2, &fTempVecNorm );
	VecNorm( fVec, NORM_2, &fVecNorm );
	momentumEquationResidual = fTempVecNorm / fVecNorm;
	Journal_PrintfL( self->info, 1, "  |f - K u - G p|/|f|       = %.8e\n", momentumEquationResidual );
	Journal_Firewall( isGoodNumber( momentumEquationResidual ), errorStream, 
			"Bad residual for the momentum equation (|| F - Ku - Gp || / || F || = %g):\n"
			"\tCheck to see if forcing term is zero or nan - \n\t|| F - Ku - Gp || = %g \n\t|| F || = %g.\n", 
			momentumEquationResidual,
			fTempVecNorm, fVecNorm );
		
	/* "Preconditioned"	residual for the momentum equation 
	 		r_{w} = || Q_{K}(r) || / || Q_{K}(F)
			fTempVec contains the residual but is overwritten once used
			vStarVec is used to hold the diagonal preconditioner Q_{K} 
	*/
	
	MatGetDiagonal( K_Mat, vStarVec );
	VecReciprocal( vStarVec );
	VecPointwiseMult( vStarVec, fTempVec, fTempVec );
	VecNorm( fTempVec, NORM_2, &weightedResidual );
	VecPointwiseMult( vStarVec, fVec, fTempVec );
	VecNorm( fTempVec, NORM_2, &weightedVelocityScale );
		
	Journal_PrintfL( self->info, 1, "  |f - K u - G p|_w/|f|_w   = %.8e\n", weightedResidual / weightedVelocityScale );	
		
	/* Report back on the solution - velocity and pressure 
	 Note - correction for dof in Vrms ??
	*/

	VecNorm( uVec, NORM_INFINITY, &uVecNormInf );
	VecNorm( uVec, NORM_2, &uVecNorm );
	VecGetSize( uVec, &uVecSize );
	VecNorm( qVec, NORM_INFINITY, &qVecNormInf );
	VecNorm( qVec, NORM_2, &qVecNorm );
	VecGetSize( qVec, &qVecSize );
        Journal_PrintfL( self->info, 1, "  |u|_{\\infty} = %.8e , u_rms = %.8e\n", 
		uVecNormInf, uVecNorm / sqrt( (double)uVecSize ) );
	Journal_PrintfL( self->info, 1, "  |p|_{\\infty} = %.8e , p_rms = %.8e\n",
               	qVecNormInf, qVecNorm / sqrt( (double)qVecSize ) );

	{	PetscInt lmin,lmax;
		PetscReal min,max;
		VecMax( uVec, &lmax, &max );
		VecMin( uVec, &lmin, &min );
		Journal_PrintfL( self->info, 1, "  min/max(u) = %.8e [%d] / %.8e [%d]\n",min,lmin,max,lmax);
                VecMax( qVec, &lmax, &max );
                VecMin( qVec, &lmin, &min );
                Journal_PrintfL( self->info, 1, "  min/max(p) = %.8e [%d] / %.8e [%d]\n",min,lmin,max,lmax);
        }
	VecSum( qVec, &p_sum );
	Journal_PrintfL( self->info, 1, "  \\sum_i p_i = %.8e \n", p_sum );

	} /* journal stream enabled */

	#if DEBUG
	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
		Journal_DPrintf( self->debug, "Velocity solution:\n" );
		_SLE_VectorView( uVec, self->debug );
		Journal_DPrintf( self->debug, "Pressure solution:\n" );
		_SLE_VectorView( qVec, self->debug );
	}
	#endif
	Stream_UnIndentBranch( StgFEM_Debug );

        Stream_SetPrintingRank( self->info, init_info_stream_rank );
		/* Now gather up data for printing out to FrequentOutput file: */
	
	
	/*!!! if non-linear need to divide by number of nonlinear iterations and we do this in SystemLinearEquations */
	if((sle->isNonLinear != True)){
		self->avgnuminnerits = self->totalnuminnerits/self->totalnumouterits;
		self->avgnumouterits = self->totalnumouterits;
		self->avgtimeouterits = (self->totalouteritstime - self->totalinneritstime)/self->totalnumouterits;
		self->avgtimeinnerits = self->totalinneritstime/self->totalnuminnerits;
	}	
}
Dictionary_Entry_Value* _Stg_ComponentFactory_PluginGetDictionaryValue( void* cf, void *codelet, Dictionary_Entry_Key key, Dictionary_Entry_Value* defaultVal ) {
   Stg_ComponentFactory*       self              = (Stg_ComponentFactory*) cf;
   Stg_Component*             plugin          = (Stg_Component*)codelet;
   Dictionary*                thisPluginDict = NULL;
   Dictionary*                pluginDict     = (Dictionary*)Dictionary_Get( self->rootDict, "plugins" );
   Name                      pluginType;
   Index      pluginIndex;
   Dictionary_Entry_Value* returnVal;
   Bool                    usedDefault       = False;
   Stream*                 errorStream       = Journal_Register( Error_Type, Stg_Component_Type );
   Stream*                 stream            = self->infoStream;

   Journal_Firewall( self != NULL, errorStream, "In func %s: Stg_ComponentFactory is NULL.\n", __func__ );

   Journal_PrintfL( stream, 2, "Getting parameter '%s': ", key );

   Journal_Firewall( pluginDict != NULL, errorStream, 
         "In func %s: Stg_Component Factory's dictionary is NULL.\n", __func__ );

   /* Get this plugins Dictionary */
   for( pluginIndex = 0; pluginIndex < Dictionary_Entry_Value_GetCount( (Dictionary_Entry_Value*)pluginDict ); pluginIndex++ ) {
      thisPluginDict = Dictionary_Entry_Value_AsDictionary( Dictionary_Entry_Value_GetElement( (Dictionary_Entry_Value*)pluginDict, pluginIndex ) );
      pluginType = StG_Strdup( Dictionary_GetString( thisPluginDict, "Type" ) );
      if( !strcmp( plugin->type, pluginType ) ){
         Memory_Free( pluginType );
         break;
      }
                Memory_Free( pluginType );
   }

   /* Get this Stg_Component's Dictionary */
   Journal_Firewall( thisPluginDict != NULL, errorStream,
         "In func %s: Can't find sub-dictionary for component '%s'.\n", __func__, plugin->name );

   /* Get Value from dictionary */
   returnVal = Dictionary_Get( thisPluginDict, key );
   if ( !returnVal && defaultVal ) {
      returnVal = Dictionary_GetDefault( thisPluginDict, key, defaultVal );
      usedDefault = True;
   }

   /* Print Stuff */
   if ( usedDefault ) {
      Journal_PrintfL( stream, 2, "Using default value = " );
      if ( Stream_IsPrintableLevel( stream, 2 ) ) 
         Dictionary_Entry_Value_Print( returnVal, stream );
      Journal_PrintfL( stream, 2, "\n" );

      return returnVal;
   }
   else if ( returnVal ) {
      Journal_PrintfL( stream, 2, "Found - Value = " );
      if ( Stream_IsPrintableLevel( stream, 2 ) ) 
         Dictionary_Entry_Value_Print( returnVal, stream );
      Journal_PrintfL( stream, 2, "\n" );
   }
   else 
      Journal_PrintfL( stream, 2, "Not found.\n" );

   return returnVal;
}
void MemoryPointer_Print( MemoryPointer* memoryPointer, MemoryPointerColumn columns )
{
	Index i, j;

	/*
	 * Bit compare which flags are set in order.
	 * Print each field accordingly
	 */
	
	if ( columns & MEMORYPOINTER_ALLOCTYPE )
	{
		switch ( memoryPointer->allocType )
		{
			case MEMORY_OBJECT:
				Journal_PrintfL( stgMemory->infoStream, 2, "Object,     " );
				break;
			case MEMORY_1DARRAY:
				Journal_PrintfL( stgMemory->infoStream, 2, "1D Array,   " );
				break;
			case MEMORY_2DARRAY:
				Journal_PrintfL( stgMemory->infoStream, 2, "2D Array,   " );
				break;
			case MEMORY_3DARRAY:
				Journal_PrintfL( stgMemory->infoStream, 2, "3D Array,   " );
				break;						
			case MEMORY_4DARRAY:
				Journal_PrintfL( stgMemory->infoStream, 2, "4D Array,   " );
				break;				
			case MEMORY_2DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "2D as 1D,   " );
				break;
			case MEMORY_3DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "3D as 1D,   " );
				break;					
			case MEMORY_4DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "4D as 1D,   " );
				break;
			case MEMORY_2DCOMPLEX:
				Journal_PrintfL( stgMemory->infoStream, 2, "2D Complex, " );
				break;
			case MEMORY_3DSETUP:
				Journal_PrintfL( stgMemory->infoStream, 2, "3D Setup,   " );
				break;
			case MEMORY_3DCOMPLEX:
				Journal_PrintfL( stgMemory->infoStream, 2, "3D Complex, " );
				break;
		}
	}
	if ( columns & MEMORYPOINTER_PTR )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "(ptr)%p, ", memoryPointer->ptr );
	}
	if ( columns & MEMORYPOINTER_TYPE )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "%s, ", memoryPointer->type->value );
	}
	if ( columns & MEMORYPOINTER_NAME )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "%s, ", memoryPointer->name->value );
	}
	if ( columns & MEMORYPOINTER_FILE )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "%s, ", memoryPointer->file->value );
	}
	if ( columns & MEMORYPOINTER_FUNC )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "%s(), ", memoryPointer->func->value );
	}
	if ( columns & MEMORYPOINTER_LINE )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "Line:%d, ", memoryPointer->line );
	}
	if ( columns & MEMORYPOINTER_TOTALSIZE )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "Total:%d, ", memoryPointer->totalSize );
	}
	if ( columns & MEMORYPOINTER_ITEMSIZE )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "ItemSize:%d, ", memoryPointer->itemSize );
	}
	if ( columns & MEMORYPOINTER_LENGTH )
	{
		Journal_PrintfL( stgMemory->infoStream, 2, "Count: " );
		switch ( memoryPointer->allocType )
		{
			case MEMORY_OBJECT:
				Journal_PrintfL( stgMemory->infoStream, 2, "N/A" );
				break;
			case MEMORY_1DARRAY:
				Journal_PrintfL( stgMemory->infoStream, 2, "%d", memoryPointer->length );
				break;
			case MEMORY_2DARRAY:
			case MEMORY_2DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "%d x %d",
					memoryPointer->length.twoD[0],
					memoryPointer->length.twoD[1] );
				break;
			case MEMORY_3DARRAY:
			case MEMORY_3DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "%d x %d x %d",
					memoryPointer->length.threeD[0],
					memoryPointer->length.threeD[1],
					memoryPointer->length.threeD[2] );
				break;
			case MEMORY_4DARRAY:
			case MEMORY_4DAS1D:
				Journal_PrintfL( stgMemory->infoStream, 2, "%d x %d x %d x %d",
					memoryPointer->length.fourD[0],
					memoryPointer->length.fourD[1],
					memoryPointer->length.fourD[2],
					memoryPointer->length.fourD[3] );
				break;				
			case MEMORY_2DCOMPLEX:
			case MEMORY_3DSETUP:
				Journal_PrintfL( stgMemory->infoStream, 3, "%d by { ", memoryPointer->length.xyz.x );
				for ( i = 0; i < memoryPointer->length.xyz.x; ++i )
				{
					Journal_PrintfL( stgMemory->infoStream, 3, "%d", memoryPointer->length.xyz.y[i] );
					if ( i != memoryPointer->length.xyz.x - 1 )
					{
						Journal_PrintfL( stgMemory->infoStream, 3, ", " );
					}
				}
				Journal_PrintfL( stgMemory->infoStream, 3, " }" );
				break;
			case MEMORY_3DCOMPLEX:
				Journal_PrintfL( stgMemory->infoStream, 3, "\n" );
				for ( i = 0; i < memoryPointer->length.xyz.x; ++i )
				{
					Journal_PrintfL( stgMemory->infoStream, 3, "{ " );
					for ( j = 0; j < memoryPointer->length.xyz.y[i]; ++j )
					{
						Journal_PrintfL( stgMemory->infoStream, 3, "%d", memoryPointer->length.xyz.z[i][j] );
						if ( j != memoryPointer->length.xyz.y[i] - 1 )
						{
							Journal_PrintfL( stgMemory->infoStream, 3, ", " );
						}
					}
					Journal_PrintfL( stgMemory->infoStream, 3, " }\n" );
				}
				Journal_PrintfL( stgMemory->infoStream, 3, " }" );
				break;
		}
	}
	Journal_PrintfL( stgMemory->infoStream, 2, "\n" );

}
int main( int argc, char* argv[] ) {
    MPI_Comm CommWorld;
    int rank;
    int numProcessors;
    int procToWatch;

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

    BaseFoundation_Init( &argc, &argv );
    BaseIO_Init( &argc, &argv );

    if( argc >= 2 ) {
        procToWatch = atoi( argv[1] );
    }
    else {
        procToWatch = 0;
    }
    if( rank == procToWatch )
    {
        Stream* infoTest1;
        Stream* infoTest2;
        Stream* debugTest1;
        Stream* debugTest2;
        Stream* dumpTest1;
        Stream* dumpTest2;
        Stream* newTest1;
        Stream* newTest2;

        Stream* fileTest1;
        Stream* fileTest2;

        Stream* propTest1;
        Stream* propTest2;

        Dictionary* dictionary = Dictionary_New();
        XML_IO_Handler* io_handler = XML_IO_Handler_New();

        infoTest1 = Journal_Register( Info_Type, "test1" );
        infoTest2 = Journal_Register( Info_Type, "test2" );
        debugTest1 = Journal_Register( Debug_Type, "test1" );
        debugTest2 = Journal_Register( Debug_Type, "test2" );
        dumpTest1 = Journal_Register( Dump_Type, "test1" );
        dumpTest2 = Journal_Register( Dump_Type, "test2" );

        IO_Handler_ReadAllFromFile( io_handler, "data/journal.xml", dictionary );

        Journal_ReadFromDictionary( dictionary );

        newTest1 = Journal_Register( Info_Type, "test1.new1" );
        newTest2 = Journal_Register( Info_Type, "test1.new2" );

        Journal_Printf( infoTest1, "infoTest1\n" );
        Journal_Printf( infoTest2, "infoTest2\n" );
        Journal_Printf( debugTest1, "debugTest1\n" );
        Journal_Printf( debugTest2, "debugTest2\n" );
        Journal_Printf( dumpTest1, "dumpTest1\n" );
        Journal_Printf( dumpTest2, "dumpTest2\n" );
        Journal_PrintfL( newTest1, 3, "newTest1\n" );
        Journal_PrintfL( newTest1, 4, "newTest1\n" );
        Journal_Printf( newTest2, "newTest2\n" );

        fileTest1 = Journal_Register( "newtype", "hello" );
        fileTest2 = Journal_Register( "newtype", "other" );

        Journal_Printf( fileTest1, "yay!" );
        Journal_Printf( fileTest2, "double yay!" );

        propTest1 = Journal_Register( Info_Type, "propertiestest1" );
        propTest2 = Journal_Register( Info_Type, "propertiestest2" );

        Print( propTest1, infoTest1 );
        Print( propTest2, infoTest1 );

        Stg_Class_Delete( io_handler );
        Stg_Class_Delete( dictionary );
    }

    BaseIO_Finalise();
    BaseFoundation_Finalise();

    /* Close off MPI */
    MPI_Finalize();

    return EXIT_SUCCESS;
}